站长资讯网
最全最丰富的资讯网站

vue初始化data方法有哪些

vue初始化data方法有两种:1、object方式,语法“var data = { 键值对 }”;2、function方式,语法“data: function () {return { 键值对 }}”。需要注意组件和extend中的data初始化不能是Object,否则会报错。组件中data用function方式是为了防止多个组件实例对象之间共用一个data,产生数据污染。

vue初始化data方法有哪些

本教程操作环境:windows7系统、vue3版,DELL G3电脑。

vue data有两种初始化的方式,function和object,但是这两种情况适用场景有哪些?能不能通用?带着这两个问题咱们一起分析下

data初始化

// 代码来源于官网示例  // 第一种定义方式 var data = { a: 1 }  // 直接创建一个实例 var vm = new Vue({   data: data })  // Vue.extend() 中 data 必须是函数 var Component = Vue.extend({ // 第二种定义方式   data: function () {     return { a: 1 }   } })
登录后复制

上述代码简单描述了data定义的两种方式

  • function

  • object

官网demo中也着重说了extend中data初始化不能用object。那么为什么呢?

源码分析

按照官网demo,Vue.extend中的data初始化不能是Object,如果我们强制写成Object会出现什么?

var Component = Vue.extend({   data: { a: 1 } })
登录后复制

运行以后chrome的consolo直接报错,信息如下

vue.esm.js?efeb:591 [Vue warn]: The "data" option should be a function that returns a per-instance value in component definitions.
登录后复制

通过分析源码以及报错信息,当触发Vue.extend的时候,他会做一个合并操作,把一个基础组件(里面vmode, transtion等)和你定义在extend内的信息,通过mergeField往options上合并,当合并到data的时候,他会触发strats.data,在这个里面会check data是不是一个function,这里需要注意的是filter、components等和data走的是两套合并流程,详细的请看代码注释,如下

// 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) };
登录后复制

其他情况

其实我们上述代码只是一个简单的流程,在实际开发中同类情况有:子组件内、路由内都不可以把data定义为一个对象,因为他们底层都调用了mergeOptions方法

什么时候可以定义成一个对象

在vue初始化的时候,如下

new Vue({   data: {     linke: '//sinker.club'   } })
登录后复制

意义

ok,上面说了那么多,那么这么做的意义是什么?为什么那几种情况不可以定义为对象? 其实回答这个问题,需要回到js本身,众所周知js数据类型分为引用和基本,引用类型包含Object, Array, Function,何为引用类型就不在这里阐述了

  var obj = {link: '//www.sinker.club'}   var obj2 = obj   var obj3 = obj   obj2.link = "//gitlab.sinker.club"   console.log(obj3.link) // "//gitlab.sinker.club"
登录后复制

上述代码反应了一个问题,由于obj3和obj2在内存中都是指向一个地址,那么obj2的修改会影响到obj3,当然处理这种问题可以用深copy来做到

  • JSON.parse(JSON.stringify(obj))

  • deepClone(obj)

但是这两种做法需要开发或者框架每一次都要深copy一次,当数据量大的时候对性能什么都不友好,那么Vue怎么做的呢?把data定义成一个function

function data() {   return {    link: '//sinker.club'   } }  var obj = test() var obj2 = test()  obj2.link ="//gitlab.sinker.club" console.log(obj.link) '//sinker.club'
登录后复制

为什么这么做?解决的场景是什么呢?

比如我定一个子组件,data是按照对象的方式定义的,这个组件在多个地方引用,如果其中一个引用此组件的data修改了,那么就会造成其余引用此组件的data同时改变, end.

扩展知识:

vue实例的时候定义data属性既可以是一个对象,也可以是一个函数

const app = new Vue({     el:"#app",     // 对象格式     data:{         foo:"foo"     },     // 函数格式     data(){         return {              foo:"foo"         }     } })
登录后复制

组件中定义data属性,只能是一个函数

如果为组件data直接定义为一个对象

Vue.component('component1',{     template:`<div>组件</div>`,     data:{         foo:"foo"     }})
登录后复制

则会得到警告信息

vue初始化data方法有哪些

说明:

  • vue中组件是用来复用的,为了防止data复用,将其定义为函数。

  • vue组件中的data数据都应该是相互隔离,互不影响的,组件每复用一次,data数据就应该被复制一次,之后,当某一处复用的地方组件内data数据被改变时,其他复用地方组件的data数据不受影响,就需要通过data函数返回一个对象作为组件的状态。

  • 当我们将组件中的data写成一个函数,数据以函数返回值形式定义,这样每复用一次组件,就会返回一份新的data,拥有自己的作用域,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据。

  • 当我们组件的date单纯的写成对象形式,这些实例用的是同一个构造函数,由于JavaScript的特性所导致,所有的组件实例共用了一个data,就会造成一个变了全都会变的结果。

赞(0)
分享到: 更多 (0)