需求描述:
實現(xiàn)一個自定義圖表拖拽功能强岸,拖拽的組件中有下拉框锻弓,輸入框,時間選擇器等組件蝌箍。為了方便青灼,決定使用Element UI組件。
問題描述:
通過拖拽創(chuàng)建一個div元素(父元素)妓盲,通過vue的方法defineAsyncComponent引入一個異步組件杂拨,使用createApp創(chuàng)建一個vue實例,并將其掛載到父元素上悯衬。部分代碼如下
import { createApp, defineAsyncComponent } from "vue";
function createInputCom(data) {
let oldVue = null;
oldVue = defineAsyncComponent(() => import("../components/viewComp/input.vue"));
let baseComp = document.querySelector("#" + data.id);
baseComp.style.padding = "10px 20px"
let Id = data.id;
this.id = Id;
let obj = {
id: Id,
type: 'type_label',
};
this.option = obj;
this.baseVue = createApp(oldVue, obj).use(ElementPlus, { locale });
this.baseVue.config.globalProperties =
window.globalApp._context.config.globalProperties;
this.baseVue.mount(baseComp);
this.registerComponentInWindow(Id, this.baseVue, data.ElConfig)
}
input.vue
<template>
<div class="input-box">
<el-input v-model="value" placeholder="請輸入" />
</div>
</template>
<script>
import { getCurrentInstance, onMounted, ref, watch } from "vue";
import { useInstanceContent } from "../../utils/combinedFunction.js"
export default {
setup() {
const { proxy } = getCurrentInstance();
const value = ref("");
const changeInputValue = (val) => {
value.value = val
}
onMounted(() => {
useInstanceContent(proxy.$attrs.id, proxy)
});
return {
value,
changeInputValue,
};
},
};
</script>
<style scoped>
.input-box {
width: 100%;
height: 100%;
}
</style>
因為會通過外在編輯對組件的內(nèi)容進行修改弹沽,所以想要通過vue實例去獲取到內(nèi)部組件(這里指input.vue)的實例。這里通過對this.baseVae進行查看筋粗,發(fā)現(xiàn) this.baseVae_instance.vnode.el.__vueParentComponent.ctx可以訪問到內(nèi)部組件的實例(目標實例)
找到實例贷币,將目標實例掛載到全局上以便進行使用。
function registerComponentInWindow(ID, content, config) {
Object.prototype.toString.call(window.components) !== '[object Object]' ? window.components = {} : ''
setTimeout(() => {
if (content._instance.vnode.el.__vueParentComponent && content._instance.vnode.el.__vueParentComponent.ctx) {
window.components[ID] = {
content: content._instance.vnode.el.__vueParentComponent.ctx,
config: {
labelCom: {},
selectCom: {},
inputCom: {},
buttonCom: {},
dateCom: {},
tableCom: {},
}, // 存放一些需要的屬性
}
}
}, 500) // 這里需要異步亏狰,不然取不到this.baseVue的實例役纹。
}
這種方法在本地開發(fā)中是沒有問題,但是在打包發(fā)布之后這個方法就有問題了暇唾,打包發(fā)布之后的this.baseVae_instance值為null促脉,就導致其它地方?jīng)]法操作我們的組件。
原因
目前還不知道策州,知道的老師可以在評論區(qū)留下知識瘸味,謝謝。
解決方案
在每個組件的mounted階段够挂,進行全局注冊
export function useInstanceContent (id, content) {
Object.prototype.toString.call(window.components) !== '[object Object]' ? window.components = {} : ''
Object.prototype.toString.call(window.components[id]) !== '[object Object]' ? window.components[id] = {
content: {},
config: {}
} : ''
window.components[id].content = content
}