• 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  实现的效果

    2022年3月7日16:14:02 补充

    由于客户需求是这里的数据是实时的,这里就需要重新发请求后,先删除之前的组件,在重复上述的动态添加。 这里之所以不去组件中发请求是因为每个table组件中的数据都是通过 props传过去的,如果要在table组件中发送请求,需要做一些额外的处理,比如数据过滤啥的,虽然不麻烦,加上这个实时功能做好了,补充这个博文才想到如何在组件中发请求,就还是在外面发了。

    如何去动态删除上面动态添加的组件:

    // 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 () => { 
         app?.unmount();
    app = undefined
    }
    }
    //  可以看到renderComponent 这里返回的一个方法, 可以看到 明显是移除挂载的意思,所以就好办了
    // destroy 

      

    let destroyComp = ref([]); //定义数组 接收renderComponent 返回值,至于要定义为数组是因为不只一个table组件,要全部移除的话就需要每个table组件的实例都执行这个方法
    
        destroyComp.value.push( // vue3 写法,将每个table 组件实例所对应的unmount方法存入数组
          renderComponent({
            // renderComponent 返回一个函数,调用这个函数可以移除动态添加的组件!!!
            el: div,
            component: (await import("@/components/tagDiv.vue")).default,
            props: {
              resData: [v],
            },
            appContext,
          })
        );
    
    
    
    // 遍历destroyComp ,执行unmount方法
        destroyComp.value.forEach((v) => {
          v();
          destroyComp.value.unshift(); // 执行一次就推出一个
        });
  • 相关阅读:
    angular.isDefined()
    angular.isDate()
    angular.isArray()
    .NET中栈和堆的比较
    SQL Server 2012配置Always On可用性组
    一分钟了解负载均衡的一切
    C# 线程并发锁
    获取Http请求参数
    什么是WCF
    Bitmap算法应用
  • 原文地址:https://www.cnblogs.com/Hijacku/p/15949337.html
Copyright © 2020-2023  润新知