VueJS笔记-Vue中实现全局唯一单例组件思路及实例[TS](Vue Plugins)
设计思路备忘笔记...
Vue 2.0
使用场景:各种全局弹窗..例如登录弹窗,设置弹窗,模态通用的Confirm对话框等等....
吐槽:在C#/C++/JS/SQL间反复横跳,这个月又轮到的JS....我也真是醉了
流程就是Vue的插件开发方式....
以vueJs得ts版本为例:
*********************************割割割*********************************
例如有组件:
*.vue:
<template>
    <div v-if="bShow" class="game-setting-dialog">
        <div class="container">
            <h2>Hi, Singleton Component</h2>
        </div>
    </div> 
</template>
<script lang="ts" src="./index.ts"></script>
<style scoped lang="stylus">
.game-setting-dialog
    position    : fixed;
    top         : 0;
    height      : 100%;
    width       : 100%;
    z-index     : 1;
    text-align  : center;
    background  : rgba( 0, 0, 0, 0.7 );
    .container
        background  : red;
        width       : 50%;
        top         : 10vh;
        min-height  : 100px;
</style>
*.TS脚本:
import {Vue,Prop,Component}from 'vue-property-decorator'
import { Store } from 'vuex';
@Component({ name: 'GameSettingDialog' })
export default class GameSettingDialogComponent extends Vue 
{
    private _bShow:boolean = false;
    mounted() {
    }
    get bDialog():boolean
    {
        return this._bShow ;
    }
    set bDialog(val:boolean)
    {
        this._bShow = false;
    }
}
初始化函数 (注入单例访问函数):
install.ts:
import Vue,{} from 'vue';
import GameSettingDialog from '@/views/Singleton/GameSettingDialog/index.vue';
import GameSettingDialogComponent from '@/views/Singleton/GameSettingDialog/index.ts';
import store from '@/store/index';
import router from '@/router/index';
declare const window:any;
let instance : any| null = null;
 //构造一个新的Vue实例句柄.....
/**
 * App初始化时调用...
 */
const install = function (vue:typeof Vue, opts = {})
{
    //往Vue类里写入一个`静态函数’
    Vue.prototype.$gameSettingDialog = (opt?:any)=>
    {
        if (!instance)
        {
            //如果单例未创建...
            let div = document.createElement('div');
            instance  =  new GameSettingDialog({
                el      : div ,
                store   : store ,  // 如果用到vuex需要包含
                router  : router   // 同route
            });
            document.body.appendChild(instance.$el);
        }
        return instance as GameSettingDialogComponent;
    };
} 
export default install;
编写一个*.d.ts,重新扩展Vue类的接口成员:
import Vue, {VNode} from 'vue'
import GameSettingDialogComponent from '@/views/Singleton/GameSettingDialog/index.ts'
declare module 'vue/types/vue'
{
    interface Vue {
      /** Displays a global notification message at the upper right corner of the page */
      $gameSettingDialog:(opt?:any) => GameSettingDialogComponent
    }
}
然后use即可,如:
//#region import 区域 import Vue from 'vue'; import App from './App.vue'; import './registerServiceWorker'; import router from './router'; import store from './store'; import GameSettingDialog from '@/views/Singleton/GameSettingDialog/install'; //#endregion Vue.config.productionTip = false; //注入全局唯一组件到整个Vue App中... Vue.use(GameSettingDialog); new Vue({ router : router , store : store , render : (h) => h(App) }).$mount('#app');
任意Vue组件中,使用this.$xxxx调用,例如:
this.$gameSettingDialog().bDialog = true; this.$gameSettingDialog().$once('custom-event', ()=> { console.log('事件绑定'); this.$gameSettingDialog().bDialog = false; });
*********************************割割割*********************************
为什么要这样实现?
因为优雅......(战术后仰)
而且如果是多项目通用的唯一组件,这种方式封装成插件...基本是开箱即用....
vuex,vue-route 都是这样子实现全局唯一的...
    本文原创,不定时更新
可以随意转载到任何网站
~但是~ 转载也要按“基本法”
请注明原文出处和作者
)O$HJZH.png) 

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号