vue 如何处理两个组件异步问题_Vue动态异步组件实现思路及其问题
前言:在vue
官方资料中,我们可以可以很学会如何通过vue构建“动态组件”以及“异步组件”,然而,在官方资料中,并没有涉及到真正的“动态异步”组件,经过大量的时间研究和技术分析,我们给出目前比较合理的技术实现方式,并分析一下vue动态异步组件的实现思路。
动态/异步组件的问题
官网中介绍,动态组件是通过tagcomponent来构建,在当中绑定组件的引用即可,大致代码如下:
import compA from './CompA';
import compB from './CompB';
import compC from './CompC';
export default {
data () {
return {
currentComp: compA
}
},
methods: {
changeComp (name) {
switch (name) {
case 'compA' : {
this.currentComp = compA;
break;
case 'compB' :
this.currentComp = compB;
break;
case 'compC' :
this.currentComp = compC;
break;
default :
this.currentComp = compA;
break;
}
}
}
}
简单说明一下,通过对字符串的判断,来切换组件的实例,实例发生变化后,component组件会自动切换。这就是vue中最基本的动态组件。但是,这样的代码有个很显著的问题:
所有的组件都是写死的,比如在代码层面上提前定义,即代码5-7行;
组件的引入是同步的,即便compB和compC在一开始没渲染,但组件的内存已经被加载;
对于第二点,我们可以很容易的使用require或者import语法来进行异步加载。然而这并没有解决问题1所带来的隐患。按照实际的要求,我们需要一个可以在客户端随意配置的组件,即通过组件的地址或配置在进行动态加载的方式。这就是为什么要进行动态异步组件的构建。
这种构建方式是刚需的,一方面他可以构筑类似portal中的porlet组件,另一方面,他的实现方式将给组件加载带来巨大的提升。
构建AsyncComponent
首先,我们看一下预期的结果,我们希望构建如下的代码模式:
因此,我们创建一个AsyncComponent.vue文件,并书写代码:
export default {
props: {
path: {
type: String,
required: true,
default: () => null
}
},
data () {
const componentFile = this.render;
return {
componentFile: componentFile
}
},
methods: {
render () {
this.componentFile = (resolve) => ({
component: import(`@/${this.path}`),
loading: { template: '
' },
error: { template: '
' },
delay: 200,
timeout: 10000
});
}
},
watch: {
file () {
this.render();
}
}
}
这个代码很好解释:
组件中传入path属性,构建时候通过render函数创建异步组件;
render函数为官网的异步组件构建方式;
监控path属性,当发生变化时,重新通过render函数构建;
为了能够让组件可被重新激活,并且重用性更高,我们对组件进行更多的参数化,最终结果如下:
:is="AsyncComponent"
v-bind="$attrs"
v-on="$listeners"/>
v-else
:is="AsyncComponent"
v-bind="$attrs"
v-on="$listeners"/>
import factory from './factory.js';
/**
* 动态文件加载器
*/
export default {
inheritAttrs: false,
// 外部传入属性
props: {
// 文件的路径
path: {
type: String,
default: null
},
// 是否保持缓存
keepAlive: {
type: Boolean,
required: false,
default: true
},
// 延迟加载时间
delay: {
type: Number,
default: 20
},
// 超时警告时间
timeout: {
type: Number,
default: 2000
}
},
data () {
return {
// 构建异步组件 - 懒加载实现
AsyncComponent: factory(this.path, this.delay, this.timeout)
}
},
watch: {
path () {
this.AsyncComponent = factory(this.path, this.delay, this.timeout);
}
},
methods: {
load (path = this.path) {
this.AsyncComponent = factory(path, this.delay, this.timeout);
}
}
}
具体改动如下:
代码第2行增加keep-alive配置,可让组件持久化;
代码第5行增加属性绑定,可让异步渲染的组件通过外部(async-componenttag)传参;
代码第6行增加事件绑定,可让异步渲染的组件通过外部(async-componenttag)进行事件监听;
代码16行为封装异步组件构造器factory(工厂模式),可暴露出去方便其他开发者使用;
factory函数增加加载组件、错误组件、未定义组件的封装;
增加了delay、timeout配置;
暴露了load函数,方便外部JavaScript调用;
至此,我们可以通过来构建组件,如果path是一个传入属性,通过改变该属性触发watch来重新加载新组件。或者给该组件添加ref属性来获取异步组件容器,通过调用load方法来重新装载。
后续的问题
看上去,现在的封装已经非常好,但是距离完美还差很大一截。虽然已经解决了开发人员重复造轮子的问题,并优化了最佳的代码模式,然而我们仍然能发现一个问题:ref之后,拿到的是AsyncComponent组件,并非能像tag一样可以直接对内部组件进行获取。如果按照这样的理想去思考,有利也是有弊的。利是我们构建出了tag的动态异步版,弊是AsyncComponent作为容器的属性很容易被内部的装载物所替换,比如load方法。
且不考虑这样实现之后的问题,我们可以在开发过程中通过约束来避免,代码中也可以增加属性检测机制。但这样的实现方式非常困难,我尝试过如下方式,均不能实现:
函数式组件: 通过添加
functional: true可以把一个组件函数化,这样使得该组件无法获取到
this即组件实例,因此他所挂载的就是内部的装载组件。然而在构建过程中,出现了无限递归
render函数的问题,无法解决,而且
createElement函数无法创建空节点,导致组件总会出现一个不必要的标签。
抽象化组件: 通过添加abstract: true可以把一个组件抽象化,这样组件是无法渲染其自身,而只会挂在内部的装载组件。但这样做之后,会导致外部容器无法通过ref属性查找到它,更无法获取到装载组件,因此也以失败告终。
继承式组件: 通过添加extends可以在构建AsyncComponent的时候实现继承,这样装载组件的属性都会传入到AsyncComponent中,然而,这样的方式不支持动态继承,所以还是宣告失败。
虽然都是失败的结果,但这并不能停止我们的想象,相信未来会有方法来解决这个问题。目前,我们还只能老老实实的把AsyncComponent当做容器来使用。
动态异步的未来
你要问我动态异步组件的未来是什么,我会告诉你我们的梦想有多大。我们希望实现分布式前端UIServer,让AsyncComponent可以加载远程组件。远程组件就可以实现配置化,就可以脱离代码本身而进行前端的组件构建。
vue 如何处理两个组件异步问题_Vue动态异步组件实现思路及其问题相关推荐
- vue 如何处理两个组件异步问题_Vue异步组件使用详解
Vue的异步组件,供大家参考,具体内容如下 1.前置要求 建议使用webpack: Browserify在默认情况下不支持: 2.用法解释 首先上官网说明:异步组件 虽然说明是没问题的,但是示例中的写 ...
- vue 如何处理两个组件异步问题_Vue异步组件处理路由组件加载状态的解决方案...
vue.js 组件 组件(Component)是 Vue.js 最强大的功能之一. 组件可以扩展 HTML 元素,封装可重用的代码. 在大型单页面应用中,处于对性能的考虑和首屏加载速度的要求,我们一般 ...
- vue怎么调用子元素的方法_vue.js 父组件如何触发子组件中的方法
文章目录 组件 组件 (Component) 是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码.在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能 ...
- vue rules 两个输入框不能相等_Vue 学习笔记(二十五):webpack 相关
Webpack 是什么 Vue CLI Webpack 相关 Webpack 更多参考官方文档 Webpack 是一个前端资源加载/打包工具.它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定 ...
- Vue3 父传子、使用 defineAsyncComponent 异步挂载组件、利用 is 动态引入组件
1.父组件 index.vue defineAsyncComponent 是 Vue3 的异步挂载 <template><div v-for="v in nav_items ...
- vue中父子组件先后渲染_Vue中父子组件执行的先后顺序
前几天,朋友向我提出了一个关于Vue中父子组件执行的先后顺序问题,相信很多朋友在学习的过程中也会遇到这个问题,所以我就在此提出我自己的一些小看法. 问题如下:请问下图中父子组件执行的先后顺序? 首先, ...
- 【Vue】动态添加组件的两种实现
在Vue项目中,想要动态为页面上添加组件,是一件十分容易就能够实现的事情,这必须要得益于Vue框架的强力支持! 但有时候往往就是由于事情变得简单起来后,却突然忘记了要如何去实现.这大概就是对代码走火入 ...
- vue 父组件获取接口值传到子组件_vue父组件异步获取数据传给子组件的方法
但是现在问题是父组件的数据是异步获取的,而子组件一开始就会渲染,如果此时没有传入数据,而子组件又要用到数据中的length属性时就会报错: 怎么办呢?最简单的办法就是让子组件条件渲染,当有数据的时候才 ...
- vue 父组件获取接口值传到子组件_vue 项目中 “父组件” 异步获取数据之后,传递给子组件不显示...
有两个组件:一个为 transaction(父组件),一个为 transactionList (子组件): 上图为一个列表页,为父组件,在父组件里面的data中定义了数据列表, template中: ...
最新文章
- Mybatis注解学习记录
- 基于px2rpx-loader,探讨一下loader的封装思想
- LINUX 第五章 apache php mysql
- 渲染到ui_虚幻4渲染编程(UI篇)【第二卷:程序化UI特效-[1]】
- BZOJ 1051 受欢迎的牛(Tarjan缩点)
- 几家OA厂商介绍及产品特点总结
- TenSorFlow随笔-除法
- android应用程序开发_深圳app开发公司:跨平台应用程序开发工具有哪些?
- environment variable
- 湖南大学计算机学院张柏杨,缪力-湖大信息科学与工程学院
- datastage odbc mysql,Linux系统odbc配置实现Datastage8.x连接mssqlserver数据库
- 如何在脱敏数据中使用BERT等预训练模型
- VMware 虚拟机安装
- c语言程序设计第4版pdf荣政_C语言程序设计 PDF 第4版
- mac上SCRT中文变问号的处理方式,亲测有效
- HEVC和AV1幕后视频编解码器之战
- 网络原理考试到ADSL上网原理
- 欢迎清风艾艾在ITPUB博客安家!
- Property dataSource threw exception
- Python绘制节点是饼状图的社交网络图(Plot network with pie chart)
热门文章
- Unity Android 2021:用C#打造3D ZigZag赛车游戏
- Appium+python自动化(八)- 初识琵琶女Appium(千呼万唤始出来,犹抱琵琶半遮面)- 下(超详解)...
- [mqtt]mqtt嵌入式移植
- 大型技术网站的技术( 高并发、大数据、高可用、分布式....)(一)
- 使用SQLite删除Mac OS X 中launchpad里的快捷方式
- nRF51800 蓝牙学习 进程记录 2:关于二维数组 执念执战
- hiho_1139_二分+bfs搜索
- Linux UserSpace Back-Door、Rootkit SSH/PAM Backdoor Attack And Defensive Tchnology
- 【T-SQL】基础——表别名
- 最近想做个音乐共享的软件