灵光一闪!帮你用Vue解决无法解决的“动态挂载”
在一些特殊场景下,无法确定使用组件的时机,或者无法在Vue模板中确定我们要使用的组件。这时候动态的,或者使用运行时编译,动态创建组件并挂载。今天我们就带大家从实际项目出发,看看在实际解决客户问题时如何动态挂载组件,为大家展示一个解决动态挂载问题的完整流程。无法解决的“动态挂载”当我们的电子表格控件SpreadJS运行时,有这样一个功能:当用户双击单元格时,会显示一个输入框,用于编辑单元格的内容,用户可以根据需要自定义单元格到需要。类型规范定义了输入框的形式,集成了任意Form表单输入类型。这个输入框的创建和销毁是通过继承cell类型对应的方法来实现的,所以这里有个问题——这种动态创建的方法不能简单的在VUE模板中配置,然后直接使用。而且前不久客户问我:你们控件的自定义cell支持ElementUI的AutoComplete等V??ue组件吗?由于上面提到的问题:想了半天,认真的回复客户:“组件运行生命周期不一致,不能用”,后来话锋一转,说这个问题可以通过使用来解决通用组件。问题成功解决。但这种无奈的“不能用”也成了这几天我无法逾越的一道坎。后来某天看vue的文档,想到app是在运行时挂载在#app上的,理论上其他组件也应该动态挂载到需要的Dom上,这样创建时机的问题就解决了!正式开启动态挂载我们继续看文档,全局的APIVue.extend(options)是通过extend创建的。Vue实例可以使用$mount方法直接挂载到DOM元素上——这正是我们所需要的。
//创建构造函数varProfile=Vue.extend({template:'
{{firstName}}{{lastName}}aka{{alias}}}}}p>',data:function(){return{firstName:'Walter',lastName:'White',alias:'Heisenberg'}}})//创建一个Profile实例并将其附加到一个元素。newProfile().$mount('#mount-point')根据SpreadJS自定义单元格示例创建AutoCompleteCellType,并设置到单元格中:functionAutoComplateCellType(){}AutoComplateCellType.prototype=newGC.Spread.Sheets.CellTypes.Base();AutoComplateCellType.prototype.createEditorElement=function(context,cellWrapperElement){//cellWrapperElement.setAttribute("gcUIElement","gcEditingInput");cellWrapperElement.style.overflow='visible'leteditorContext"=document.createElement(div")editorContext.setAttribute("gcUIElement","gcEditingInput");让editor=document.createElement("div");//自定义cell中的editorContext作为容器,需要创建child进行挂载,不能直接挂载到editorContexteditorContext.appendChild(editor);returneditorContext;}AutoComplateCellType.prototype.activateEditor=function(editorContext,cellStyle,cellRect,context){让宽度=cellRect.width>180?cellRect.width:180;if(editorContext){//创建构造函数varProfile=Vue.extend({template:'
{{firstName}}{{lastName}}aka{{alias}}
',data:function(){return{firstName:'Walter',lastName:'White',别名:'Heisenberg'}}})//创建一个Profile实例并将其挂载到一个元素上newProfile().$mount(editorContext.firstChild);}};运行,双击进入编辑状态,却发现报错。根据报错信息,我们此时有两种解决方案:启用runtimeCompiler,在vue.config.js中添加runtimeCompiler:true配置,允许运行时编译,这样可以动态生成模板,满足动态组件的需要编译模板预先并且只动态挂载,自动完成组件是确定的,我们可以使用这个方法新建一个AutoComplete.vue组件进行动态挂载,这样编译好的组件就可以挂载了。
{{firstName}}{{lastName}}aka{{alias}}
从'./AutoComplate.vue'导入AutoComplateAutoComplateCellType.prototype.activateEditor=function(editorContext,cellStyle,cellRect,context){letwidth=cellRect.width>180?cellRect.width:180;if(editorContext){//创建构造函数varProfile=Vue.extend(AutoComplate);//创建一个Profile实例并将其挂载到一个元素上。新配置文件()。$装载(editorContext.firstChild);}};双击进入编辑状态,可以看到组件中的内容。接下来,对于自定义单元格,需要在组件中设置和获取编辑内容。此时,通过组件添加props,同时在挂载时创建的VueComponent实例上可以直接获取所有的props内容,相应的操作即可实现数据获取设置。更新AutoComplate.vue,添加道具,添加用于编辑的输入
{{firstName}}{{lastName}}aka{{alias}}
通过this.vm存储VueComponent实例,在getEditorValue和setEditorValue方法中获取和设置VUE组件的Value。编辑完成后,通过调用$destroy()方法销毁动态创建的组件。AutoComplateCellType.prototype.activateEditor=function(editorContext,cellStyle,cellRect,context){让宽度=cellRect.width>180?cellRect.width:180;if(editorContext){//创建构造函数varProfile=Vue.extend(MyInput);//创建一个Profile实例并将其附加到一个元素。this.vm=newProfile().$mount(editorContext.firstChild);}};AutoComplateCellType.prototype.getEditorValue=function(editorContext){//设置组件的默认值if(this.vm){returnthis.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的初衷,而是把简单的问题复杂化了。今天的分享到这里就结束了,接下来我们会为大家带来更多严肃有趣的内容~大家在开发中有没有“忘初心”的情况呢?