美文网首页
使用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()设计避免数据共享问题

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

  • java中synchronized的底层实现

    在java中如果使用了多线程对共享数据进行操作,那无可避免会遇到同步问题。为解决此问题可以使用synchroniz...

  • 数据共享

    容器与host共享数据 容器之间共享数据 volume container data-packed volume ...

  • 线程封闭与不变性 Java并发编程实战总结

    当访问共享的可变数据时, 通常需要使用同步。一种避免使用同步的方式就是不共享数据。如果仅在单线程内访问数据, 就不...

  • 高性能编程

    ## 重点 1、线程安全概念 线程安全来自于竞争,核心思路避免共享数据结构、共享状态,使用线程local变量、使用...

  • Build Apps with Content Sharing

    如何创建apps与设备之间共享数据的app. Sharing Simple Data 使用Intent和Actio...

  • Java线程封闭

    线程封闭 多线程中不需要使用共享数据,使用数据封闭避免使用同步的技术 线程封闭的具体实现:ThreadLocal、...

  • DAO设计模式

    DAO(Data Access Objects)设计模式属于JavaEE数据层的操作。 使用DAO设计模式可以简化...

  • 线程封闭

    线程封闭 当访问共享的可变数据时,通常需要使用同步。一种避免使用同步的方式就是不共享数据。如果仅在单线程内访问数据...

  • Redis在Spring-data-session共享中存在的问

    SASS Redis在Spring-data-session共享中存在的问题 公司使用网易云Redis服务,使用s...

网友评论

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

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