登录  /  注册
首页 > web前端 > Vue.js > 正文

带你使用Vue搞定无法解决的“动态挂载”

青灯夜游
发布: 2022-09-02 20:30:55
转载
2161人浏览过

带你使用Vue搞定无法解决的“动态挂载”

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

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

无法解决的“动态挂载”

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

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

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

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

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

问题呢,是顺利解决了。

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

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

正式开启动态挂载

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

<div></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 &gt; 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.

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

  • 开启runtimeCompiler,在vue.config.js中加入runtimeCompiler: true的配置,允许运行时编译,这样可以动态生成template,满足动态组件的需求

  • 提前编译模板仅动态挂载,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 &gt; 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>
  </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 &gt; 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搞定无法解决的“动态挂载”的详细内容,更多请关注php中文网其它相关文章!

智能AI问答
PHP中文网智能助手能迅速回答你的编程问题,提供实时的代码和解决方案,帮助你解决各种难题。不仅如此,它还能提供编程资源和学习指导,帮助你快速提升编程技能。无论你是初学者还是专业人士,AI智能助手都能成为你的可靠助手,助力你在编程领域取得更大的成就。
相关标签:
来源:博客园网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
最新问题
关于CSS思维导图的课件在哪? 课件
凡人来自于2024-04-16 10:10:18
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2024 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号