Exploring Vue data binding: why data must be a function instead of an object?

Jiangcheng Cheerful Pea: Personal homepage

Personal column :《VUE》《javaScript》

Personal website : “Jiangcheng Cheerful Pea”

The ideal of life is for an ideal life!

Table of Contents

? Column introduction

Article introduction

1. The difference between instance and component definition data

2. The difference between component data definition functions and objects

3. Principle analysis

4. Conclusion

?Write at the end


? Column Introduction

Welcome to the front-end entry journey! This column is created for readers who are interested in web development and have just started learning front-end. Whether you are a beginner or a developer with some basic knowledge, we will provide you with a systematic and friendly learning platform here. We update it in the form of questions and answers to present you with selected front-end knowledge points and best practices. By explaining concepts in simple and easy-to-understand terms and providing practical examples and exercises, you can gradually build a solid foundation. Whether it is HTML, CSS, JavaScript or the latest front-end frameworks and tools, we will provide you with rich content and practical skills to help you better understand and apply various technologies in front-end development.

At the same time, we will also pay attention to the latest front-end trends and developments. As Web technology continues to evolve, front-end development is also constantly innovating. We will introduce the latest front-end frameworks, tools and technologies in a timely manner so that you can stay at the forefront and keep pace with the times. By mastering the latest front-end technologies, you will be able to become more competitive in the highly competitive field of web development.

Article introduction

1. The difference between instance and component definition data

When defining an instance of vue, the data attribute can be either an object or a function.

const app = new Vue({
    el:"#app",
    // Object format
    data:{
        foo:"foo"
    },
    // function format
    data(){
        return {
             foo:"foo"
        }
    }
})

The data attribute defined in the component can only be a function

If the component data is directly defined as an object

Vue.component('component1',{
    template:`<div>Component</div>`,
    data:{
        foo:"foo"
    }
})

You will get a warning message

image.png

Warning: The returned data should be a function in each component instance

2. The difference between component data definition functions and objects

As mentioned above, the component data must be a function. I wonder if you have ever thought about why this is?

When we define a component, vue will eventually form a component instance through Vue.extend()

Here we imitate the component constructor and define the data attribute in the form of an object

function Component(){
 
}
Component.prototype.data = {
count: 0
}

Create two component instances

const componentA = new Component()
const componentB = new Component()

Modify the value of the data attribute of the componentA component, and the value in componentB has also changed.

console.log(componentB.data.count) // 0
componentA.data.count = 1
console.log(componentB.data.count) // 1

The reason for this is that the two share the same memory address, and the content modified by componentA also affects componentB

If we adopt the form of a function, this situation will not occur (the memory address of the object returned by the function is not the same)

function Component(){
this.data = this.data()
}
Component.prototype.data = function (){
    return {
   count: 0
    }
}

Modify the value of the data attribute of the componentA component. The value in componentB will not be affected.

console.log(componentB.data.count) // 0
componentA.data.count = 1
console.log(componentB.data.count) // 0

The vue component may have many instances, and the function returns a new data form so that the data of each instance object will not be contaminated by the data of other instance objects.

3. Principle Analysis

First, you can take a look at the code for vue to initialize data. The definition of data can be a function or an object.

Source code location: /vue-dev/src/core/instance/state.js

function initData (vm: Component) {
  let data = vm.$options.data
  data = vm._data = typeof data === 'function'
    ? getData(data, vm)
    : data || {}
    ...
}

data can be both object and function, so why does the above warning appear?

Don’t worry, continue reading below

When the component is created, options will be merged

Source code location: /vue-dev/src/core/util/options.js

Custom components will enter mergeOptions for option merging

Vue.prototype._init = function (options?: Object) {
    ...
    // merge options
    if (options & amp; & amp; options._isComponent) {
      // optimize internal component instantiation
      // since dynamic options merging is pretty slow, and none of the
      // internal component options needs special treatment.
      initInternalComponent(vm, options)
    } else {
      vm.$options = mergeOptions(
        resolveConstructorOptions(vm.constructor),
        options || {},
        vm
      )
    }
    ...
  }

Defining data will perform data verification

Source code location: /vue-dev/src/core/instance/init.js

At this time, the vm instance is undefined, and enters the if judgment. If the data type is not function, a warning message will appear

strats.data = function (
  parentVal: any,
  childVal: any,
  vm?: Component
): ?Function {
  if (!vm) {
    if (childVal & amp; & amp; typeof childVal !== "function") {
      process.env.NODE_ENV !== "production" & amp; & amp;
        warn(
          'The "data" option should be a function ' +
            "that returns a per-instance value in component " +
            "definitions.",
          vm
        );

      return parentVal;
    }
    return mergeDataOrFn(parentVal, childVal);
  }
  return mergeDataOrFn(parentVal, childVal, vm);
};

Four. Conclusion

  • The root instance object data can be an object or a function (the root instance is a singleton), which will not cause data pollution.
  • The component instance object data must be a function. The purpose is to prevent multiple component instance objects from sharing a data and causing data pollution. In the form of a function, it will be used as a factory function when initData will return a new data object.

? Write at the end

Please feel free to give me some advice, comment below or send me a private message. Thank you very much.

? I think a certain part of my design is too cumbersome. Is there a simpler or higher-quality packaging method?

? Think some of my code is too old and can provide new API or the latest syntax?

? Don’t understand some of the content in the article

?Answer some questions in my article

? Think that some interactions and functions need to be optimized, and find bugs

? Want to add new features and have better suggestions for the overall design and appearance?

Finally, thank you for your patience in watching. Now that we are here, click Like and go!

The knowledge points of the article match the official knowledge files, and you can further learn relevant knowledge. Vue entry skill treeHomepageOverview 39842 people are learning the system