美文网首页
简单的看一下computed

简单的看一下computed

作者: HelenYin | 来源:发表于2021-03-20 19:32 被阅读0次

    先看看computed的用法

    var vm = new Vue({
      data: {
        firstName: 'Foo',
        lastName: 'Bar'
      },
      computed: {
        fullName: function () {
          return this.firstName + ' ' + this.lastName
        }
      }
    })
    

    这里我只考虑计算属性是function的情况,还有一种get,set的我暂时不考虑。
    被设置为computed的这个值fullName,依赖两个变量:this. firstNamethis.lastName。这两个变量有其中一个变化,那么fullName就随之改变。
    这很容易就联想到,当我们一个被响应式监听的data变量被赋值后,notify,然后更新依赖这个data变量的watcher。那么这里的computed也是这个原理,我们把每个在computed里声明过得方法,放到watcher里,每当有notify,那么就更新watcher。

    export function initState (vm) {
    + const { data, props, computed } = vm.$options;
      props && initProps(vm, props);
      data && initData(vm);
    + computed && initComputed(vm, computed);
    }
    
    function initComputed (vm, computed) {
      for (const key in computed) {
        const getter = computed[key];
        new Watcher(vm, getter);
      }
    }
    

    当我们在访问计算属性的时候需要返回相应的值

    function initComputed (vm, computed) {
      for (const key in computed) {
        const getter = computed[key];
        new Watcher(vm, getter);
    +    if (!(key in vm)) {
    +      defineComputed(vm, key, getter);
    +    } else {
    +      console.warn('计算属性与与data中的属性命名冲突');
    +    }
      }
    }
    
    function defineComputed (vm, key, get) {
      Object.defineProperty(vm, key, { get });
    }
    

    验证一下:

    export const Hello = {
      name: 'Hello',
      data() {
        return {
          firstName: 'Foo',
          lastName: 'Bar',
        }
      },
      computed: {
        fullName: function () {
          return `${this.firstName} ${this.lastName}`;
        },
      },
      mounted() {
        setTimeout(() => {
          this.firstName = 'helen';
        }, 1000);
      },
      render: function(h) {
        return h('div', {}, this.fullName);
      },
    }
    

    现在看来好像没啥问题
    但是渲染watcher和computedwatcher有点差异
    渲染watcher因为需要直接执行render函数,所以需要立即执行,computed在new Watcher的时候其实不需要直接执行,在真实执行渲染Watcher的时候会触发getter函数,这个时候的computed属性收集的依赖是渲染watcher,在执行computed的函数时,会触发data里的变量的getter函数,这个时候,data里变量收集的依赖就是computed watcher。
    这里给watcher多加一个option,用来让watcher 知道是computed watcher还是渲染 watcher

    function initComputed (vm, computed) {
      for (const key in computed) {
        const getter = computed[key];
    +   const computedWatcherOptions = { lazy: true };
        new Watcher(vm, getter, computedWatcherOptions);
        if (!(key in vm)) {
          defineComputed(vm, key, getter);
        } else {
          console.warn('计算属性与与data中的属性命名冲突');
        }
      }
    }
    
    class Watcher {
      constructor (
        vm, 
        exp, 
    +   options) {
      if (options.lazy) {
        // 这里暂时这样写
        console.log('========');
      } else {
        this.get()
      }
      }
    }
    

    官网上说

    我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这就意味着只要 message 还没有发生改变,多次访问 reversedMessage 计算属性会立即返回之前的计算结果,而不必再次执行函数。

    好像没啥问题
    https://github.com/TingYinHelen/tempo/src/instance/state.js

    相关文章

      网友评论

          本文标题:简单的看一下computed

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