Here is a dialog component in my demo. And i want to render it by calling a JS method, just like element-plus MessageBox component. here is my code.
import { render, createVNode } from 'vue';
import MshMessageBox from './MshMessageBox.vue';
import _ from 'lodash';
const getContainer = () => document.createElement('div');
const initInstance = (props, container) => {
const vnode = createVNode(MshMessageBox, props);
render(vnode, container);
document.body.appendChild(container.firstElementChild);
return vnode.component;
};
const destoryInstance = (container) => {
render(null, container);
};
const showMessage = (option) => {
return new Promise((resolve, reject) => {
const props = _.cloneDeep(option ?? {});
props.onAction = (action) => {
if (action === 'cancle') {
reject(action);
} else {
resolve(action);
}
};
props.onVanish = () => {
destoryInstance(container);
};
const container = getContainer();
const instance = initInstance(props, container);
console.log(instance);
const vm = instance?.proxy;
Object.keys(props).forEach((prop) => {
if (_.has(props, prop) && !_.has(vm.$props, prop)) {
vm[prop] = props[prop];
}
});
vm.trigger = true;
});
};
export default showMessage;
<template>
<el-dialog v-model="trigger" width="25%" top="30vh" @closed="emit('vanish')" :before-close="handleClose">
<template #header>
<div>
<span :class="$style.title">{{ title }}</span>
</div>
</template>
<div>
{{ message }}
</div>
<template #footer>
<span>
<el-button @click="handleAction('cancle')">取消</el-button>
<el-button type="primary" @click="handleAction('confirm')" style="background: #064dff">确定</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup>
import { ElDialog, ElButton } from 'element-plus';
import { nextTick, ref } from 'vue';``
defineProps({
message: {
type: String,
default: 'message',
},
title: {
type: String,
default: 'title',
},
});
const emit = defineEmits(['action', 'vanish']);
const trigger = ref(false);
const handleAction = (action) => {
if (!trigger.value) {
return;
}
trigger.value = false;
emit('action', action);
};
const handleClose = (done) => {
emit('action', 'cancle');
nextTick(() => {
done();
});
};
</script>
it work successfully in dev environment.
but in prod environment, it dosen't render on the container. just add a empty dom element to body.
is anyone know how to fix it? thanks.
ok find the source of this, can't change component data by vm.xxx = 'xx' in prod environment. that's why the component not render.