VueJS筆記-Vue中實現全局唯一單例組件思路及實例[TS](Vue Plugins)


設計思路備忘筆記...

 

使用場景:各種全局彈窗..例如登錄彈窗,設置彈窗,模態通用的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 都是這樣子實現全局唯一的...

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM