IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> vue依赖收集的具体时机 -> 正文阅读

[JavaScript知识库]vue依赖收集的具体时机

有没有面试官问过你,vue的依赖收集是在什么时候进行的?

在面试官的灵魂拷问下,整理出了这篇文章。

1、首先,了解下vue生命周期函数

vue生命周期分为beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed

官网对这个已经解释的很清楚了:实例生命周期钩子

2、从源码层面走个流程找到依赖收集的具体时机

1> 进入页面,Vue开始初始化,执行new Vue(),进入到Vue的构造函数中,在构造函数中执行了_init()方法。

2> 在_init()这个方法里,首先初始化绑定事件和生命周期钩子,然后调用 beforeCreate 这个钩子函数,在这个钩子函数中还没有初始化数据,所以在这个钩子函数中一般不进行操作。

3> 紧接着进行props、data、methods、computed、watch等的初始化,这个过程中已经将数据转换为了响应式数据。紧接着调用了 created 这个钩子函数,在这个钩子函数中已经可以拿到数据,而且可以对数据进行修改,我们可以在这个钩子函数中向后端发起请求,异步获取到数据,这个时候修改数据不会调用update函数,也不会触发其他生命周期钩子。

PS: 在_init()方法中:

// vm 的声明周期相关变量初始化
// $children/$parent/$root/$refs
initLifecycle(vm)
// vm 的事件监听初始化,父组件绑定在当前组件上的事件
initEvents(vm)
// $slots/$scopedSlots/_c/$createElement/$attress/$listeners
initRender(vm)
// 生命钩子的回调
callHook(vm, 'beforeCreate')
// 把 inject 的成员注入到 vm 上
initInjections(vm) // resolve injections before data/props
// 初始化 vm 的 _props/methods/_data/computed/watch
initState(vm)
//  初始化 provide
initProvide(vm) // resolve provide after data/props
// 生命钩子的回调
callHook(vm, 'created')
// 紧接着调用$mount函数
if (vm.$options.el) {
    vm.$mount(vm.$options.el)
}

4> 紧接着调用 m o u n t 函 数 , 在 mount函数,在 mountmount函数中将 template/el 转化成 render 函数,准备渲染。然后调用了mountComponent,在mountComponent中首先调用了beforeMount钩子,在这个钩子中,模板已经编译好了,还没有转为真实DOM挂载到页面,这个钩子函数中也可以请求数据,修改数据,修改也不会触发updata函数,不会触发其他生命周期钩子函数。

5> 紧接着定义了updateComponent,给updateComponent赋值为一个将虚拟DOM转换为真实DOM并挂载到页面上的函数。然后初始化Watcher实例,并将updateComponent作为回调函数cb传入Watcher,在Watcher构造器中,判断了cb回调函数是否是函数,如果是函数,赋给this.getter,然后调用了this.get()方法

PS: 在mountComponent方法中:

callHook(vm, 'beforeMount')
let updateComponent
updateComponent = () => {
	vm._update(vm._render(), hydrating)
}
// updateComponent 作为回调函数cb
new Watcher(vm, updateComponent, noop, {
    before () {
      if (vm._isMounted && !vm._isDestroyed) {
        callHook(vm, 'beforeUpdate')
      }
    }
}, true /* isRenderWatcher */)

6> 重点来了,依赖收集就是发生在这个get方法中,在beforeMount钩子函数之后。在get方法中,首先调用pushTarget()方法将这个Watcher实例入栈,并设置Dep.target = Watcher实例(启用依赖收集)。然后调用this.getter(),也就是调用updateComponent这个回调函数,在这个函数中,首先调用_render()方法将虚拟DOM渲染为真实DOM,在这个方法中,触发了c方法,v方法,s方法,会访问到所依赖的数据,触发getter,然后判断Dep.target是否存在,我们在pushTarget中已经启用了依赖收集,所以这个时候就会通过判断,执行depend方法,调用Watcher的addDep方法,在addDep方法中,首先获取dep的id,然后判断newDepIds数组中是否存在这个id,防止重复收集依赖。如果不存在,将dep.id存到newDepIds数组中,并将这个Watcher实例增加到dep的subs数组中。至此依赖收集完成,接着将真实DOM挂载到页面上,触发mounted钩子函数

PS: 在Watcher类中:

constructor (
    vm: Component,
    expOrFn: string | Function,
    cb: Function,
    options?: ?Object,
    isRenderWatcher?: boolean
  ) {
    this.vm = vm
    // options
    if (options) {
      this.lazy = !!options.lazy
    }
    // parse expression for getter
    if (typeof expOrFn === 'function') {
      this.getter = expOrFn
    }
    this.value = this.lazy
      ? undefined
      : this.get()
}
get () {
	// 开启依赖收集
    pushTarget(this)
    const vm = this.vm
    try {
      // 调用 updateComponent 期间访问到依赖数据触发getter进行依赖收集
      value = this.getter.call(vm, vm)
    } catch (e) {
      
    } finally {
      // 当前组件收集完毕,如果有父组件,继续收集父组件依赖
      popTarget()
      this.cleanupDeps()
    }
    return value
}

7> 至此依赖收集就完成了。当数据更新后,就会立即执行beforeUpdate钩子函数,然后 Vue 的虚拟 dom 机制会重新构建虚拟 dom 与上一次的虚拟 dom 树利用 diff 算法进行对比之后重新渲染,一般不做什么事 。

8> 当更新完成后,执行 updated 钩子函数,数据已经更改完成,dom 也重新 render 完成,可以操作更新后的虚拟 dom 。

9> 当经过某种途径调用$destroy 方法后,立即执行 beforeDestroy 钩子函数,一般在这里做一些善后工作,例如清除计时器、清除绑定的事件等等。组件的数据绑定、监听…去掉后只剩下 dom 空壳,这个时候,执行 destroyed 钩子函数,在这里做善后工作也可以 。

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-23 10:38:28  更:2021-07-23 10:40:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/22 23:33:12-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码