美文网首页
使用data()设计避免数据共享问题

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

作者: 彼小星星空下看星星 | 来源:发表于2018-08-31 15:33 被阅读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>
    
    • 方式一是怎么处理data的?

    源码位于global-api/extend.js

    extend.png

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

    • 方式二怎么处理data的?

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

    component.png

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

    • 使用时怎么处理data的?

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

    • 那么new过程data是怎么样的呢?

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


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

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


    相关文章

      网友评论

          本文标题:使用data()设计避免数据共享问题

          本文链接:https://www.haomeiwen.com/subject/puoswftx.html