前言:在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动态异步组件实现思路及其问题相关推荐

  1. vue 如何处理两个组件异步问题_Vue异步组件使用详解

    Vue的异步组件,供大家参考,具体内容如下 1.前置要求 建议使用webpack: Browserify在默认情况下不支持: 2.用法解释 首先上官网说明:异步组件 虽然说明是没问题的,但是示例中的写 ...

  2. vue 如何处理两个组件异步问题_Vue异步组件处理路由组件加载状态的解决方案...

    vue.js 组件 组件(Component)是 Vue.js 最强大的功能之一. 组件可以扩展 HTML 元素,封装可重用的代码. 在大型单页面应用中,处于对性能的考虑和首屏加载速度的要求,我们一般 ...

  3. vue怎么调用子元素的方法_vue.js 父组件如何触发子组件中的方法

    文章目录 组件 组件 (Component) 是 Vue.js 最强大的功能之一.组件可以扩展 HTML 元素,封装可重用的代码.在较高层面上,组件是自定义元素,Vue.js 的编译器为它添加特殊功能 ...

  4. vue rules 两个输入框不能相等_Vue 学习笔记(二十五):webpack 相关

    Webpack 是什么 Vue CLI Webpack 相关 Webpack 更多参考官方文档 Webpack 是一个前端资源加载/打包工具.它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定 ...

  5. Vue3 父传子、使用 defineAsyncComponent 异步挂载组件、利用 is 动态引入组件

    1.父组件 index.vue defineAsyncComponent 是 Vue3 的异步挂载 <template><div v-for="v in nav_items ...

  6. vue中父子组件先后渲染_Vue中父子组件执行的先后顺序

    前几天,朋友向我提出了一个关于Vue中父子组件执行的先后顺序问题,相信很多朋友在学习的过程中也会遇到这个问题,所以我就在此提出我自己的一些小看法. 问题如下:请问下图中父子组件执行的先后顺序? 首先, ...

  7. 【Vue】动态添加组件的两种实现

    在Vue项目中,想要动态为页面上添加组件,是一件十分容易就能够实现的事情,这必须要得益于Vue框架的强力支持! 但有时候往往就是由于事情变得简单起来后,却突然忘记了要如何去实现.这大概就是对代码走火入 ...

  8. vue 父组件获取接口值传到子组件_vue父组件异步获取数据传给子组件的方法

    但是现在问题是父组件的数据是异步获取的,而子组件一开始就会渲染,如果此时没有传入数据,而子组件又要用到数据中的length属性时就会报错: 怎么办呢?最简单的办法就是让子组件条件渲染,当有数据的时候才 ...

  9. vue 父组件获取接口值传到子组件_vue 项目中 “父组件” 异步获取数据之后,传递给子组件不显示...

    有两个组件:一个为 transaction(父组件),一个为 transactionList (子组件): 上图为一个列表页,为父组件,在父组件里面的data中定义了数据列表, template中: ...

最新文章

  1. Mybatis注解学习记录
  2. 基于px2rpx-loader,探讨一下loader的封装思想
  3. LINUX 第五章 apache php mysql
  4. 渲染到ui_虚幻4渲染编程(UI篇)【第二卷:程序化UI特效-[1]】
  5. BZOJ 1051 受欢迎的牛(Tarjan缩点)
  6. 几家OA厂商介绍及产品特点总结
  7. TenSorFlow随笔-除法
  8. android应用程序开发_深圳app开发公司:跨平台应用程序开发工具有哪些?
  9. environment variable
  10. 湖南大学计算机学院张柏杨,缪力-湖大信息科学与工程学院
  11. datastage odbc mysql,Linux系统odbc配置实现Datastage8.x连接mssqlserver数据库
  12. 如何在脱敏数据中使用BERT等预训练模型
  13. VMware 虚拟机安装
  14. c语言程序设计第4版pdf荣政_C语言程序设计 PDF 第4版
  15. mac上SCRT中文变问号的处理方式,亲测有效
  16. HEVC和AV1幕后视频编解码器之战
  17. 网络原理考试到ADSL上网原理
  18. 欢迎清风艾艾在ITPUB博客安家!
  19. Property dataSource threw exception
  20. Python绘制节点是饼状图的社交网络图(Plot network with pie chart)

热门文章

  1. Unity Android 2021:用C#打造3D ZigZag赛车游戏
  2. Appium+python自动化(八)- 初识琵琶女Appium(千呼万唤始出来,犹抱琵琶半遮面)- 下(超详解)...
  3. [mqtt]mqtt嵌入式移植
  4. 大型技术网站的技术( 高并发、大数据、高可用、分布式....)(一)
  5. 使用SQLite删除Mac OS X 中launchpad里的快捷方式
  6. nRF51800 蓝牙学习 进程记录 2:关于二维数组 执念执战
  7. hiho_1139_二分+bfs搜索
  8. Linux UserSpace Back-Door、Rootkit SSH/PAM Backdoor Attack And Defensive Tchnology
  9. 【T-SQL】基础——表别名
  10. 最近想做个音乐共享的软件