最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 你知道Vue中的computed源码! ! !

    正文概述 掘金(诺颜)   2021-03-30   571

    前言


    今天来研究下Vue中的 Computed源码过程,学习computed我们必须理解一下几点:


    我们知道vue调用实例后,Vue内部initState时候,会处理很多不同的数据,包括有data、props、methods....

    处理computed的方法就是initComputed。 看看initComputed做了些啥!

    function initComputed(vm, computed) {
        var watchers = vm._computedWatchers = Object.create(null);
        // 是否服务器渲染 
        var isSSR = isServerRendering();
        for (var key in computed) {
          var userDef = computed[key];
          var getter = typeof userDef === 'function' ? userDef : userDef.get;
          if (getter == null) {
            warn(
              ("Getter is missing for computed property \"" + key + "\"."),
              vm
            );
          }
          if (!isSSR) {
            // create internal watcher for the computed property.
            watchers[key] = new Watcher(
              vm,
              getter || noop,
              noop,
              computedWatcherOptions
            );
          }
          if (!(key in vm)) {
            defineComputed(vm, key, userDef);
          }
        }
      }
    

    上面做了几件事1.为每个computed中的属性添加 watcher。2.defineComputed的处理

    1.new Watcher生成一个computed-Watcher

    先来看下new Watcher()做了些啥,先列出重点的源码

    function Watcher(vm, expOrFn, options) {    
        this.dirty = this.lazy = options.lazy;    
        this.getter = expOrFn;   
        this.value = this.lazy ? undefined: this.get();
    };
    
    // getter 就是 watcher 回调
    Watcher.prototype.get = function() {  
        var value = this.getter.call(vm, vm);    
        return value
    };
    
    

    一开始new Watcher(vm, getter, { lazy: true })lazy是设为true,这样在执行computed中属性初始化的时候,不用立马求值,算是一个小优化吧!只有等到后面再次请求computed中的值才会进行this.get();

    2.再看看defineComputed做了一些什么鬼!

    function defineComputed(
        target, key, userDef
    ) {    
        // 设置 set 为默认值,避免 computed 并没有设置 set
        var set = function(){}      
        
        //  如果用户设置了set,就使用用户的set
        Object.defineProperty(target, key, {        
            // 包装get 函数,主要用于判断计算缓存结果是否有效
            get:createComputedGetter(key),        
            set:set
        });
    }
    

    其实就是给computed中的每一个属性都进行依赖拦截处理,看下get中重点createComputedGetter。

    function createComputedGetter(key) {    
        return function() {        
            // 获取到相应 key 的 computed-watcher
            var watcher = this._computedWatchers[key];        
            // 如果 computed 依赖的数据变化,dirty 会变成true,从而重新计算,然后更新缓存值 watcher.value
            if (watcher.dirty) {
                watcher.evaluate();
            }        
            // 这里后面重点讲,主要是建立联系
            if (Dep.target) {
                watcher.depend();
            }        
            return watcher.value
    }
    
    Watcher.prototype.evaluate = function() {    
        this.value = this.get();    
        this.dirty = false;
    };
    

    看到上面的watcher.dirty了吗,就是这个,当你dirty为true时才会执行内部的watcher.evaluate(),执行之后又会进行this.dirty进行设为false,这样就不用每一次都进行重新求值,起到了真正缓存的作用,那什么时候才要进行设为dirty为true呢,就是比如说当computed依赖的响应数据进行变化的时候,会触发它依赖收集中的computed-watcher,之后进行update。看下面简单源码

    Watcher.prototype.update = function() {    
        if (this.lazy)  this.dirty = true;
        ....还有其他无关操作,已被省略
    };
    

    这样在你只要重新获取computed中的属性值就会执行get,从而执行watcher.evaluate()。

    重点是上面的watcher的depend(),后续再讲!累了


    起源地下载网 » 你知道Vue中的computed源码! ! !

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元