首页 > 其他分享 >《Vue.js 设计与实现》读书笔记(1-3章)

《Vue.js 设计与实现》读书笔记(1-3章)

时间:2023-01-12 20:46:29浏览次数:47  
标签:el Vue container 读书笔记 vnode tag const js children

第 1 章、权衡的艺术

命令式 or 声明式

命令式:关注过程
声明式:关注结果

声明式直接声明想要的结果,框架帮用户封装好命令式的代码,所以在封装的过程中要做一些其他的事情来(生成要做的事情/找出差异)生成命令式的代码,优势是可维护性强,但是性能:命令式 ≥ 声明式

框架设计要做的就是,保持可维护性,同时让性能损失更少。

虚拟 DOM

性能:innerHTML < 虚拟DOM < 原生JavaScript
心智负担/可维护性:虚拟DOM < innerHTML < 原生JavaScript

运行时和编译时

三种选择:纯运行时、运行时+编译时、纯编译时

手写vdom太麻烦,所以通过模板 or JSX 完成书写,但是这些还需要经历一次编译

Vue:运行时+编译时
Svelte: 纯编译时

第 2 章、设计框架要注意什么?

提升开发体验

用户未按要求使用时的错误提示,console 自定义 formatter 直观显示数据

控制框架代码的体积

开发环境提供良好提示,不增加生产环境体积。(通过 __DEV__ 变量判断)

Tree-Shaking

使用 ESM
如果一个函数有副作用,将不会被 Tree-Shaking 删除,通过 /*#__PURE__*/ 在打包工作( rollup/webpack )中声明没有副作用。

输出产物

IIFE:rollup format: 'iife'
ESM: format: 'esm'
CommonJS: format: 'cjs'

特性开关

用户关闭的特性,利用 Tree-Shaking 不打包到最终资源里。比如在 Vue3 中,对于 options API

处理错误

执行用户提供的函数时,做统一的错误处理(try...catch),并提供给用户错误接口来处理。(可以错误上报等。)

TypeScript类型支持

第 3 章、Vue3 的设计思路

声明式的描述 UI

模板描述,或者虚拟DOM描述

渲染器

渲染器:把虚拟DOM变成真实DOM并渲染到浏览器页面。一个简单的渲染器实现:

点击查看代码
const vnode = {
  tag: 'div',
  props: {
    onClick: () => alert('hello'),
  },
  children: 'click me',
};

function renderer(vnode, container) {
  const el = document.createElement(vnode.tag);
  for (const key in vnode.props) {
    if (/^on/.test(key)) {
      // on 开头是事件
      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)) {
    vnode.children.forEach((child) => {
      renderer(child, el);
    });
  }

  container.appendChild(el);
}

renderer(vnode, document.body);

组件的本质

组件就是一组 DOM 元素的封装。上面的渲染器兼容组件(包括函数写法和对象写法):

点击查看代码
const MyComponent = function() {
  return {
    tag: 'div',
    props: {
      onClick: () => alert('hello'),
    },
    children: 'click me - MyComponent',
  }
}

const MyComponent1 = {
  render() {
    return {
      tag: 'div',
      props: {
        onClick: () => alert('hello'),
      },
      children: 'click me - MyComponent1',
    }
  }
}

const vnode = {
  tag: MyComponent
};

function renderer(vnode, container) {
  if (typeof vnode.tag === 'string') {
    // 标签元素
    mountElement(vnode, container);
  } else if (typeof vnode.tag === 'function') {
    // 函数描述组件
    mountFunctionComponent(vnode, container);
  } else if (typeof vnode.tag === 'object') {
    // 对象描述组件
    mountObjectComponent(vnode, container)
  }
}

function mountElement(vnode, container) {
  const el = document.createElement(vnode.tag);
  for (const key in vnode.props) {
    if (/^on/.test(key)) {
      // on 开头是事件
      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)) {
    vnode.children.forEach((child) => {
      renderer(child, el);
    });
  }

  container.appendChild(el);
}

function mountFunctionComponent(vnode, container) {
  // 获取 vnode
  const subtree = vnode.tag();
  renderer(subtree, container);
}

function mountObjectComponent(vnode, container) {
  // 获取 vnode
  const subtree = vnode.tag.render();
  renderer(subtree, container);
}

renderer(vnode, document.body);

模板的工作原理

编译器:模板编译为渲染函数

<div @click="handler">
  click me
</div>

编译为

render() {
  return  h('div', { onClick: handler }, 'click me')
}

Vue 是各模块组成的有机体

模板 --[编译器]--> 渲染函数 --[渲染器]--> 真实DOM

如果在编译器中增加优化,比如静态节点的判断,就可以在渲染器减少一些工作。

标签:el,Vue,container,读书笔记,vnode,tag,const,js,children
From: https://www.cnblogs.com/wenruo/p/17047716.html

相关文章

  • Vue 指定配置运行
    在项目根目录创建run.js:const{spawnSync}=require('child_process');const{resolve}=require('path');constargs=process.argv.slice(2)if(args.lengt......
  • 【Vue3.0】关于 script setup 语法糖的用法
    scriptsetup-简介先来看一看官网关于<scriptsetup>的介绍:要彻底的了解setup语法糖,你必须先明确setup()这个组合式API官网中对于这一api的介绍是——在se......
  • axios 处理响应( 流文件或 json)
    今天遇到一前端问题。axios导出后台xls文件出现乱码。多会儿没写发现前端了,发现是【没指定响应类型时,axios默认把响应内容包成字符串,即type(res.data)='string'】,......
  • C# 中,对象转JSON以及对象转JSON字符串或者反向转换
    对象转JSON:1privatevoidbutton3_Click(objectsender,EventArgse)2{3SaleOrder_Save_Main.MainSM=newSaleOrder_Save_Main......
  • vue data为什么是函数
    vuedata是函数的原因:1、防止data复用;2、data独立性;3、作用域;4、js的特性。总结来说,如果data是一个函数的话,这样每复用一次组件,就会返回一份新的data(类似于给每个组......
  • The State of JS 2022 All In One
    TheStateofJS2022AllInOneTheStateofJS2022:LibrariesVitesthttps://2022.stateofjs.com/en-US/libraries/(......
  • JS_3_数组
    JavaScript中的数组是自动扩容的。灵活地!  声明:1、vararr=newArray();2、vararr=newArray(length);3、vararr=[];赋值和取值:通过......
  • 无法将“vue”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写
    安装vue-cli脚手架之后,运行vue命令,报错。试了很多去缓存加环境变量的都没有成功。遇到一个简单且有效的加环境变量的方法运行npmconfiggetprefix显示一段路径地址......
  • jquery.liMarquee.js-文字滚动效果
    jquery.liMarquee.js插件:jquery多风格多功能滚动特效代码插件说明:须引入3个文件jquery.js、liMarquee的js和css文件代码:<!DOCTYPEhtml><htmllang="en"><head>......
  • vite vue插件打包配置
    import{defineConfig,UserConfigExport,ConfigEnv}from"vite";importexternalGlobalsfrom"rollup-plugin-external-globals";importvuefrom"@vitejs/plugi......