在Vue3 + Vite项目,将vnode渲染到dom上,开发环境和生产环境表现不一致? #6627
Answered
by
chenxch
HJ-Hao
asked this question in
Help/Questions
-
在这个demo里面,有个dialog组件,想通过调用js方法去渲染组件,类似于element-plus的MessageBox写法。下面是代码部分 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);
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',
},
});
console.log(ElDialog, ElButton);
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> 上面这个组件在dev环境正常渲染出来了,但在生产环境并没有成功,而且console也没有报错。有大佬知道如何解决吗? |
Beta Was this translation helpful? Give feedback.
Answered by
chenxch
Nov 15, 2022
Replies: 3 comments 1 reply
-
你需要做以下2个变更 // messageBox.js
Object.keys(props).forEach((prop) => {
if (_.has(props, prop) && !_.has(vm.$props, prop)) {
vm[prop] = props[prop];
}
});
vm.$.exposed.trigger.value = true; // MshMessageBox.vue
defineExpose({ trigger }) |
Beta Was this translation helpful? Give feedback.
0 replies
-
你的代码是参考ep的实现方式,但是要注意的一点是ep的 如果你觉得这个对你有帮助可以标记为答案哈~~😁 |
Beta Was this translation helpful? Give feedback.
1 reply
Answer selected by
HJ-Hao
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
你的代码是参考ep的实现方式,但是要注意的一点是ep的
messageBox.vue
使用的是optionAPI
,而你的是用script setup
,optionAPI
编写的组件其内部属性外部是可以直接访问的,而script setup
需要自行expose
。如果你觉得这个对你有帮助可以标记为答案哈~~😁