溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么使用Vue解決動(dòng)態(tài)掛載

發(fā)布時(shí)間:2022-09-05 09:58:28 來(lái)源:億速云 閱讀:280 作者:iii 欄目:編程語(yǔ)言

今天小編給大家分享一下怎么使用Vue解決動(dòng)態(tài)掛載的相關(guān)知識(shí)點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識(shí),所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來(lái)了解一下吧。

無(wú)法解決的“動(dòng)態(tài)掛載”

我們的電子表格控件SpreadJS在運(yùn)行時(shí),存在這樣一個(gè)功能:當(dāng)用戶雙擊單元格會(huì)顯示一個(gè)輸入框用于編輯單元格的內(nèi)容,用戶可以根據(jù)需求按照自定義單元格類型的規(guī)范自定義輸入框的形式,集成任何Form表單輸入類型。

這個(gè)輸入框的創(chuàng)建銷毀都是通過(guò)繼承單元格類型對(duì)應(yīng)方法實(shí)現(xiàn)的,因此這里就存在一個(gè)問(wèn)題——這個(gè)動(dòng)態(tài)的創(chuàng)建方式并不能簡(jiǎn)單在VUE template中配置,然后直接使用。

而就在前不久,客戶問(wèn)然詢問(wèn)我:你家控件的自定義單元格是否支持Vue組件比如ElementUI的AutoComplete?

由于前面提到的這個(gè)問(wèn)題:

怎么使用Vue解決動(dòng)態(tài)掛載

沉思許久,我認(rèn)真給客戶回復(fù):“組件運(yùn)行生命周期不一致,用不了”,但又話鋒一轉(zhuǎn),表示可以使用通用組件解決這個(gè)問(wèn)題。

問(wèn)題呢,是順利解決了。

但是這個(gè)無(wú)奈的"用不了",卻也成為我這幾天午夜夢(mèng)回跨不去的坎。

后來(lái),某天看Vue文檔時(shí),我想到App是運(yùn)行時(shí)掛載到#app上的。,從理論上來(lái)說(shuō),其他組件也應(yīng)該能動(dòng)態(tài)掛載到需要的Dom上,這樣創(chuàng)建時(shí)機(jī)的問(wèn)題不就解決了嘛!

正式開啟動(dòng)態(tài)掛載

讓我們繼續(xù)查看文檔,全局APIVue.extend( options )是通過(guò)extend創(chuàng)建的。Vue實(shí)例可以使用$mount方法直接掛載到DOM元素上——這正是我們需要的。

<div id="mount-point"></div>
 
// 創(chuàng)建構(gòu)造器
var Profile = Vue.extend({
  template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
  data: function () {
    return {
      firstName: 'Walter',
      lastName: 'White',
      alias: 'Heisenberg'
    }
  }
})
// 創(chuàng)建 Profile 實(shí)例,并掛載到一個(gè)元素上。
new Profile().$mount('#mount-point')

按照SpreadJS自定義單元格示例創(chuàng)建AutoCompleteCellType,并設(shè)置到單元格中:

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作為容器,需要在創(chuàng)建一個(gè)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) {
      // 創(chuàng)建構(gòu)造器
      var Profile = Vue.extend({
        template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
        data: function () {
          return {
            firstName: 'Walter',
            lastName: 'White',
            alias: 'Heisenberg'
          }
        }
      })
      // 創(chuàng)建 Profile 實(shí)例,并掛載到一個(gè)元素上。
      new Profile().$mount(editorContext.firstChild);
    }
};

運(yùn)行,雙擊進(jìn)入編輯狀態(tài),結(jié)果卻發(fā)現(xiàn)報(bào)錯(cuò)了

[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.

根據(jù)報(bào)錯(cuò)提示,此時(shí)候我們有兩種解決辦法:

  • 開啟runtimeCompiler,在vue.config.js中加入runtimeCompiler: true的配置,允許運(yùn)行時(shí)編譯,這樣可以動(dòng)態(tài)生成template,滿足動(dòng)態(tài)組件的需求

  • 提前編譯模板僅動(dòng)態(tài)掛載,autocomplete的組件是確定的,我們可以使用這種方法

新建AutoComplete.vue組件用于動(dòng)態(tài)掛載,這樣可以掛載編譯好的組件。

<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) {
      // 創(chuàng)建構(gòu)造器
      var Profile = Vue.extend(AutoComplate);
      // 創(chuàng)建 Profile 實(shí)例,并掛載到一個(gè)元素上。
      new Profile().$mount(editorContext.firstChild);
    }
};

雙擊進(jìn)入編輯狀態(tài),看到組件中的內(nèi)容

怎么使用Vue解決動(dòng)態(tài)掛載

下一步,對(duì)于自定義單元格還需要設(shè)置和獲取組件中的編輯內(nèi)容,這時(shí)通過(guò)給組件添加props,同時(shí)在掛載時(shí)創(chuàng)建的VueComponent實(shí)例上直接獲取到所有props內(nèi)容,對(duì)應(yīng)操作即可實(shí)現(xiàn)數(shù)據(jù)獲取設(shè)置。

更新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>

通過(guò)this.vm存儲(chǔ)VueComponent實(shí)例,在getEditorValue 和setEditorValue 方法中獲取和給VUE組件設(shè)置Value。編輯結(jié)束,通過(guò)調(diào)用$destroy()方法銷毀動(dòng)態(tài)創(chuàng)建的組件。

AutoComplateCellType.prototype.activateEditor = function (editorContext, cellStyle, cellRect, context) {
    let width = cellRect.width > 180 ? cellRect.width : 180;
    if (editorContext) {
      // 創(chuàng)建構(gòu)造器
      var Profile = Vue.extend(MyInput);
      // 創(chuàng)建 Profile 實(shí)例,并掛載到一個(gè)元素上。
      this.vm = new Profile().$mount(editorContext.firstChild);
    }
};
 
AutoComplateCellType.prototype.getEditorValue = function (editorContext) {
    // 設(shè)置組件默認(rèn)值
    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;
};

怎么使用Vue解決動(dòng)態(tài)掛載

整個(gè)流程跑通了,下來(lái)只需要在AutoComplate.vue中,將input替換成ElementUI 的el- autocomplete并實(shí)現(xiàn)對(duì)應(yīng)方法就好了。

結(jié)果

讓我們看看效果吧。

怎么使用Vue解決動(dòng)態(tài)掛載

以上就是“怎么使用Vue解決動(dòng)態(tài)掛載”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會(huì)為大家更新不同的知識(shí),如果還想學(xué)習(xí)更多的知識(shí),請(qǐng)關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

vue
AI