There are two methods for Vue to initialize data: 1. Object mode, syntax "var data = {key-value pair}"; 2. Function mode, syntax "data: function () {return { key-value pair}" }". It should be noted that the data initialization in components and extend cannot be Object, otherwise an error will be reported. The purpose of using function mode for data in components is to prevent multiple component instance objects from sharing the same data and causing data pollution.
The operating environment of this tutorial: windows7 system, vue3 version, DELL G3 computer.
Vue data has two initialization methods, function and object, but what are the applicable scenarios for these two situations? Can it be universal? With these two questions, let’s analyze them together
data initialization
// 代码来源于官网示例 // 第一种定义方式 var data = { a: 1 } // 直接创建一个实例 var vm = new Vue({ data: data }) // Vue.extend() 中 data 必须是函数 var Component = Vue.extend({ // 第二种定义方式 data: function () { return { a: 1 } } })
The above code briefly describes the two ways of defining data
function
object
The official website demo also emphasizes that object cannot be used for data initialization in extend. . So why?
Source code analysis
According to the official website demo, the data initialization in Vue.extend cannot be Object. What will happen if we force it to be written as Object?
var Component = Vue.extend({ data: { a: 1 } })
After running, chrome's console directly reports an error, the information is as follows
vue.esm.js?efeb:591 [Vue warn]: The "data" option should be a function that returns a per-instance value in component definitions.
By analyzing the source code and error information, when Vue.extend is triggered, it will perform a merge operation and merge a basic component (Inside vmode, transition, etc.) and the information you defined in extend are merged into options through mergeField. When merged into data, it will trigger strats.data, which will check whether data is a function, which is required here. Note that filters, components, etc. and data go through two sets of merge processes. Please see the code comments for details, as follows
// vue.extend 源码地址https://github.com/vuejs/vue/blob/dev/src/core/global-api/extend.js Vue.extend = function (extendOptions: Object): Function { ... // 在这里会触发mergeOptions方法 Sub.options = mergeOptions( Super.options, extendOptions ) ... } // mergeOptions 源码地址https://github.com/vuejs/vue/blob/dev/src/core/util/options.js export function mergeOptions ( parent: Object, child: Object, vm?: Component ): Object { ... const options = {} let key // parent对象内包含components、filter,、directive for (key in parent) { mergeField(key) } // child对象内对应的是Vue.extend内定义的参数 for (key in child) { if (!hasOwn(parent, key)) { mergeField(key) } } function mergeField (key) { // 这一步是根据传入的key找到不同的合并策略filter、components、directives用到合并策略是这个方法mergeAssets和data用到的不一样,当合并到data的时候会进入专属的合并策略方法内 const strat = strats[key] || defaultStrat options[key] = strat(parent[key], child[key], vm, key) } } // strats.data 源码地址https://github.com/vuejs/vue/blob/dev/src/core/util/options.js strats.data = function ( parentVal, childVal, vm ) { if (!vm) { // 如果data不是function的话会直接走下面的报错信息 if (childVal && typeof childVal !== 'function') { process.env.NODE_ENV !== 'production' && 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) };
Other situations
In fact, our above code is just a simple process. In actual development, similar situations include: data cannot be defined as an object in subcomponents and routes, because they all call the mergeOptions method at the bottom
When can it be defined as an object
When vue is initialized, as follows
new Vue({ data: { linke: '//sinker.club' } })
Meaning
Okay, so much has been said above, so what is the significance of doing this? Why can't those situations be defined as objects? In fact, to answer this question, we need to go back to js itself. As we all know, js data types are divided into reference and basic. Reference types include Object, Array, and Function. What is a reference type will not be explained here.
var obj = {link: '//www.sinker.club'} var obj2 = obj var obj3 = obj obj2.link = "//gitlab.sinker.club" console.log(obj3.link) // "//gitlab.sinker.club"
The above code reflects One problem is that since obj3 and obj2 both point to an address in memory, the modification of obj2 will affect obj3. Of course, deep copy can be used to deal with this problem.
JSON .parse(JSON.stringify(obj))
deepClone(obj)
But these two methods require development or framework every time A deep copy is required. When the amount of data is large, it is not good for performance. So how does Vue do it? Define data as a function
function data() { return { link: '//sinker.club' } } var obj = test() var obj2 = test() obj2.link ="//gitlab.sinker.club" console.log(obj.link) '//sinker.club'
Why do you do this? What is the solution scenario?
For example, if I define a subcomponent, the data is defined as an object. This component is referenced in multiple places. If one of the data referencing this component is modified, then it will Cause other data referencing this component to change at the same time, end.
Extended knowledge:
When defining a vue instance, the data attribute can be either a The object can also be a function
const app = new Vue({ el:"#app", // 对象格式 data:{ foo:"foo" }, // 函数格式 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>组件</div>`, data:{ foo:"foo" }})
you will get Warning message
Description:
Components in vue are used for reuse. In order to prevent data To reuse, define it as a function.
The data data in the vue component should be isolated from each other and not affect each other. Every time the component is reused, the data data should be copied once. After that, when a certain place is reused When the data data in the used local component is changed, the data data of other reused local components will not be affected, so you need to return an object as the status of the component through the data function.
When we write the data in the component as a function, the data is defined in the form of function return value, so that every time the component is reused, a new data will be returned, with its own Scope is similar to creating a private data space for each component instance, allowing each component instance to maintain its own data.
When the date of our component is simply written in object form, these instances use the same constructor. Due to the characteristics of JavaScript, all component instances share one data, so It will lead to a result that changes everything.
[Related recommendations: vuejs video tutorial, web front-end development]
The above is the detailed content of What are the methods for initializing data in Vue?. For more information, please follow other related articles on the PHP Chinese website!