我通过ChatGpt复习Vue第三天

第三天学习内容

1. Vue.js 的虚拟 DOM

1.1 什么是虚拟 DOM

  • 虚拟 DOM 是 Vue.js 和其他现代前端框架(如 React)使用的概念。它是一种在内存中表示 UI 结构的对象,而不是直接操作真实的 DOM 节点。
  • 优点:通过虚拟 DOM,Vue 可以在更新 UI 时更高效地对比新旧节点,减少不必要的 DOM 操作,从而提升性能。

1.2 Vue2 中的虚拟 DOM 实现

  • Vue2 中使用了一个轻量级的 VNode 类来表示虚拟 DOM 节点。每次组件重新渲染时,Vue 会生成新的 VNode 树并与旧的 VNode 树进行比较(称为 diffing),以决定哪些部分需要更新。

VNode 类定义:

class VNode {
  constructor(tag, data, children, text, elm) {
    this.tag = tag;           // 节点标签名
    this.data = data;         // 节点数据
    this.children = children; // 子节点
    this.text = text;         // 文本节点
    this.elm = elm;           // 对应的真实DOM节点
  }
}

  • Diff 算法:Vue2 的 Diff 算法是采用双端比较,尽量减少 DOM 的修改。它会逐层对比新旧节点,找到最小的更新路径。

1.3 Vue3 中的虚拟 DOM 改进

  • Vue3 在虚拟 DOM 上做了大量优化,主要体现在对 VNode 的更高效处理和更快的 Diff 算法。

Vue3 中的 VNode:

function createVNode(type, props = null, children = null) {
  const vnode = {
    type,
    props,
    children,
    el: null, // 与真实DOM的关系由 el 属性连接
    key: props && props.key,
  };
  return vnode;
}

  • Patch 函数:Vue3 中使用 patch 函数来处理新旧 VNode 树之间的差异,通过递归地比较新旧节点,实现最小更新。

2. Vue.js 的模板编译

2.1 模板编译的作用

  • Vue.js 中的模板编译器将模板语法转换为渲染函数。渲染函数生成虚拟 DOM 树,最终渲染到真实 DOM 上。

2.2 编译流程

  • 解析(Parsing):将模板字符串解析为抽象语法树(AST)。
  • 优化(Optimize):静态标记优化,标记出静态节点,减少后续更新时的比较成本。
  • 代码生成(Code Generation):将 AST 转化为渲染函数。

模板编译示例:

const template = `<div id="app">{{ message }}</div>`;
const render = compile(template);

// 转换为:
function render() {
  return _c('div', { attrs: { id: 'app' } }, [_v(_s(message))]);
}

2.3 Vue2 与 Vue3 模板编译的区别

  • Vue2 的模板编译是将模板转换为渲染函数,然后在每次数据更新时执行渲染函数以生成新的虚拟 DOM。
  • Vue3 通过进一步优化编译过程,引入了 compiler 模块,将模板转换为更高效的渲染函数,使得运行时的性能更优。

3. Vue.js 的生命周期

3.1 Vue2 的生命周期

  • Vue2 的生命周期钩子包括 beforeCreate, created, beforeMount, mounted, beforeUpdate, updated, beforeDestroy, destroyed。
  • 这些钩子函数提供了在组件各个阶段执行代码的机会。

Vue2 生命周期图示:

Vue.component('example', {
  beforeCreate() {
    console.log('beforeCreate');
  },
  created() {
    console.log('created');
  },
  // 其他钩子函数...
});

3.2 Vue3 的生命周期

  • Vue3 的生命周期钩子名称稍有变化,例如 beforeDestroy 变成了 beforeUnmount,destroyed 变成了 unmounted。
  • 同时,Vue3 还引入了基于 Composition API 的生命周期钩子函数,如 onMounted, onUpdated, onUnmounted。

Vue3 生命周期示例:

import { onMounted, onUnmounted } from 'vue';

export default {
  setup() {
    onMounted(() => {
      console.log('Component mounted');
    });

    onUnmounted(() => {
      console.log('Component unmounted');
    });
  }
};

4. Vue Router 与 Nuxt.js 的高级应用

4.1 Vue Router 的路由守卫

  • 全局守卫:如 beforeEach, beforeResolve, afterEach,用于控制导航过程。
  • 路由级别守卫:在路由配置中指定守卫。
  • 组件内守卫:在组件内部通过 beforeRouteEnter, beforeRouteUpdate, beforeRouteLeave 实现路由控制。

全局守卫示例:

router.beforeEach((to, from, next) => {
  if (to.meta.requiresAuth && !store.state.isAuthenticated) {
    next('/login');
  } else {
    next();
  }
});

4.2 Nuxt.js 的 SSR 与静态生成

  • SSR(Server-Side Rendering):Nuxt.js 的核心功能之一,它将 Vue.js 应用在服务器端渲染,从而提升首屏加载速度和 SEO。
  • 静态生成:Nuxt.js 通过 nuxt generate 命令将应用预渲染为静态页面,适合内容较少但访问量较大的应用。

Nuxt.js 简单示例:

// pages/index.vue
<template>
  <div>
    <h1>{{ title }}</h1>
  </div>
</template>

<script>
export default {
  async asyncData({ $axios }) {
    const title = await $axios.$get('/api/title');
    return { title };
  }
};
</script>

5. 总结

第三天的学习内容涵盖了 Vue.js 的虚拟 DOM 和模板编译的深层理解,以及生命周期管理与 Vue Router/Nuxt.js 的高级应用。这些知识点对于构建高性能、高可维护性的 Vue 应用至关重要。

6.Diff算法扩展

6.1 Diff 算法的基本原理

Diff 算法的主要目标是找到最小的更新路径,也就是在新旧虚拟 DOM 树对比时,只更新那些真正需要更新的部分,尽可能减少 DOM 操作的次数和范围,从而提升性能。

6.2 Vue2 中的 Diff 算法

在 Vue2 中,Diff 算法基于双端比较策略,即同时从新旧节点的头部和尾部进行比较,以下是详细步骤:

  1. 同一层级的比较
    Diff 算法只会比较同一层级的节点,不会跨层级对比,这样可以大大简化计算过程。
  2. 双端对比策略
  • 头部对头部(sameVnode(oldStartVNode, newStartVNode)):先比较新旧虚拟 DOM 树的头部节点。如果相同,则直接复用旧节点,继续比较下一个头部节点。
  • 尾部对尾部(sameVnode(oldEndVNode, newEndVNode)):如果头部节点不相同,则比较新旧虚拟 DOM 树的尾部节点。如果相同,复用旧节点,继续比较下一个尾部节点。
  • 旧头部对新尾部(sameVnode(oldStartVNode, newEndVNode)):如果头尾都不相同,则将旧头部节点与新尾部节点比较,如果相同,进行相应的节点移动操作。
  • 旧尾部对新头部(sameVnode(oldEndVNode, newStartVNode)):同理,比较旧尾部节点与新头部节点,相同则进行节点移动操作。
  1. 处理剩余节点
  • 当头尾对比结束后,如果仍有剩余节点,需要根据情况进行插入或删除操作。
  1. Key 的作用
  • 在 Diff 算法中,如果虚拟 DOM 节点设置了 key 属性,算法会优先通过 key 来匹配节点,而不只是比较节点的类型。key 的作用在于更精确地找到对应的旧节点,提高算法效率。
    示例代码(简化版的 patch 函数):
  function patch(oldVNode, newVNode) {
  if (!oldVNode) {
    // 如果 oldVNode 不存在,直接创建新节点
    createElm(newVNode);
  } else if (sameVnode(oldVNode, newVNode)) {
    // 如果两个节点是相同节点,则进行精细化比较
    patchVnode(oldVNode, newVNode);
  } else {
    // 如果两个节点不是相同节点,替换旧节点
    const oldEl = oldVNode.elm;
    const parentEl = oldEl.parentNode;
    createElm(newVNode);
    parentEl.insertBefore(newVNode.elm, oldEl);
    parentEl.removeChild(oldEl);
  }
}

6.3 Vue3 中的 Diff 算法优化

Vue3 对 Diff 算法进行了优化,主要体现在以下几个方面:

  1. 更高效的 Patch 流程
  • Vue3 的 patch 函数进行了大量优化,在处理复杂结构时效率更高,尤其是针对静态节点和大型列表的更新。
  1. 静态提升(Static Hoisting)
  • 在编译阶段,Vue3 会对模板中的静态内容进行提升,只创建一次静态节点,并在后续更新中直接复用,减少不必要的计算。
  1. Fragment 支持
  • Vue3 支持 Fragment 作为根节点进行更新,这样可以避免不必要的包裹元素,提高渲染灵活性和性能。
  1. 更加智能的 Diff 策略
  • Vue3 在处理长列表时,通过智能化的 Keyed Diff 策略进一步优化对比过程,减少 DOM 操作次数。它引入了一种更加先进的最长递增子序列(LIS,Longest Increasing Subsequence)算法,用于优化非同层次节点的移动操作。
    示例代码(简化版的 Vue3 Patch 逻辑):
function patchKeyedChildren(c1, c2, container) {
  // 新旧节点列表双端比较,依次处理节点移动或更新操作
  let i = 0;
  let e1 = c1.length - 1;
  let e2 = c2.length - 1;

  // 头部对比
  while (i <= e1 && i <= e2) {
    const n1 = c1[i];
    const n2 = c2[i];
    if (isSameVNode(n1, n2)) {
      patch(n1, n2, container);
      i++;
    } else {
      break;
    }
  }

  // 尾部对比
  while (e1 >= i && e2 >= i) {
    const n1 = c1[e1];
    const n2 = c2[e2];
    if (isSameVNode(n1, n2)) {
      patch(n1, n2, container);
      e1--;
      e2--;
    } else {
      break;
    }
  }

  // 处理新增或删除节点
  if (i > e1) {
    const nextPos = e2 + 1;
    const anchor = nextPos < c2.length ? c2[nextPos].el : null;
    while (i <= e2) {
      patch(null, c2[i], container, anchor);
      i++;
    }
  } else if (i > e2) {
    while (i <= e1) {
      unmount(c1[i], container);
      i++;
    }
  }
}

6.4 Diff 算法的优化策略

  1. 用 key
  • 为节点设置唯一的 key 属性,特别是在长列表中。key 能帮助 Diff 算法更准确地找到对应的节点,减少不必要的操作。
  1. 避免过度更新
  • 在设计组件时,尽量减少数据状态的频繁变动,避免在每个数据变动时都触发重新渲染。
  1. 合理使用静态节点
  • 在模板中标记不需要更新的静态内容,可以避免 Diff 算法的过度计算。Vue3 通过编译阶段的静态提升,自动优化了这一点。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值