使用data()设计避免数据共享问题

2018-08-31  本文已影响0人  彼小星星空下看星星

vue中data为啥要用函数

理解为啥使用函数不直接使用对象的方式,简单一句话。直接对象会造成同一对象共享问题。

为什么会造成共享问题?

细探源码,下面从组件的三个过程看看整个过程。
组件的三个过程

  1. 创建
  2. 注册
  3. 实例化
    下面这篇文章对VUE源码有比较清晰的认识https://blog.csdn.net/yolo0927/article/details/78242989
组件是如何使用的?
// 方式一
var MyComponent = Vue.extend({
    name: 'my-component',
    template: '<div>{{name}}</div>',
    data(){
        return{
            name:""
        }
    }
});
Vue.component('my-component', MyComponent);
 
// 方式二
Vue.component('my-component', {
    name: 'my-component',
    template: '<div>{{name}}</div>',
    data(){
        return{
            name:""
        }
    }
});

// 使用组件
<div id="example">
    <my-component></my-component>
</div>

源码位于global-api/extend.js

extend.png

这里传入的参数extendOptions和Super.options都一并合并放入的Sub.options,并通过this._init将原型上的options也并入Sub.options.extend最后返回的是这个构造函数Sub;

具体如何定位到component源码的可以参考这篇文章的分析
https://segmentfault.com/a/1190000012004707

component.png

从上面可以看出,component做的处理就是注册这个创建的组件,如果传入的第二个参数是一个对象,则会进行一次创建操作,其实也就是内部也会执行一下extend操作,然后在注册。这里没有涉及到data的操作,也没有实例化这个组件。这里的这个definition对象是一个Sub构造函数。

使用是组件实例化并完成了挂载过程。组件实例化也就是new一个构造函数实例化,挂载也就是将组件指定到HTML元素中输出。new Sub则会实例化创建的这个组件。

new内部会创建一个新的空对象,然后将这个对象的原型指向这个构造函数的原型,并复制构造函数的属性,然后返回这个新的对象。如下:

function myNew(constructor){
    return function(){
        let obj={};
        obj.__proto__=constructor.prototype;
        constructor.apply(obj, arguments);
        return obj;
    }
}

所以Sub.options是构造函数的属性,最后会通过constructor.apply(obj, arguments);变成实例化对象的属性。

一般的构造函数实例化,属性被共享的情况
function initData(data){
    return typeof data==='function'?data():data;
}
function Sub(data){
    this.data=initData(data);
}
let data={
    name:'mzz'
}
let dataFn=function(){
    return{
        name:'mzz'
    }
}
let obj1=new Sub(data),
    obj2=new Sub(data);
console.log(obj1.data===obj2.data);   //true
let obj3=new Sub(dataFn),
    obj4=new Sub(dataFn);
console.log(obj3.data===obj4.data);  //false

上面这个一般化类实例对象结果对象属性被所有实例对象共享,VUE采取data()而不是直接对象也是这个道理。

总结

js中对象的引用造成数据被共享问题比较常见,可以学习这里传函数形式避免构造函数的对象属性被实力对象共享。大家都知道的原型继承原型会被所有实例对象共享,无论在原型上的属性是对象还是一般数据类型,通过这里的学习,也可以看到实例对象还会共享构造函数的对象类型属性。


以上仅作为个人学习参考,如有错误望批评指正;

如果有小伙伴再继续深入,有新见解的,望赐教。


上一篇下一篇

猜你喜欢

热点阅读