《Vue.js设计与实现》笔记

第一章 框架的定位和方向

命令式 声明式
差异 关注过程,利用原生JavaScript 进行Dom操作(jQuery) 关注结果,类 HTML 的模板(Vue)
优缺点 理论上可以做到极致优化,但心智负担大 封装了过程,损失一部分性能,心智负担小,可维护性更强
更新性能消耗 直接修改 找出差异(虚拟Dom) + 直接修改
纯运行时 纯编译时
解释 Render函数,将虚拟Dom -> 真实Dom。 把 HTML 标签编译成树型结构的数据对象,或直接编译成命令式代码
缺点 没办法分析用户提供的内容,哪些内容未来可能会改变,哪些内容永远不会改变 由于不需要任何运行时,而是直接编译成可执行的 JavaScript 代码,因此性能可能会更好,但是这种做法有损灵活性

Vue.js 3 是一个编译时 + 运行时的声明式框架。

第二章 设计核心

开发体验是衡量一个框架的重要指标之一,提供友好的警告信息至关重要。提供了registerErrorHandler函数,用户可以使用它注册错误处理程序。

框架的大小也是衡量框架的标准之一。利用 Tree-Shaking 机制,定义__DEV__ 常量,生产环境去除警告信息。添加 /*#__PURE__*/ 注释,标记不会产生副作用的函数,辅助Tree-Shaking。定义__VUE_OPTIONS_API__常量等决定一些特性的开关,减少打包体积。

输出格式:

  1. IIFE 形式。立即执行的函数表达式,通过<script> 标签引入。
  2. ESM 格式。带有 -bundler 字样的 ESM 资源是给 rollup.js 或 webpack 等打包工具使用的,而带有 -browser 字样的 ESM 资源是直接给 <script type="module"> 使用的。前者需要(process.env.NODE_ENV !== ‘production’) 替换 __DEV__ 常量。
  3. cjs 格式。服务端渲染中,资源的模块格式应该是 CommonJS。

第三章 设计思路

介绍了编译器、渲染器的基本实现、组件的本质。

  1. 渲染器:虚拟Dom -> 真实Dom。
 // 虚拟Dom
 const vnode = {
    
    
     tag: "div",
     props: {
    
    
       onClick: () => alert("hello"),
     },
     children: "click me",
 };
 
 // 渲染器
 function renderer(vnode, container) {
    
    
     const el = document.createElement(vnode.tag);
     // 遍历 vnode.props,将属性、事件添加到 DOM 元素
     for (const key in vnode.props) {
    
    
       if (/^on/.test(key)) {
    
    
         el.addEventListener(
           key.substr(2).toLowerCase(), // onClick ---> click
           vnode.props[key] // 事件处理函数
         );
       }
     }
 
     // 处理 children
     if (typeof vnode.children === "string") {
    
    
       // 文本子节点
       el.appendChild(document.createTextNode(vnode.children));
     } else if (Array.isArray(vnode.children)) {
    
    
       // 递归地调用 renderer 函数渲染子节点,使用当前元素 el 作为挂载点
       vnode.children.forEach((child) => renderer(child, el));
     }
 
     container.appendChild(el);
 }
  1. 编译器:模板 -> 虚拟Dom。
const template = '<div id="foo" :class="cls"></div>';

// 虚拟Dom
 render() {
    
    
   return {
    
    
     tag: 'div',
     props: {
    
    
       id: 'foo',
       class: cls
     },
     patchFlags: 1 // 假设数字 1 代表 class 是动态的,通过标记知道哪些是动态的,提高性能
   }
 }
  1. 组件:DOM 元素的封装。
   const vnode = {
    
    
       tag: myComponent,
       props: {
    
    },
   };
   
   const myComponent = {
    
    
       tag: "div",
       props: {
    
    },
   }
   
   // 渲染器添加判断
   function renderer(vnode, container) {
    
    
     if (typeof vnode.tag === 'string') {
    
    
       mountElement(vnode, container)
     } else if (typeof vnode.tag === 'object') {
    
     // 如果是对象,说明 vnode 描述的是组件
       mountComponent(vnode, container)
     }
   }

更新中…

猜你喜欢

转载自blog.csdn.net/m0_49343686/article/details/130831843