gpt4 book ai didi

vue.js - 如何在不注入(inject)的情况下创建全局组件?

转载 作者:行者123 更新时间:2023-12-04 03:45:54 27 4
gpt4 key购买 nike

有一种情况,我们需要在全局中使用一个组件,如 this.$toast('some words')this.$dialog({title:'title words ',contentText:'一些话').

在Vue 2.x中,我们可以将Toast.vue的方法添加到Vue.prototype中,调用Toast.vue'无处不在的方法。但是我们如何在 Vue 3.x 中做到这一点?

我阅读了vue-next中的i18n plugin demo文档。但是它需要将 i18n 插件注入(inject)到每个需要使用它的组件中。不方便。

最佳答案

一种无需注入(inject)即可在 vue3 应用程序的任何位置显示组件的方法

机制

每次都将组件挂载到dom中。

实现

例如使用'Toast':

第一步:创建SFC(Toast.vue)

<template>
<transition name="fade">
<div class="toast" v-html="msg" :style="style" @click="closeHandle"></div>
</transition>
</template>

<script>
import {ref,computed,onMounted,onUnmounted} from 'vue'
export default {
name: "Toast",
props:{
msg:{type:String,required:true},
backgroundColor:{type:String},
color:{type:String},
// closing the Toast when timed out. 0:not closed until to call this.$closeToast()
timeout:{type:Number,default:2000, validate:function (val){return val >= 0}},
// closing the Toast immediately by click it, not wait the timed out.
clickToClose:{type:Boolean, default: true},
// a function provied by ToastPlugin.js, to unmout the toast.
close:{type:Function,required: true}
},

setup(props){
let innerTimeout = ref();
const style = computed(
()=>{return{backgroundColor:props.backgroundColor ? props.backgroundColor : '#696969', color:props.color ? props.color : '#FFFFFF'}}
);

onMounted(()=>{
toClearTimeout();
if(props.timeout > 0)
innerTimeout.value = setTimeout(()=>{ props.close(); },props.timeout);
});

/**
* when toast be unmounted, clear the 'innerTimeout'
*/
onUnmounted(()=>{toClearTimeout()})

/**
* unmount the toast
*/
const closeHandle = () => {
if(props.clickToClose)
props.close();
}

/**
* to clear the 'innerTimeout' if it exists.
*/
const toClearTimeout = ()=>{
if(innerTimeout.value){
try{
clearTimeout(innerTimeout.value);
}catch (e){
console.error(e);
}
}
}

return {style,closeHandle};
},
}
</script>

<style scoped>
.toast{position: fixed; top: 50%; left: 50%; padding: .3rem .8rem .3rem .8rem; transform: translate(-50%,-50%); z-index: 99999;
border-radius: 2px; text-align: center; font-size: .8rem; letter-spacing: .1rem;}
.fade-enter-active{transition: opacity .1s;}
.fade-leave-active {transition: opacity .3s;}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {opacity: 0;}

</style>

第二步:创建插件(ToastPlugin.js)

import Toast from "./Toast.vue";
import {createApp} from 'vue'
const install = (app) => {
// dom container for mount the Toast.vue
let container;
// like 'app' just for Toast.vue
let toastApp;
// 'props' that Toast.vue required.
const baseProps = {
// define a function to close(unmount) the toast used for
// case 1: in Toast.vue "click toast appeared and close it"
// case 2: call 'this.$closeToast()' to close the toast in anywhere outside Toast.vue
close:()=> {
if (toastApp)
toastApp.unmount(container);

container = document.querySelector('#ToastPlug');
if(container)
document.body.removeChild(container);
}
};

// show Toast
const toast = (msg)=>{
if(typeof msg === 'string')
msg = {msg};

const props = {...baseProps,...msg}
console.log('props:',JSON.stringify(props));

// assume the toast(previous) was not closed, and try to close it.
props.close();

// create a dom container and mount th Toast.vue
container = document.createElement('div');
container.setAttribute('id','ToastPlug');
document.body.appendChild(container);
toastApp = createApp(Toast, props);
toastApp.mount(container);
}

// set 'toast()' and 'close()' globally
app.config.globalProperties.$toast = toast;
app.config.globalProperties.$closeToast = baseProps.close;
}

export default install;

第三步:使用

在 main.js 中

import ToastPlugin from 'xxx/ToastPlugin'
import { createApp } from 'vue'

const app = createApp({})
app.use(ToastPlugin)

// then the toast can be used in anywhere like this:
this.$toast('some words')
this.$toast({msg:'some words',timeout:3000})

关于vue.js - 如何在不注入(inject)的情况下创建全局组件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65154183/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com