在一些特殊场景下,使用组件的时机无法确定,或者无法在Vue的template中确定要我们要使用的组件,这时就需要动态的挂载组件,或者使用运行时编译动态创建组件并挂载。

今天我们将带大家从实际项目出发,看看在实际解决客户问题时,如何将组件进行动态挂载,并为大家展示一个完整的解决动态挂载问题的完整过程。

无法解决的“动态挂载”

我们的电子表格控件SpreadJS在运行时,存在这样一个功能:当用户双击单元格会显示一个输入框用于编辑单元格的内容,用户可以根据需求按照自定义单元格类型的规范自定义输入框的形式,集成任何Form表单输入类型。

这个输入框的创建销毁都是通过继承单元格类型对应方法实现的,因此这里就存在一个问题——这个动态的创建方式并不能简单在VUE template中配置,然后直接使用。

而就在前不久,客户问然询问我:你家控件的自定义单元格是否支持Vue组件比如ElementUI的AutoComplete?

由于前面提到的这个问题:

沉思许久,我认真给客户回复:“组件运行生命周期不一致,用不了”,但又话锋一转,表示可以使用通用组件解决这个问题。

问题呢,是顺利解决了。

但是这个无奈的"用不了",却也成为我这几天午夜梦回跨不去的坎。

后来,某天看Vue文档时,我想到App是运行时挂载到#app上的。,从理论上来说,其他组件也应该能动态挂载到需要的Dom上,这样创建时机的问题不就解决了嘛!

正式开启动态挂载

让我们继续查看文档,全局APIVue.extend( options )是通过extend创建的。Vue实例可以使用$mount方法直接挂载到DOM元素上——这正是我们需要的。

<div id="mount-point"></div>// 创建构造器
var Profile = Vue.extend({template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',data: function () {return {firstName: 'Walter',lastName: 'White',alias: 'Heisenberg'}}
})
// 创建 Profile 实例,并挂载到一个元素上。
new Profile().$mount('#mount-point')

按照SpreadJS自定义单元格示例创建AutoCompleteCellType,并设置到单元格中:

function AutoComplateCellType() {
}
AutoComplateCellType.prototype = new GC.Spread.Sheets.CellTypes.Base();
AutoComplateCellType.prototype.createEditorElement = function (context, cellWrapperElement) {
//   cellWrapperElement.setAttribute("gcUIElement", "gcEditingInput");cellWrapperElement.style.overflow = 'visible'let editorContext = document.createElement("div")editorContext.setAttribute("gcUIElement", "gcEditingInput");let editor = document.createElement("div");// 自定义单元格中editorContext作为容器,需要在创建一个child用于挂载,不能直接挂载到editorContext上editorContext.appendChild(editor);return editorContext;
}
AutoComplateCellType.prototype.activateEditor = function (editorContext, cellStyle, cellRect, context) {let width = cellRect.width > 180 ? cellRect.width : 180;if (editorContext) {// 创建构造器var Profile = Vue.extend({template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',data: function () {return {firstName: 'Walter',lastName: 'White',alias: 'Heisenberg'}}})// 创建 Profile 实例,并挂载到一个元素上。new Profile().$mount(editorContext.firstChild);}
};

运行,双击进入编辑状态,结果却发现报错了

[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

根据报错提示,此时候我们有两种解决办法:

  1. 开启runtimeCompiler,在vue.config.js中加入runtimeCompiler: true的配置,允许运行时编译,这样可以动态生成template,满足动态组件的需求
  2. 提前编译模板仅动态挂载,autocomplete的组件是确定的,我们可以使用这种方法

新建AutoComplete.vue组件用于动态挂载,这样可以挂载编译好的组件。

<template><div><p>{{ firstName }} {{ lastName }} aka {{ alias }}</p></div>
</template>
<script>
export default {data: function () {return {firstName: "Walter",lastName: "White",alias: "Heisenberg",};},
};
</script>import AutoComplate from './AutoComplate.vue'AutoComplateCellType.prototype.activateEditor = function (editorContext, cellStyle, cellRect, context) {let width = cellRect.width > 180 ? cellRect.width : 180;if (editorContext) {// 创建构造器var Profile = Vue.extend(AutoComplate);// 创建 Profile 实例,并挂载到一个元素上。new Profile().$mount(editorContext.firstChild);}
};

双击进入编辑状态,看到组件中的内容

下一步,对于自定义单元格还需要设置和获取组件中的编辑内容,这时通过给组件添加props,同时在挂载时创建的VueComponent实例上直接获取到所有props内容,对应操作即可实现数据获取设置。

更新AutoComplate.vue,添加props,增加input用于编辑

<template><div><p>{{ firstName }} {{ lastName }} aka {{ alias }}</p><input type="text" v-model="value"></div>
</template>
<script>
export default {props:["value"],data: function () {return {firstName: "Walter",lastName: "White",alias: "Heisenberg",};},
};
</script>

通过this.vm存储VueComponent实例,在getEditorValue 和setEditorValue 方法中获取和给VUE组件设置Value。编辑结束,通过调用$destroy()方法销毁动态创建的组件。

AutoComplateCellType.prototype.activateEditor = function (editorContext, cellStyle, cellRect, context) {let width = cellRect.width > 180 ? cellRect.width : 180;if (editorContext) {// 创建构造器var Profile = Vue.extend(MyInput);// 创建 Profile 实例,并挂载到一个元素上。this.vm = new Profile().$mount(editorContext.firstChild);}
};AutoComplateCellType.prototype.getEditorValue = function (editorContext) {// 设置组件默认值if (this.vm) {return this.vm.value;}
};
AutoComplateCellType.prototype.setEditorValue = function (editorContext, value) {// 获取组件编辑后的值if (editorContext) {this.vm.value = value;}
};
AutoComplateCellType.prototype.deactivateEditor = function (editorContext, context) {// 销毁组件this.vm.$destroy();this.vm = undefined;
};

整个流程跑通了,下来只需要在AutoComplate.vue中,将input替换成ElementUI 的el- autocomplete并实现对应方法就好了。

结果

让我们看看效果吧。

其实动态挂载并不是什么复杂操作,理解了Vue示例,通过vm来操作实例,灵活的运用动态挂载或者运行时编译的组件就不是什么难事了。

其实一切的解决方案就在Vue教程入门教程中,但是脚手架的使用和各种工具的使用让我们忘记了Vue的初心,反而把简单问题复杂化了。

今天的分享到这里就结束啦,后续还会为大家带来更多严肃和有趣的内容~

你有什么在开发中"忘记初心"的事情吗?

灵光一闪!帮你使用Vue,搞定无法解决的“动态挂载”相关推荐

  1. excel中如何动态地创建控件以显示查询结果_年终汇报,Excel图表真难搞?80份可视化图表帮你10秒搞定...

    最近分享了20个EXCEL图表的详细制作方法,这些图表是我在工作中经常用到的,因为工作中要处理大量的数据,常常要做PPT向领导汇报工作,有时接到通知就要汇报了,给我们的只有准备会场和通知参会人员的时间 ...

  2. 【AI公司酷05期】美宅科技:独创人工智能室内设计引擎,帮你3秒搞定装修方案,要用AI赋能家居新零售

    作者|震霆   出品|遇见人工智能  公众号 GOwithAI [AI公司酷05期]美宅科技--家居新零售领导者,全球独创人工智能室内设计引擎--图灵猫,受邀参加2017年1月11美国硅谷全球人工智能 ...

  3. 重磅教程!帮你全面彻底搞定Material design的学习笔记

    http://www.uisdc.com/comprehensive-material-design-note 转载于:https://www.cnblogs.com/520-1314/p/52529 ...

  4. word被锁定无法编辑怎么解锁_Word论文里的公式怎么编辑?这4个小工具帮你一分钟搞定!...

    临近毕业时,不少小可爱都在为论文头秃!搜索并下载论文,论文排版,论文查重,这些我们之前已经写过相关文章啦!今天,再来给大家分享一个写论文时经常会遇到的难题!它就是论文里的公式:(来自网友的吐槽)大家吐 ...

  5. (建议收藏)万字长文,帮你一招搞定产品经理面试-详解产品经理面试大全

    ​ 前言 产品经理这个岗位由于其特殊性,在面试当中往往不能够以技术性的题目来衡量,也因其涉猎的范围广泛,所以在准备面试时必须面面俱到,才能够胸有成竹. 博主从个人方面.公司方面.项目方面.产品基础知识 ...

  6. 电脑word在哪_Word论文里的公式怎么编辑?这4个小工具帮你一分钟搞定!

    临近毕业时,不少小可爱都在为论文头秃! 搜索并下载论文,论文排版,论文查重,这些我们之前已经写过相关文章啦! Tools指南推荐搜索论文论文排版论文查重论文网站 今天,再来给大家分享一个写论文时经常会 ...

  7. 新系统如何测试软件,怎样检测电脑能否升级到最新的Windows11系统?官方检测工具帮你一招搞定!...

    日前,微软正式发布了Windows11系统,新的Windows11操作系统不仅采用了全新的居中设计的开始键以及任务栏,同时还取消了Windows8引入的实时磁贴设计,取而代之的是最近文档.应用程序以及 ...

  8. 复制网站部分内容_这些网站帮你十分钟搞定年终报告/合同/公文/策划写作!

    恰逢春节之际,网易云.支付宝.微信等互联网公司都纷纷赶在除夕前发布了年终报告. 看到这些精美的H5页面,在感叹设计文案的奇思妙手时,许多人也陷入一番苦恼中--自己的述职报告和年终总结写些啥? 今天,我 ...

  9. 图片太大怎么办?压缩图帮你几秒搞定在线图片压缩

    说到图片压缩(https://www.yasuotu.com/),对于经常使用图片的小伙伴们来说一定都不陌生,大家在使用图片的时候难免会遇到图片大小超过限制没法使用的情况,对于一些超过限制不多的图片, ...

最新文章

  1. 树莓派3b python3.6.1 SSL模块调用不起来的坑
  2. myloader原理解析
  3. java 微分方程求解_Java中的微分方程
  4. mysql为什么要编译安装_Mysql编译安装
  5. 随机森林原理详解及python代码实现
  6. fastdfs 吗 支持windows_主流开源文件存储系统-fastdfs是否支持windows?你可以选择minio...
  7. 史上最烧脑的学习方法,看完瞬间涨姿势!
  8. python (高级消息队列)普通、进程、进程池的消息队列
  9. oracle查找clob中的值,Oracle 查找带有CLOB字段的所有表
  10. 3.sf2 核心目录及文件结构
  11. 一文带你了解手机运营商类api接口
  12. 毕业设计源码——旅游打卡小程序
  13. SRT公网点对点传输及搭建SRT流媒体服务器
  14. 自用软件系列之:迅雷X ,无广告,纯净版
  15. php soap wsse,改变xmlns:wsse命名空间在使用Python Zeep的SOAP请求中
  16. 【论文精读】Deep Defocus Map Estimation using Domain Adaptation-2019CVPR
  17. mmdetection训练自己的COCO数据集及常见问题
  18. 一、<a>标签如何实现下载
  19. Asp.net Core 自带DI依赖注入
  20. Cause: java.sql.SQLException: connection closed问题排查、解决

热门文章

  1. 怎样架设传奇 30分钟学会传奇架设;画面精美大气的战神冰雪传奇,时下最流行的微端搭建设技术分享
  2. gif透明背景动画_Gif 编辑器合集
  3. G4900 win7 显卡驱动 下载 G5400 win7显卡驱动下载
  4. antd使用craco的按需引入、主题定制最新版
  5. 255%可用已接通电源_现货UPS不间断电源报价性价比超高
  6. defy 超频/降频CPU设置
  7. 研究区域制图 | 在 ArcGIS Pro中创建地图布局
  8. python查询手机号
  9. 彩虹显IP QQ动了谁的奶酪?
  10. Python tkinter实现计算器