1. 程式人生 > 其它 >vue3 動態將元件插入到指定的DOM下!!!

vue3 動態將元件插入到指定的DOM下!!!

這個近期做three.js 專案有這種需求,需要將一個元件插入到 css2dobject 生產的 2d標籤下實現自定義標籤的效果。

大概就是這種效果。

最終尋求到的方案有兩種:

// method 1


** mount.js **
import { createVNode, render } from 'vue'

export const mount = (component, { props, children, element, app } = {}) => {
    let el = element

    let vNode = createVNode(component, props, children)
    if (app && app._context) vNode.appContext = app._context
    if (el) render(vNode, el)
    else if (typeof document !== 'undefined' ) render(vNode, el = document.createElement('div'))

    const destroy = () => {
        if (el) render(null, el)
        el = null
        vNode = null
    }

    return { vNode, destroy, el }
}

** useage **
/**+
tagDiv:  待插入的元件
div: 帶插入的元件的目標div
root: 當前頁面的 vue根元件例項
*/

    
const { el, vNode, destory } = mount(tagDiv, {
    props: { // 傳入到元件中的props
        resData: tableData.value 
    },
    element: div,
    app: root
});

// 結果是 可以將元件插入到div中,但是有侷限性,就是插入的元件內無法識別物件和響應式資料

,如圖,會被直接當成文字,搞不懂, 將只有純文字的元件插入顯示是ok的,插值表示式,插槽props object 都不會被識別。。。

//method 2

/**

*/
// renderComponent.js
import { createApp } from 'vue'

export default function renderComponent({ el, component, props, appContext }) {
  let app = createApp(component, props)
  Object.assign(app._context, appContext) // must use Object.assign on _context
  app.mount(el)

  return () => {
    // destroy app/component
    app?.unmount()
    app = undefined
  }
}

// usage
<script setup>
import { ref, onUnmounted, getCurrentInstance } from 'vue'
import renderComponent from '@/data/renderCom.js'

const { appContext } = getCurrentInstance() // 這個appContext 是當前根元件上下文?  官網沒找到說明
const container = ref()
let counter = 1
let destroyComp = null

onUnmounted(() => destroyComp?.())

const insert = async () => {
  destroyComp?.()
  destroyComp = renderComponent({
    el: container.value, //  元件要插入的那個dom
    component: (await import('@/components/HelloWorld.vue')).default, // 要插入的元件
    props: { // 傳入 props
      key: counter,
      msg: 'Message ' + counter++,
      test: [{name: 'testpropsaaa'}]
    },
    appContext, // 獲取元件例項的 
  })
}
</script>

<template>
  <button @click="insert">Insert component</button>
  <div ref="container"></div>
</template>

這種方式 插入的元件都是 ok的 nice!!!

附上效果圖:

這裡是以 div 承載 el-table 結合 three.js 實現的效果