关于javascript:灵光一闪帮你使用Vue搞定无法解决的动态挂载

在一些非凡场景下,应用组件的机会无奈确定,或者无奈在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);
    }
};

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

依据报错提醒,此时候咱们有两种解决办法:

  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的初心,反而把简略问题复杂化了。

明天的分享到这里就完结啦,后续还会为大家带来更多庄重和乏味的内容~

你有什么在开发中”遗记初心”的事件吗?

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理