这个近期做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 实现的效果