zoukankan      html  css  js  c++  java
  • Vue结构

    转自:https://www.jianshu.com/p/90b762f1f649

    架构图

    先看下Vue源码的基本架构图:

     
    vue源码结构.png

    Vue的设计可以概括成两部分:响应式数据节点挂载。简单来讲,前者是设计数据的getter和setter方法,保证get和set时触发视图的更新;后者是解析视图的结构,生成相应的directive(指令),视图的更新是由directive完成的。

    响应式数据

    Vue进行实例化时,会执行_init函数,_init包括了以下几个执行步骤:

    Vue.prototype._initState = function () {
        this._initProps()
        this._initMeta()
        this._initMethods()
        this._initData()
        this._initComputed()
      }
    
    • _initProps 处理props属性,在Component中会使用到props属性
    • _initMeta 处理诸如$index, $key & $value等meta信息
    • _initMethods 把methods属性中包含的方法绑定到Vue实例上,并且指定其作用域为该Vue的实例
    • _initData 给数据的每个字段添加响应逻辑,数据获取(getter)时会更新依赖,数据设置(setter)时会通知依赖进行更新
    • _initComputed computed属性中方法的执行和计算,同时生成Watcher实例,Watcher负责关联数据和directive
    _initData

    _initData 的主要功能是给data中所有字段都加上响应式设计。当字段进行get操作时,更新订阅当前字段的Watcher对象,也就是更新依赖;当字段set时,通知Watcher对象,Watcher对象会通知directive对象进行进行View的改变。 Watcher在数据(data)和指令(directive)之间充当数据桥梁的作用。它的主要逻辑集中在defineReactive函数:

    function defineReactive (obj, key, val) {
      var dep = new Dep()  // dep对象负责维护订阅列表(对数据而言,就是Watcher对象)
      ...
      var childOb = observe(val) // 迭代遍历执行
      Object.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        get: function reactiveGetter () {
          var value = getter ? getter.call(obj) : val
          if (Dep.target) {  // Dep.target是个Watcher对象实例
            dep.depend()  // 把Dep.target这个Watcher对象加入到dep的subs列表中
            if (childOb) {  // 迭代更新字段的子字段
              childOb.dep.depend()
            }
            ...
          }
          return value
        },
        set: function reactiveSetter (newVal) {
          var value = getter ? getter.call(obj) : val
          if (newVal === value) {
            return
          }
          if (setter) {
            setter.call(obj, newVal)
          } else {
            val = newVal
          }
          childOb = observe(newVal)
          // 此处会调用依赖列表的watcher进行数据视图的同步! 
          // watcher会调用directive的更新方法
          dep.notify()
        }
      })
    }
    

    挂载节点

    普通节点

    节点的挂载主要逻辑在在_compile中,它对挂载的root节点和子节点分开处理。 对root节点,执行的流程:

    _compile -> compileRoot -> compileDirectives -> vm._bindDir -> directive._bind
    

    vm._bindDir 会依据节点的指令生成directive对象实例,然后调用directive的_bind方法实现directive和Watcher的关联:

    Directive.prototype._bind = function () {
      var name = this.name
      var descriptor = this.descriptor
    
      // initial bind
      // 调用directive 如 on click的bind方法
      if (this.bind) {
        this.bind()
      }
    
      ...
      // 生成watcher对象,watcher对象实例化时 会执行get方法 进行一次数据的依赖收集
        var watcher = this._watcher = new Watcher(
          this.vm,
          this.expression,
          this._update, // callback
          {
            filters: this.filters,
            twoWay: this.twoWay,
            deep: this.deep,
            preProcess: preProcess,
            postProcess: postProcess,
            scope: this._scope
          }
        )
        // v-model with inital inline value need to sync back to
        // model instead of update to DOM on init. They would
        // set the afterBind hook to indicate that.
        if (this.afterBind) {
          this.afterBind()
        } else if (this.update) {
          this.update(watcher.value)
        }
      }
      this._bound = true
    }
    

    对于非root节点,有一个迭代遍历解析的过程,基本的执行过程相同。

    Component节点

    对了组件(Component)中的逻辑,其执行流程和普通的节点相似;不同的地方是它有一个独立的作用域。



    作者:狐尼克朱迪
    链接:https://www.jianshu.com/p/90b762f1f649
    來源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
  • 相关阅读:
    Mysql JSON 新特性用法
    fastjson 使用技巧
    kafka 笔记
    nginx 使用教程
    spring boot 和 spring mvc 使用 jackson 包处理 忽略 null 字段返回
    jmeter 安装使用
    windows 下千万不要用 git的“换行符自动转换功能”
    ps grep awk 结合 xargs kill进程
    linux发行版版本及内核查看
    union 跟 order by同时使用
  • 原文地址:https://www.cnblogs.com/chinet/p/9285701.html
Copyright © 2011-2022 走看看