zoukankan      html  css  js  c++  java
  • vue computed 源码分析

    我们来看看computed的实现。最简单的一个demo如下:

    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    </head>
    <body>
    <div id="app">
      <div name="test">{{computeA}}</div>
    
    </div>
    </body>
    <script src="vue.js"></script>
    <script type="text/javascript">
      new Vue({
      el: '#app',
      data: function () {
        return {
          firstName: 111,
          lastName: 222
        }
      },
      computed: {
        computeA: function () {
          return this.firstName + ' ' + this.lastName
        }
      },
      created(){
        setTimeout(
          () => {
            this.firstName = 333;
          },1000
        )
      }
    })
    </script>
    </html>
    

      

    1在初始化实例创建响应式的时候。对options中的computed做了特殊处理:

    function initComputed (vm, computed) {
      var watchers = vm._computedWatchers = Object.create(null);
    
      for (var key in computed) {
        var userDef = computed[key];
        var getter = typeof userDef === 'function' ? userDef : userDef.get;
        {
          if (getter === undefined) {
            warn(
              ("No getter function has been defined for computed property "" + key + ""."),
              vm
            );
            getter = noop;
          }
        }
        // create internal watcher for the computed property.
        watchers[key] = new Watcher(vm, getter, noop, computedWatcherOptions);//为每一个computed项目订制一个watcher
    
        // component-defined computed properties are already defined on the
        // component prototype. We only need to define computed properties defined
        // at instantiation here.
        if (!(key in vm)) {
          defineComputed(vm, key, userDef);
        } else {
          if (key in vm.$data) {
            warn(("The computed property "" + key + "" is already defined in data."), vm);
          } else if (vm.$options.props && key in vm.$options.props) {
            warn(("The computed property "" + key + "" is already defined as a prop."), vm);
          }
        }
      
    
    function defineComputed (target, key, userDef) {
      if (typeof userDef === 'function') {
        sharedPropertyDefinition.get = createComputedGetter(key);
        sharedPropertyDefinition.set = noop;
      } else {
        sharedPropertyDefinition.get = userDef.get
          ? userDef.cache !== false
            ? createComputedGetter(key)
            : userDef.get
          : noop;
        sharedPropertyDefinition.set = userDef.set
          ? userDef.set
          : noop;
      }
      Object.defineProperty(target, key, sharedPropertyDefinition);
    }
    
    function createComputedGetter (key) {//构造该computed的get函数
      return function computedGetter () {
        var watcher = this._computedWatchers && this._computedWatchers[key];
        if (watcher) {
          if (watcher.dirty) {
            watcher.evaluate();//收集该watcher的订阅
          }
          if (Dep.target) {
            watcher.depend();//同一为这一组订阅再加上组件re-render的订阅(该订阅负责更新组件)
          }
          return watcher.value
        }
      }
    }
    

      组件初始化的时候。computed项和data中的分别建立响应式。data中的数据直接对属性的get,set做数据拦截。而computed则建立一个新的watcher,在组件渲染的时候。先touch一下这个computed的getter函数。将这个watcher订阅起来。这里相当于这个computed的watcher订阅了firstname和lastname。touch完后。Dep.target此时又变为之前那个用于更新组件的。再通过watcher.depend()将这个组统一加上这个订阅。这样一旦firstname和lastname变了。同时会触发两个订阅更新。其中一个便是更新组件。重新re-render的函数。

  • 相关阅读:
    raid阵列算法/数据恢复方法汇总
    EMC Isilon(OneFS)误删文件数据恢复过程<存储数据恢复>
    Raid磁盘阵列更换磁盘时另一块盘离线(v7000存储数据恢复)
    SqlServer数据库无法读取的数据恢复方案实施过程
    ds4800服务器lvm信息丢失数据恢复方案
    Hyper-V数据文件丢失数据恢复过程
    v7000存储数据恢复成功率分析-数据恢复初检报告
    Ext4文件系统fsck后损坏如何恢复?-北亚数据恢复
    服务器raid5两块硬盘离线lvm vxfs文件系统数据恢复过程
    临时表
  • 原文地址:https://www.cnblogs.com/smzd/p/8624272.html
Copyright © 2011-2022 走看看