其他分享
首页 > 其他分享> > 个人自学前端28-Vue5-虚拟节点,生命周期

个人自学前端28-Vue5-虚拟节点,生命周期

作者:互联网

目录

一. 虚拟节点

目前流行的视图框架都是基于虚拟节点技术开发的.
视图框架 => 更新视图的最后异步是DOM操作. => 尽量以最低的代价进行DOM操作.
视图框架如何进行最低代价的DOM操作 => 虚拟节点 => 虚拟节点的更新 => diff算法.
虚拟节点 => 一个纯对象 => 描述真实节点.
虚拟节点在描述一个标签时,都有3个最基本的属性 => 标签名,属性列表,子节点列表。
虚拟节点就是真实节点的js描述.(AST语法树)

    const Vnode = {
      // 描述标签名
      tag: 'div',
      // 描述属性节点列表
      attrs: [{id: 'app'}],
      children: [{
        tag: 'h3',
        attrs: [],
        children: ['Vue你好']
      }]
    }
    console.log(vm._vnode);

真实节点更新 => 一定是DOM操作完成.
虚拟节点更新 => 修改纯对象.

如何根据更新后的虚拟节点,决定如何进行DOM操作去更新真实节点. => diff算法.
diff算法 => 比较更新前和更新后的虚拟节点一桶,最终决定如何进行DOM操作.

二. 生命周期

Vue的生命周期 => Vue实例从创建达到销毁过程中的特定阶段.
image
new Vue实例化(组件实例化)
触发beforeCreate
通过Object.defineProperty给data数据设置数据劫持
触发created.
判断有没有el选项.
如果没有el选项,则等待$mount方法触发,如果这个方法也没触发,则实例化失败.( $mount(选择器) === el: 选择器)
如果有,继续判断有没有template选项
如果有template选项,则编译template
如果没有template选项,则编译el所在的标签
触发beforeMount
根据编译的虚拟节点生成真实节点vm.$el.并且用真实的新视图替换掉老视图
触发mounted.进入运行阶段.
监控数据变化,触发beforeUpdate,updated
实例(组件DOM)销毁时,先调用beforeDestory
调用Destroyed,全部销毁

1. 创建期

创建 => 给vue实例添加数据 => 给data设置数据劫持.
创建前后 => 数据劫持前后.(Object.defineProperty进行数据劫持前后)
这两个钩子只会触发一次.

2. 挂载期

挂载 => 新视图替换老视图.(组件template替换组件标签).
挂载前后 => 新视图出现前后.
这两个钩子也只触发一次.
mounted => 视图初始化.
挂载都发生了什么事情?

  1. 编译template.(把字符串模板编译成虚拟节点).
  2. 编译遇到指令和插值表达式,都会进行求值.(收集依赖).
  3. 把虚拟节点转换为新视图,替换老视图.

3. 更新期

视图更新前后 => 分别触发beforeUpdate和updated
默认不触发(Vue实例化阶段不触发).
Vue实例化完成之后,视图再更新,才会触发.
有可能触发很多次.

  1. updated和watch的区别
    updated => 视图更新就触发.不能知道本次更新是由于哪个数据变化导致的.具有响应式效果的数据变化,都触发updated.
    watch => 数据变化就触发.监听哪个数据,就触发哪个方法.
  2. 更新真实节点
    数据变化 => 导致视图更新 (响应式)
    数据变化 => 先更新虚拟节点 => diff算法判断 => 最后更新真实节点。
    1. 原地更新.(标签不增删,不移动,直接修改内容或者属性)(更新前后是同一个标签) => 更新前后的tag和key完全一致.
    2. 替换更新.(会增删,移动元素)(新增,删除,移动) => tag或key有一个不一样.
  3. 什么时候原地更新?什么时候替换更新?
    1. 比较更新前后的虚拟节点.(同级比较)
    2. 如果同级的tag一致,并且key一样,则表示更新前后是同一个标签,使用原地更新策略.
    3. 如果同级的tag或者key有一个不一样,则表示更新前后不是同一个标签,使用替换更新策略.

4. 销毁期

destroyed => 组件销毁后的善后处理,例如停止定时器
组件销毁只是让数据不驱动视图更新了而已.组件实例还是存在的.

5.父子组件生命周期顺序

父beforeCreate
父created
父beforeMount
子beforeCreate
子created
子beforeMount
子mounted
父mounted

为什么顺序是这样的. => 函数执行顺序回答.父组件的视图编译就是一个函数从上往下执行.
能不能修改这个顺序.(4父4子) => 通过v-if实现.父组件挂载后再编译子组件.

三. nextTick

如何针对某个数据变化导致的视图更新写单独的逻辑?
vue的视图更新是异步的,数据变化不会马上导致视图更新.

nextTick的回调函数,会在视图更新后自动触发.只触发一次
一定是用来处理跟视图相关的逻辑.

    const App = {
      template: `
        <div>
          <button @click='fn'>修改str</button>
          <ul ref='ul'>
            <li v-for='d in count'>{{d}}</li>
          </ul>
        </div>
      `,
      data() {
        return {
          count: 0
        }
      },
      methods: {
        fn() {
          // 数据变化会导致视图变化.视图变化完成之后,就会触发nextTick
          this.count++;
          // 这里只会在count变化导致的视图更新后触发.
          this.$nextTick(() => {
            let oUl = this.$refs.ul;
            oUl.scrollTop = oUl.scrollHeight - oUl.clientHeight;
          });
        }
      }
    }

标签:触发,生命周期,28,更新,Vue5,虚拟,视图,组件,节点
来源: https://www.cnblogs.com/DarkCrow/p/15353495.html