Vue3 with Vite render VNode not work after build

Viewed 64

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.

dialog screenShoot.

but in prod environment, it dosen't render on the container. just add a empty dom element to body.

web dom.

is anyone know how to fix it? thanks.


here is my demo.


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.

0 Answers
Related