</script> <body><...">
最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Vue.js源码解析——响应式

    正文概述 掘金(Yaping)   2021-01-22   580

    准备工作

    这个文章很简单,主要是看下面的代码运行的过程

    <script src="../../dist/vue.js"></script>
    <body>
      <div id="app">
        {{ msg }}
      </div>
      <script>
        const vm = new Vue({
          el: '#app',
          data: {
            msg: 'Hello!',
          }
        });
      </script>
    </body>
    

    开始调试

    所在目录调试函数要做的事
    src/core/instance/index.jsVue发现他调用了this._init()方法(此时this上已经挂载了很多方法,关于这些挂载的方法,以后再出文)src/core/instance/init.js_init()调用initState去初始化实例状态, 进入initStatesrc/core/instance/state.jsinitState()_data、_props、_methods, 调用 initData(vm), 进入initDatasrc/core/instance/state.jsinitData()把data中的成员注入到vue实例,并把她转换成响应式..initData()获取data的所有属性名,判断是否和props,methods重名,如果不重名把data中的成员注入到vue实例 _data中..initData()执行observe(data,true /* asRootData */) 开始响应式的处理,进入observer函数src/core/observer/index.jsobserver()判断value是否为对象或者是VNode,不是对象直接返回..observe()如果value有__ob__(observer对象)属性并且value.ob 是Observer实例,返回实例..observe()否则 new Observer(value) ,并且返回, 下面我们进入Observer看下里面发生了什么src/core/observer/index.jsObserver类在构造函数内部,看到了this.dep = new Dep() 进行依赖收集,进入Depsrc/core/observer.dep.jsDep类发现里面定义了一些方法,和subs数组,准备进行依赖收集,注意:此时还没收集呢,只是定义,我们回到 Observer类src/core/observer/index.jsObserver类执行def函数,给value对象设置__ob__属性,值为当前实例,然后判断value是否为数组,如果是数组,执行对应的响应式处理,如果是对象,执行this.walk(value),进入walk函数..walk遍历每个对象属性,调用defineReactive(obj,key[i])设置为响应式数据,下面我们进入defineReactive..defineReactice创建依赖对象实例 、获取obj的属性描述符对象, 通过描述符对象提取用户设置的get、set,判断是否递归观察子对象(根据shallow去判断是否需要深度监听),并将子对象属性都转换成getter/setter, 返回子观察对象..defineReactice执行Object.defineProperty方法为对象设置get和set, 这个部分是响应式的关键,下面附上了这部分的代码及相应注释

    附上核心实现源码

    Object.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        get: function reactiveGetter () {
          // 如果用户设置了getter,则value等于getter调用的返回值, 否则直接赋予属性值
          const value = getter ? getter.call(obj) : val
          // 下面的部分来收集依赖
          // 当访问值得时候会进行依赖收集,依赖收集其实就是把依赖该属性的watcher对象添加到dep对象的subs数组中,将来数据变化的时候通知所有的watcher
          // 如果存在当前依赖目标,即 watcher对象,则建立依赖
          if (Dep.target) {
            // 进行依赖收集
            dep.depend()
            // 如果子观察目标存在,建立子对象的依赖关系
            if (childOb) {
              childOb.dep.depend()
              // 如果属性是数组,则特殊处理收集数组对象依赖
              if (Array.isArray(value)) {
                dependArray(value)
              }
            }
          }
          // 返回属性值
          return value
        },
        set: function reactiveSetter (newVal) {
          // 如果用户设置了getter,则value等于getter调用的返回值, 否则直接赋予属性值
          const value = getter ? getter.call(obj) : val
          // 如果新值等于旧值 或者 新值旧值都为NaN则不执行
          /* eslint-disable no-self-compare */
          if (newVal === value || (newVal !== newVal && value !== value)) {
            return
          }
          /* eslint-enable no-self-compare */
          if (process.env.NODE_ENV !== 'production' && customSetter) {
            customSetter()
          }
          // 如果没有 setter 直接返回
          // #7981: for accessor properties without setter
          if (getter && !setter) return
          if (setter) {
            // 如果用户设置了setter则调用setter
            setter.call(obj, newVal)
          } else {
            // setter/getter 都不存在,更新新值
            val = newVal
          }
          // 如果新值是对象,观察子对象并返回 子的 observer对象
          childOb = !shallow && observe(newVal)
          // 派发更新(发布更改通知)
          dep.notify()
        }
      })
    

    当响应式数据处理完,在src/core/instance/init.js中继续向下执行,执行$mount

      if (vm.$options.el) {
        vm.$mount(vm.$options.el)
        // 此函数里面主要是解析模板,如果用户不传递render函数,解析模板
      }
    

    src/platforms/web/entry-runtime-with-compiler.js 下面重写了$mount并进行模板的渲染


    起源地下载网 » Vue.js源码解析——响应式

    常见问题FAQ

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

    发表评论

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

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

    联系作者

    请选择支付方式

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