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可以加载远程组件。远程组件就可以实现配置化,就可以脱离代码本身而进行前端的组件构建。
相关文章:

[转载] 七龙珠第一部——第004话 掳人的妖怪——乌龙
转载于:https://www.cnblogs.com/6DAN_HUST/archive/2013/04/07/3003566.html

如何解决资料下载下来为index.html和PHP文件的问题?
最近很多Down友反映,在下载中心下载资料时,明明是pdf、rar、zip格式的文件,下载完后怎么就变成index.html、php格式的文件了?既浪费了下载豆,文件还不能用,心疼啊!这是因为下载系统是动态获取的…

给大家推荐8个SpringBoot精选项目
前言 2017年,曾在自己的博客中写下这样一段话:有一种力量无人能抵挡,它永不言败生来倔强。有一种理想照亮了迷茫,在那写满荣耀的地方。 如今2018年已过大半,虽然没有大理想抱负,但是却有自己的小计划。下面…

点击Notification正确回调到之前已经放置在后台的Task中的对应Activity,而不是创建它的一个新实例...
NotificationManager notificationManager (NotificationManager)getSystemService(NOTIFICATION_SERVICE);Notification notification new Notification(R.drawable.logo_icon_16,"移动营销", System.currentTimeMillis());Intent intent new Intent(Intent.ACTI…

函数返回类的对象与拷贝构造函数
C中,如果我们在一个函数中,定义了一个类的对象,然后返回这个对象,在main函数中用一个对象去接受这个返回的对象的时候,这里面参与的函数调用大家可能不熟悉,这里通过程序和注释的方式给大家讲解一下。编译的…

ai条码插件免安装_ai条码插件2款下载|Barcode Toolbox插件+Barcode条码插件下载 - 偶要下载站...
本次一次性打包两款ai条码插件和大家分享,分别是Barcode Toolbox插件和Barcode脚本插件,支持Illustrator CS5~CC2015的条形码脚本!这两个插件不是一个插件,是有区别的两个插件。Barcode Toolbox是AI的一个非常有用的生成条码的插件…

GridView的DataKeyNames属性 转载的
偶今天用到这个了,转载 "事在人为"楼主的,原文地址: http://www.cnblogs.com/andhm/archive/2010/05/07/1730024.html DataKeyNames表示主键的列名,可以通过GridViewEntity.DataKeys[RowIndex]["ColumsName"]来获取他的值,当然它是…

反射 -- 通过字符串操作对象中的成员
getattr()setattr()hasattr()delattr()class C:def __init__(self, name):self.name namedef f(self):return Pythonobj C(Pyhton) get_name getattr(obj, name) get_func getattr(obj, f) get_func() hasattr(obj, name) setattr(obj, age, 10) delattr(obj, name)转载于:…

android默认exported_android:exported 属性详解
转自http://blog.csdn.net/watermusicyes/article/details/46460347昨天在用360扫描应用漏洞时,扫描结果,出来一个Android:exported属性,其实之前根本不知道这个属性,更不知道这个属性用来干嘛的,详情见下图࿱…

Chipset
Chipset 芯片组是一组集成电路(芯片)用于管理计算机处理器、内存和外设的数据流,通常位于主板上。 Northbridge (Memory Controller Hub) 北桥用来处理高速信号,负责CPU、RAM、AGP和PCI Express之间的通信。 Southbridge (I/O Con…

正确设置php-fpm和nginx防止网站被黑
2019独角兽企业重金招聘Python工程师标准>>> 核心总结:php-fpm 子进程所使用的用户,不能是网站文件所有者。 凡是违背这个原则,则不符合最小权限原则。 根据生产环境不断反馈,发现不断有 php网站被挂木马,绝…
一个数字键盘引发的血案——移动端H5输入框、光标、数字键盘全假套件实现...
https://juejin.im/post/5a44c5eef265da432d2868f6 为啥要写假键盘? 还是输入框、光标全假的假键盘? 手机自带的不用非得写个假的,吃饱没事干吧? 装逼?炫技? 宝宝也是被逼的,宝宝也很委屈~.~ …

姿态检测 树莓派_怎样在树莓派上轻松实现深度学习目标检测?
原标题:怎样在树莓派上轻松实现深度学习目标检测?雷锋网按:本文为 AI 研习社编译的技术博客,原标题 How to easily Detect Objects with Deep Learning on Raspberry Pi,作者为 Sarthak Jain。翻译 | 小哥哥 狒狒 校对…
Linux目录读写和可执行权限
一 . 进入目录权限如果我在普通用户下创建了一个目录f1,然后使用chomd u-rwx,g-rwx,o-rwx之后,我在普通用户下想进入f1目录,权限不允许。然后我切换到超级用户下,再次尝试进入到f1目录,这个时候允许进入。然后回到普通…

【译】表变量和临时表的比较(转)
关于表变量是什么(和表变量不是什么),以及和临时表的比较让很多人非常困惑。虽然网上已经有了很多关于它们的文章,但我并没有发现一篇比较全面的。在本篇文章中,我们将探索表变量和临时表是什么(以及不是什…

grub加密。
一、介绍 安全无小事 linux系统的安全分为很多方面,什么端口啊,什么网络啊,听着都特么烦,今天谈谈最简单明显的密码安全。 二、单用户模式 单用户模式个人觉得相当有用,可以用来修复系统,修改密码…… 但是…
Linux下stat + 文件名后, Access,Modify,Change的含义
我们首先在一个目录下创建了一个文件使用命令touch file然后输入命令:stat file,这个时候会输出一系列信息大家注意红色框中的三个时间Access : 文件最近一次被访问的时间Modify: 文件内容最近一次被修改的时间Change: 文件属性最近一次被改变的时间接着…

基于设计模式的学习之旅-----访问者模式(附源码)
基于设计模式的学习之旅-----访问者模式 1、初始访问者模式 2、什么是访问者模式 表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。 3、模式结构图 4、模式代码事例 场景:年会,每个小组表演…

x is y python_Python 基础
2.1 程序与用户交互在python3中#input:无论用输入何种类型,都会存成字符串类型nameinput(please input your name:) #name18print(id(name),type(name),name)在python2中#raw_input与python3的input是一样的nameraw_input(please input your name:)print…

【leetcode 简单】 第八十九题 赎金信
给定一个赎金信 (ransom) 字符串和一个杂志(magazine)字符串,判断第一个字符串ransom能不能由第二个字符串magazines里面的字符构成。如果可以构成,返回 true ;否则返回 false。 (题目说明:为了不暴露赎金信字迹,要从杂…
创建专属博客栏目
今天给大家get新技能了,是不是很期待捏我们一般看到的博客页面是这样的但是你是不是特别期待这样的捏其实技术上面也不是特别的 难,我们登录自己的csdn博客,然后选择“管理博客”,跳转页面之后选择“博客栏目”进入到这个页面之后…

《帝企鹅日记》观后感
第一次看到是在高中的英语周报上,那时候蛮好奇的,企鹅也写日记,呵呵,后来想了想应该是纪录片,时隔三年,发现当初的猜测果然不假。 我觉得那些企鹅很可爱,也很漂亮。最重要的是,那一条…

合并道路_资质改革已经确定!盘点被合并的资质!有这资质的要注意了
资质改革可以说是在行业里掀起了轩然大波,众多资质面临改革,有的资质被取消,有的资质被合并,有的资质继续保留。此文就带大家来盘点一下那些在近期资质定稿中被取消,被改变的资质:勘察资质勘察资质中&#…

如何为ccflow工作流引擎增加一个优先级PRI?
为什么80%的码农都做不了架构师?>>> 如何为ccflow工作流引擎增加一个优先级PRI? 对于一条流程的优先级可分为 低,中,高三个级别,用这个状态来标示这条流程的紧急程度。 以以前版本的ccflow中是以节点表…

SQL Server (MSSQLSERVER) 服务因 2148081668 服务性错误而停止。
https://zhidao.baidu.com/question/151448005.html 具体步骤:运行-> 输入:“services.msc” ->找到 “SQL Server (SQLEXPRESS)” 服务,双击 -> 在“SQL Server (SQLEXPRESS) 的属性”界面,点登录 -> 默认登录身份是…

面试题--特别是字节对齐
来源:http://www.cnblogs.com/Braveliu/archive/2013/01/04/2844757.html 【1】设置或者清除某位。 示例代码如下: 1 #include<iostream>2 using namespace std;3 4 #define BIT3 (0x1<<3)5 6 void Set_bit3(int &a)7 {8 a|BIT3;9 } 10 11…

vim基础入门
一. vim的三种模式在Linux操作系统下,我们一般会使用vim进行文本编辑,它相当于Windows下的记事本,但是它比记事本的功能强大的多。vim一般有三种模式分别是普通模式,编辑模式和命令模式。普通模式和编辑模式可以来回的切换&#x…

python html解析查找字符串_用python的BeautifulSoup分析html
序言之前用python爬取网页的时候,一直用的是regex或者自带的库sgmllib里的SGMLParser。但是遇到复杂一点的情况时,SGMLParser往往就不那么给力了!(哈,难道说我 too native了?毕竟beautifulSoup是继承sgmlparser的么~)所…

ejb 3中bean的种类
会话bean(session bean) 主要用来编写业务逻辑和对数据库进行操作,Session Bean用于实现业务逻辑,它分为有状态bean和无状态bean。每当客户端请求时,容器就会选择一个Session Bean来为客户端服务。Session Bean可以直接访问数据库࿰…

Android学习 —— 数据的存储与访问方式一: 文件存取
笔记摘要: 在Android中主要提供了四种数据存储与访问的方式,文件、SharedPreference(偏好参数保存)、SOLite数据库、内容提供者(Content provider)和网络, 本篇文章先介绍使用文件的方式进行数据…