前言在使用Vue开发的过程中,数据选项是我们最为熟悉的。一般来说,我们的数据一般都是用函数的形式写的,通过return返回数据,但是当官方demo用根实例写的时候,发现他直接用了对象的形式。既然这样,把这个写在组件里岂不是更清爽方便?试了一下,发现如下提示:使用我渣英文翻译的,“data”选项应该是一个函数,并返回组件定义中每个实例的值。emmmmm,“数据”选项应该是一个函数???那为什么可以在根实例中使用数据对象,而不能在组件中使用呢?我们来分析一下为什么要这样做,再看看源码层面,Vue.js中做了什么。vue根实例中数据的使用可以是函数,当可以是对象vue的实例时,会调用一个init方法functionVue(options){if(process.env.NODE_ENV!=='production'&&!(thisinstanceofVue)){warn('Vue是一个构造函数,应该使用`new`关键字调用')}this._init(options)}这个init方法会传入我们的选项并做一系列的初始化,包括数据初始化,有兴趣的同学可以去vue源码的src/core/instance/init.js一探究竟。话不多说,让我们继续看下去。在初始化数据的时候,我们可以找到实例的处理//initData的时候,会先判断数据的类型,在根实例中,不管是对象还是函数类型,都会解析letdata=vm.$options.datadata=vm._data=typeofdata==='函数'?getData(数据,虚拟机):数据||{}Vue组件中数据的使用只能是函数。其实在初始化数据之前,Vue会先Mergeoptionsvm.$options=mergeOptions(resolveConstructorOptions(vm.constructor),options||{},vm)mergeOptions合并策略中有一节会判断是否是一个根实例或组件,并进行处理strats.data=function(parentVal:any,childVal:any,vm?:Component):?Function{if(!vm){if(childVal&&typeofchildVal!=='function'){process.env.NODE_ENV!=='production'&&warn('“数据”选项应该是一个函数'+',它返回组件'+'定义中的每个实例值。',vm)returnparentVal}returnmergeDataOrFn(parentVal,childVal)}returnmergeDataOrFn(parentVal,childVal,vm)}from从上面的源码可以看出,如果当前实例判断为!vm,是普通组件,如果选择item类型不是function,会报错,也就是刚才图片看到的,data选项应该是functionconclusion通过上面的代码,我们可以看出Vue是如何进行处理的。所以我们可以分析一下Vue的设计目的。在一个项目中,可以有多个组件,每个组件都可以看作是一个构造函数。注册组件的本质其实就是构造函数的引用。如果直接使用对象,它们的内存地址是一样的,改变一个数据,其他的也跟着改变,造成数据污染。如果使用函数,就会形成一个新的作用域,这样data中的数据就不会相互影响了。以避免数据污染。但由于根实例只有一个,不存在数据污染,可以使用对象。例子为了验证上面的结论,我们从原型链入手,写了一个简单的例子。constMyComponents=function(){};MyComponents.prototype.data={number:1};让component1=newMyComponents();让component2=newMyComponents();component1.data.number=2console.log(component1.data.number,'component1-data')//2console.log(component2.data.number,'component2-data')//2写在上一个Vue有很多值得我们讨论和关注的细节,通过阅读源码我们可以得到最确定准确的答案。后面会分享自己在学习源码过程中的一些心得和知识。如有不妥之处,希望大家指出,共同学习,共同进步。克服恐惧最好的方法就是面对它,加油,奥利!!!
