Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue props: Should I pass the object or its properties? Does it make much difference?

Lets say my application is a cut-down spreadsheet built in Vue. The key components are TableCollection, Table, Row and Field. The TableCollection has an array with multiple Table objects. Each Table has an array with multiple Row objects. Each Row has an array with multiple Field objects.

When using the row component in the table template I could bind a single row property (:row="row"), or I could bind a separate property for each column (:col1="col1" :col2="col2" :col3="col3"). Which is the preferred approach, and why?

Passing a single property is less verbose, but referring to it from within the row component is more verbose, so they (roughly) cancel each other out. One advantage of the single property is that I could then add a Field dynamically by pushing to the array.

Are there other factors to consider? For example, does it affect the getters and setters generated by Vue?

like image 957
DatsunBing Avatar asked Apr 10 '18 08:04

DatsunBing


Video Answer


1 Answers

After re-reading the documentation and doing some tests, I found that there is an important difference between passing the props as an object versus object properties.

This page makes is clear that either is OK, https://vuejs.org/v2/guide/components-props.html#Passing-an-Object

If you pass the object however, then any changes you make in the component will be reflected in the parent too. This makes sense, per the comment at the bottom of this section, https://vuejs.org/v2/guide/components-props.html#One-Way-Data-Flow

It reads:

Note that objects and arrays in JavaScript are passed by reference, so if the prop is an array or object, mutating the object or array itself inside the child component will affect parent state.

To prove this, you put the following code in a html page:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue Test</title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="app"></div>

<script>

    Vue.component('propTest', {
        props : ['scalar', 'object', 'other'],
        template: `<div>Scalar is <input type="text" v-model="scalar"><br>
                        Object field 1 is <input type="text" v-model="object.field1"><br>
                        Object field 2 is <input type="text" v-model="other"></div>`
    });

    var app = new Vue({
        el: '#app',
        data: {
            scalarVal : 'SCALAR',
            objectVal : {
                field1 : 'FIELD ONE',
                field2 : 'FIELD TWO'
            }
        },
        template : '<div><prop-test :scalar="scalarVal" :object="objectVal" :other="objectVal.field2"></prop-test></div>'
    })

</script>
</body>
</html>

As you can see, it three props are passed to the child: a scalar value, an object, and an object property which is a scalar value. They all have two-way bindings in the child per v-model.

Update the three values on the web page then check your Vue dev tools to see that:

  • The scalar is updated in the child, but not the root
  • When an object is passed, and a field is updated, it is reflected in both child and root
  • When the object field is passed as its own separate prop, the update shows in the child but not the root
like image 143
DatsunBing Avatar answered Sep 30 '22 18:09

DatsunBing