Vue 3.x 通过函数渲染组件实例

989 阅读1分钟

方式一:通过组件实例

getCurrentInstance

查阅 Vue 3 官网 API 可以发现这个函数,可以用在 setup生命周期函数 中,以获取当前组件实例(也就是组件内常用的 this ),通过这个函数返回的对象,可以访问我们整个 app 的全局属性:

setup() {
  // 组件实例
  const myComponentInstance = getCurrentInstance();
  // 全局属性
  const myAppGlobalProperties = myComponentInstance.appContext.config.globalProperties;
  // 后续可以将实例中的函数、方法挂载到全局属性上
}

这种方式获取的 globalPropertiesapp.config.globalProperties 是一样的,因此可以在组件实例中添加更多的全局属性。

实践

我们可以制作一个消息弹窗的组件,在根组件(App.vue)上使用,这样后续的其他子组件内部就可以直接调用 this.$message 显示消息弹窗了。

// MessageBox.vue
<template>
    <teleport to="body">
        <div v-if="visible" class="message-box">消息弹窗</div>
    </teleport>
</template>

<script>
import { ref, getCurrentInstance, defineComponent } from 'vue';

export default defineComponent({
    name: 'MessageBox',
    setup() {
        // 弹窗是否可见
        const visible = ref(false);

        /**
         * 打开弹窗
         */
        const open = () => {
            visible.value = true;
            // 5秒后关闭
            setTimeout(() => {
                visible.value = false;
            }, 5000);
        };
        
        // 获取组件实例,挂载全局函数
        const instance = getCurrentInstance();
        instance.appContext.config.globalProperties.$message = open;

        return {
            visible
        };
    },
});
</script>

<style>
.message-box {
    position: fixed;
    left: 50vw;
    top: 50vh;
    transform: translate(-50%, -50%);
    background: red;
    z-index: 9999999999;
}
</style>

方式二:通过插件

这种方式参照Element-plus的el-message实现,使用vue.render函数。

import * as Vue from 'vue';
import Message from './components/Message.vue';

const msg = (text) => {
    // 真实DOM,用来挂载VNode
    const container = document.createElement('div');
    document.body.append(container);
    // 创建一个组件,也可以直接 import 一个 *.vue 文件
    const vm = Vue.defineComponent({
        setup() {
            // 返回一个 render 函数
            return () => {
                return Vue.h('div', null, text);
            };
        }
    });
    // 将 vm 渲染到真实 DOM 上
    vue.render(vm, container);
};

export default {
    install(app) {
        app.config.globalProperties.$message = msg;
    }
}