note
  • Introduction
  • algorithm
    • Array
    • BinarySearch
    • Bits
    • Design
    • DFS
    • DP
    • DP_bag
    • DP_stock.md
    • Hash
    • Heap
    • NodeList
    • Number
    • SlideWindow
    • Sort
    • Stack
    • String
    • Tree
  • Backend
    • express
    • koa2
    • node
    • npm
    • npx
  • db
    • mongoDB
  • Frontend
    • CSS
      • BFC
      • flex
      • layout
      • less
      • middle
      • position
      • sass
      • selector
      • 动画相关属性
      • 响应式页面
      • 层叠上下文
      • 隐藏元素
    • JS
      • Array
      • async
      • DOM
      • ES6
      • JS-军规
      • macrotask-microtask
      • practice
      • RegExp
      • this-prototype-inherit
      • type-convert
      • 前端请求
      • 浏览器加载
      • 浏览器窗口间通信
    • TS
      • note
    • Vue
      • practice
      • Component-Communicate
      • Component
      • lifecycle
      • note
      • Pinia
      • practice
      • Vue-cli
      • Vue-Router
      • Vue-Source
      • Vue2
      • Vue3
      • Vuex
    • cross-domain
    • webpack
    • 从前端角度理解缓存
    • 前端概念
    • 页面性能分析与优化
    • 页面渲染机制
  • Linux
    • basic-command
    • docker
    • java-env
    • learn
    • manage-command
    • nginx
    • Shell
    • ssh
    • tmux
    • vi
  • chrome-devtools
  • git
  • Jenkins
Powered by GitBook
On this page
  1. Frontend
  2. Vue

Vue-Source

PreviousVue-RouterNextVue2

Last updated 2 years ago

流程图

  1. 数据代理this.message返回的是this.data[message]

  2. Object.defineProperty(this.data)数据劫持 + 发布订阅者

    1. dep.depend() 手机依赖

    2. dep.notify() 通知所有添加的Watcher

  3. 模板编译(初始化+绑定更新函数)

    1. node2Fragment

    2. compile

      1. compileElement

      2. compileText

模板解析详细流程

  1. 将el的所有子节点取出, 添加到一个新建的文档fragment对象中

  2. 对fragment中的所有层次子节点递归进行编译解析处理

    1. 对大括号表达式文本节点进行解析

      1. 根据正则对象得到匹配出的表达式字符串: 子匹配RegExp.$1

      2. 从data中取出表达式对应的属性值

      3. 将属性值设置为文本节点的textContent

    2. 对元素节点的指令属性进行解析(事件指令/一般指令)

      • 事件指令

        1. 从指令名中取出事件名

        2. 根据指令的值(表达式)从methods中得到对应的事件处理函数对象

        3. 给当前元素节点绑定指定事件名和回调函数的dom事件监听

        4. 指令解析完后, 移除此指令属性

      • 一般指令

        1. 得到指令名和指令值(表达式) text/html

        2. 从data中根据表达式得到对应的值

        3. 根据指令名确定需要操作元素节点的什么属性

        4. 将得到的表达式的值设置到对应的属性上(v-text---textContent 属性 v-html---innerHTML 属性)

        5. 移除元素的指令属性

  3. 将解析后的fragment添加到el中显示

数据绑定

  • 基本思想: 通过defineProperty()来监视data中所有属性(任意层次)数据的变化, 一旦变 化就去更新界面

  • Observer

    • 用来对data所有属性数据进行劫持的构造函数

    • 给data中所有属性重新定义属性描述(get/set)

    • 为data中的每个属性创建对应的dep对象

  • Dep(Depend)

    • data中的每个属性(所有层次)都对应一个dep对象

    • 创建的时机

      • 在初始化defineReactive data 中各个属性时创建对应的dep对象

      • 在data中的某个属性值被设置为新的对象时

    • dep对象的结构 { ​ id, // 每个 dep 都有一个唯一的 id ​ subs //包含 n 个对应 watcher 的数组(subscribes的简写) }

    • subs 属性说明

      • 当watcher被创建时, 内部将当前watcher添加到对应的dep对象的subs中

      • 当此data属性的值发生改变时, subs中所有的watcher都会收到更新的通知

  • Compiler

    • 用来解析模板页面的对象的构造函数(一个实例)

    • 利用compile对象解析模板页面

    • 每解析一个表达式(非事件指令)都会创建一个对应的watcher对象, 并建立watcher 与dep的关系

    • compile与watcher关系: 一对多的关系

  • Watcher

    • 模板中每个非事件指令(v-text、v-html)或表达式{{ message }}}都对应一个watcher对象

    • 监视当前表达式数据的变化

    • 创建的时机: 在初始化编译模板时

    • 对象的组成 { vm, //vm 对象 exp, //对应指令的表达式 cb, //当表达式所对应的数据发生改变的回调函数 value, //表达式当前的值 depIds //表达式中各级属性所对应的 dep 对象的集合对象,属性名为 dep 的id,属性值为dep

      }

  • dep与watcher的关系

    • 多对多

    • data中的一个属性对应一个dep, 一个dep中可能包含多个watcher(模板中有几个 表达式使用到了同一个属性) {{ a }}/v-text="a"

    • 模板中一个非事件表达式对应一个watcher, 一个 watcher中可能包含多个dep(表 达式是多层: a.b)

    • 数据绑定使用到2个核心技术(Object.defineProperty()和消息订阅与发布)

    • 如何建立的? data的属性get()中建立

    • 什么时候建立? 初始化解析模块中表达式创建watcher对象时

双向数据绑定

  • 双向数据绑定是建立在单向数据绑定(model==>View)的基础之上的

  • 双向数据绑定的实现流程:

    • 在解析v-model指令时, 给当前元素添加input监听

    • 当input的value发生改变时, 将最新的值赋值给当前表达式所对应的data属性