2021-03-10

Posted bywayboy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021-03-10相关的知识,希望对你有一定的参考价值。

vue3.0 动态创建组件

缘起

有时候, 我们希望组件在我们任何需要的时候呼之即来,而不是固定在html的DOM中.
在 element-plus中 是事先通过 el-dialog 定义 然后 控制起是否可见来决定对话框的弹出还是隐藏。
这在涉及复杂逻辑可能会不太方便。

设想中的写法:

import LocMarkDialog from 'LocMarkDialog.vue'

///省略代码 ....
let proxy = getCurrentInstance();
proxy.$mount(LocMarkDialog).then(res)=>
//点击了确定
).catch(()=>
//点击了取消

MyDialog 组件并不写在<template></template> 标签中,而是在任何业务需要的地方临时创建,并且在使用完后自动销毁.

组件的实现代码:

import  markRaw, ref, createVNode, defineComponent from 'vue'


let componentMap = ref([])

let id=0;

const factory = defineComponent(
    props:
    ,
    render()
        var children = componentMap.value.map((item, i)=>createVNode(item.c, item.p))
        return createVNode('div', class:'ui-app-component-container', children);
    ,
    setup(props)
    
        return 
            componentMap
        
    ,
    install(app)
        app.component('CompFactory', factory);
        app.config.globalProperties.$mount = (comp, props) => 
            return new Promise((resolve, reject)=>
                let p = props || ;
                Object.assign(p, q:resolve, reject, _compId: id++, finish:(id)=>
                    let ret = componentMap.value.findIndex(v=>v.p.id===id)
                    if(ret >=0)
                        componentMap.value.splice(ret, 1);
                );
                console.log('mount component.', comp);
                componentMap.value.push(c:markRaw(comp), p);
            )
        
    
)

export default factory;

用法

第一步: 首先全局引入组件

// 引入前面写的组件
import CompFactory from '/@/uiframe/layout/components/CompFactory.vue'
const app = createApp(App);
app.use(CompFactory)

第二步: 在全局使用一次组件

这么做的目的是在document 中创建一个容器节点.

App.vue

<CompFactory></CompFactory>

第三步: 如何使用

定义一个对话框组件

<template>
    <el-dialog custom-class="ui-loc-mark-dialog ui-dialog-autow" v-model="dialogVisible" destroy-on-close :modal="true" @closed="finalThings" title="地理位置标注">
        <BaiduMap :location="location" width="100%" height="100%"></BaiduMap>
        <template #footer>
            <el-button type="primary" size="mini" @click="onSure">保存</el-button>
            <el-button size="mini" @click="onCancel">取消</el-button>
        </template>
    </el-dialog>
</template>
<script>
import  ref  from '@vue/reactivity';
import BaiduMap from '/@/uiframe/layout/components/BaiduMap.vue'
import  onUnmounted  from '@vue/runtime-core';

import LocMarkDialog from '/@/uiframe/layout/components/LocMarkDialog.vue'

export default 
    components:
        BaiduMap
    ,
    props:
        q:Object, //这里是 resolve 和reject
        _compId:Number, //这里是组件id
        finish:Function, //这里是组件销毁后的回调。
        location: type:Object, default:lng:113.97, lat:28.36300,
    ,
    setup(props, ctx)
    
        let dialogVisible = ref(true); //对话框默认显示

        const onCancel = ()=>
            dialogVisible.value = false;
            props.q.reject('cancel');
        
        const onSure = ()=>
            dialogVisible.value = false;
            props.q.resolve(success:true);
        
		
		//对话框销毁后, 通知CompFactory 销毁节点.
        const finalThings = ()=>
            props.finish(props.id);
        
        onUnmounted(()=>
            console.log('bye!');
        )
        return 
            location:props.location,
            dialogVisible,
            onCancel,
            onSure,
            finalThings
        
    

</script>
<style lang="scss">
.ui-loc-mark-dialog .el-dialog__body 
  height: 23rem;padding:.5rem;

</style>

以上是关于2021-03-10的主要内容,如果未能解决你的问题,请参考以下文章

缘起性空

缘起,不算浪漫的故事

1/3人生-第一章 缘起落笔,释开篇原因

《Invert》开发日志00:缘起

跟k8s工作负载Deployments的缘起缘灭

你可能不知道的前端知识点