第13章、异步组件与函数式组件

13.1 异步组件要解决的问题

用户可以简单通过 import 异步导入组件。

<template>
<component :is="asyncComp">
</template> <script>
export default {
setup() {
const asyncComp = shallowRef(null)
import ('CompB.vue').then(CompB => asyncComp.value = CompB)
}
}
</script>

但我们还需要考虑组件加载失败,Loading 显示,失败重试等问题。

13.2 异步组件的实现原理

卸载函数增加卸载组件的逻辑

function unmount(vnode) {
if (vnode.type === Fragment) {
vnode.children.forEach((c) => unmount(c))
return
} else if (typeof vnode.type === 'object') {
unmount(vnode.component.subTree)
return
}
const parent = vnode.el.parentNode
if (parent) {
parent.removeChild(vnode.el)
}
}

在异步组件增加完善的逻辑,具体含义见代码注释。

function defineAsyncComponent(options) {
if (typeof options === 'function') {
options = {
loader: options,
}
}
const { loader } = options
let InnerComp = null let retries = 0
function load() {
return loader().catch((err) => {
if (options.onError) {
// 函数返回Promise 并让用户在retry中调用resolve
// 这样用户retry之后 通过load().then() 可以获取组件值
// 即使又失败 就是又返回一个Promise 对象 还是要获取Promise中resolve的值
// 所以这样可以多次调用retry
return new Promise((resolve, reject) => {
const retry = () => {
resolve(load())
retries++
}
const fail = () => reject(err)
options.onError(retry, fail, retries)
})
} else {
throw err
}
})
} return {
name: 'AsyncComponentWrapper',
setup() {
const loaded = ref(false)
const error = shallowRef(null)
const loading = ref(false) const loadingTimer = null
if (options.delay) {
// 设置options.delay的话,在options.delay时间之后再把loading设置为true,
// 防止组件加载比较快的情况下出现loading一闪而过导致用户体验差
loadingTimer = setTimeout(() => {
loading.value = true
}, options.delay)
} else {
loading.value = true
}
load() // 使用load函数加载组件
.then((c) => {
InnerComp = c
loaded.value = true
})
// 记录错误
.catch((err) => (error.value = err))
// 加载后设置加载成功 loading为false
.finally(() => {
loading.value = false
clearTimeout(loadingTimer)
})
let timer = null
if (options.timeout) {
timer = setTimeout(() => {
const err = new Error('异步组件加载超时')
error.value = err
}, options.timeout)
}
// 保证组件被卸载时清除定时器
onUmounted(() => clearTimeout(timer))
// 占位内容
const placeholder = { type: Text, children: '占位' }
return () => {
// 加载成功渲染组件 否则渲染占位符
if (loaded.value) {
return { type: InnerComp }
} else if (error.value && options.errorComponent) {
// 存在错误返回error对应组件
return { type: options.errorComponent, props: { error: error.value } }
} else if (loading.value && options.loadingComponent) {
// 加载中返回loading对应组件
return { type: options.loadingComponent }
}
return placeholder
}
},
}
}

13.3 函数式组件

函数式组件本质就是一个普通函数,该函数的返回值是虚拟 DOM。在 Vue3 中函数式组件的性能和普通组件差不多,但是比较简单。

实现也很简单,就是在 patch 新增对函数的支持,同时在组件挂载时,把 type 作为渲染函数。

function patch(n1, n2, container, anchor) {
//...
// 新增了对函数的判断
if (typeof type === 'object' || typeof type === 'function') {
// 组件
if (!n1) {
// 挂载
mountComponent(n2, container, anchor)
} else {
patchComponent(n1, n2, anchor)
}
}
} function mountComponent(vnode, container, anchor) {
const isFunctional = typeof vnode.type === 'function'
let componentOptions = vnode.type
if (isFunctional) {
componentOptions = {
render: vnode.type,
props: vnode.type.props,
}
}
// ...
}

使用方法:

function MyFuncComp(props) {
return {
type: 'h1',
children: props.title
}
}
MyFuncComp.props = {
title: String
}
const vnode = {
type: MyFuncComp,
props: {
title: '函数式组件'
}
}

《Vue.js 设计与实现》读书笔记 - 第13章、异步组件与函数式组件的更多相关文章

  1. 【vue.js权威指南】读书笔记(第一章)

    最近在读新书<vue.js权威指南>,一边读,一边把笔记整理下来,方便自己以后温故知新,也希望能把自己的读书心得分享给大家. [第1章:遇见vue.js] vue.js是什么? vue.j ...

  2. 【vue.js权威指南】读书笔记(第二章)

    [第2章:数据绑定] 何为数据绑定?答曰:数据绑定就是将数据和视图相关联,当数据发生变化的时候,可以自动的来更新视图. 数据绑定的语法主要分为以下几个部分: 文本插值:文本插值可以说是最基本的形式了. ...

  3. C++ primer plus读书笔记——第13章 类继承

    第13章 类继承 1. 如果购买厂商的C库,除非厂商提供库函数的源代码,否则您将无法根据自己的需求,对函数进行扩展或修改.但如果是类库,只要其提供了类方法的头文件和编译后的代码,仍可以使用库中的类派生 ...

  4. js高程读书笔记(1-3章)

    一.js简介 js是一种专为与网页交互而设计的脚本语言,由以下三个不同的部分组成: 1.ECMAScript,由ECMA-262(它规定了语言的这些组成部分:语法,类型,语句,关键字,保留字,操作符, ...

  5. 《Android内核剖析》读书笔记 第13章 View工作原理【View重绘过程】

    计算视图大小的过程(Measure) 视图大小,准确的来说应该是指视图的布局大小:我们在layout.xml中为每个UI控件设置的layout_width/layout_height两个属性被用来设置 ...

  6. Javascript设计模式与开发实践读书笔记(1-3章)

    第一章 面向对象的Javascript 1.1 多态在面向对象设计中的应用   多态最根本好处在于,你不必询问对象“你是什么类型”而后根据得到的答案调用对象的某个行为--你只管调用行为就好,剩下的一切 ...

  7. INSPIRED启示录 读书笔记 - 第13章 产品原则

    确定什么最重要 产品原则是对团队信仰和价值观的总结,用来指导产品团队作出正确的决策和取舍.它体现了产品团队的目标和愿景,是产品战略的重要组成部分.从形式上看,它是一系列明确的.体现团队特色的产品价值准 ...

  8. JavaScript高级程序设计第三版-读书笔记(1-3章)

    这是我第一次用markdown,也是我第一次在网上记录我自己的学习过程. 第一章 JavaScript主要由以下三个不同的部分构成 ECMAScript   提供核心语言功能 DOM     提供访问 ...

  9. 《Javascript高级程序设计》读书笔记(1-3章)

    第一章 JavaScript简介 1.1 JavaScript简史 略 1.2 JavaScript实现 虽然 JavaScript 和 ECMAScript 通常都被人们用来表达相同的含义,但 Ja ...

  10. 《C和指针》 读书笔记 -- 第13章 高级指针话题

    1.函数指针 int (*f)(); int *(*f[])(); 用途: [1]回调函数 e.g. /*在一个单链表中查找指定值*/ Node *search_list(Node *node,voi ...

随机推荐

  1. CSP-S提高组数据结构算法模板大合集

    CSP-S 算法总结 2.2.1 基础知识与编程环境 无 2.2.2 C++ 程序设计 2 set/nultiset map/multimap deque/priority_queue STL 2.2 ...

  2. Win11不在C盘安装WSL2(Linux环境),安装Nvidia驱动和默认使用Win11的网络代理服务

    众所周知,WSL 2 为 Windows 用户提供了一个强大.高效且灵活的 Linux 环境,特别适合开发者使用.它结合了 Windows 和 Linux 的优点,为用户提供了更加全面和高效的工作环境 ...

  3. 【MacOS】VMware安装10.15-Catalina版本

    参考自: https://www.bilibili.com/video/BV1sf4y1D77A?p=4 资源地址: https://pan.baidu.com/s/1U6WOorb_TuORQ9ab ...

  4. baselines算法库common/vec_env/util.py模块分析

    util.py模块代码: """ Helpers for dealing with vectorized environments. """ ...

  5. 使用django-treebeard实现树类型存储与编辑

    前言 其实之前做很多项目都有遇到跟树相关的功能,以前都是自己实现的,然后前端很多UI组件库都有Tree组件,套上去就可以用. 不过既然用 Django 了,还是得充分发挥一下生态的优势,但是我找了半天 ...

  6. C#.Net筑基-解密委托与事件

    委托与事件是C#中历史比较悠久的技术,从C#1.0开始就有了,核心作用就是将方法作为参数(变量)来传递和使用.其中委托是基础,需要熟练掌握,编程中常用的Lambda表达式.Action.Func都是委 ...

  7. 海豚调度调优 | 如何解决任务被禁用出现的Bug

    本系列文章是 DolphinScheduler 由浅入深的教程,涵盖搭建.二开迭代.核心原理解读.运维和管理等一系列内容.适用于想对 DolphinScheduler了解或想要加深理解的读者. 祝开卷 ...

  8. 023.Ubuntu常见个性化配置

    root登录设置 ubuntu默认关闭了root账户,可根据实际情况开启或关闭root登录. ubuntu@localhost:~$ sudo apt install openssh-server u ...

  9. 2023 ICPC 合肥游记

    board zsy 11.24 开始嗓子疼了,但可以忍受.晚上睡的很不舒服 11.25 起床就开始难受,还得骑车到地铁站,应该打个车来着.不过路上拍到了很好看的朝霞(写到这里才想起来还没发朋友圈给 t ...

  10. C语言实现url解析小实例

    一.前言 前面一口君写了一篇关于url的文章: <一文带你理解URI 和 URL 有什么区别?> 本篇在此基础上,编写一个简单的用于解析url的小例子, 最终目标是解析出URL中所有的数据 ...