最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

vue中this.$message的實(shí)現(xiàn)過程詳解

 更新時間:2023年04月26日 11:09:07   作者:小飛俠呀  
Message在開發(fā)中的使用頻率很高,也算是Element-UI組件庫中比較簡單的,對于感興趣的朋友可以一起探討一下Message組件的實(shí)現(xiàn),本文詳細(xì)介紹了vue中this.$message的實(shí)現(xiàn)過程,感興趣的同學(xué)可以參考一下

一、vue中為什么可以直接使用this.$message

1、Message在開發(fā)中的使用頻率很高,也算是Element-UI組件庫中比較簡單的,對于感興趣的朋友可以一起探討一下Message組件的實(shí)現(xiàn)

2、組件的使用

this.$message('這是一條消息提示');
this.$message({ message: '恭喜你,這是一條成功消息', type: 'success' });

3、整體的執(zhí)行過程

Vue項(xiàng)目中的使用如下:

// main.js

// 1.引入組件庫
import ElementUI from 'element-ui';
// 2.使用組件庫
Vue.use(ElementUI); 

Element-UI組件庫中邏輯如下:

每次當(dāng)Vue.use的時候,在Element—UI內(nèi)部會觸發(fā)Element-UIinstall方法,然后將組件注冊為全局組件,將方法放到Vue.prototype上,本次只看Message部分即可

// 文件目錄:node-modules/element-ui/src/index.js
// 1.引入Message對象
import Message from '../packages/message/index.js';

// 2. 定義 install函數(shù),
const install = function(Vue, opts = {}) {
  // 將組件遍歷注冊為全局組件,例如Button組件
  components.forEach(component => {
    Vue.component(component.name, component);
  });
  // 將方法放到Vue原型上
  Vue.prototype.$message = Message;
};

經(jīng)過上述兩步的處理,我們可以直接在項(xiàng)目中通過this.$message進(jìn)行組件的展示控制,接下來繼續(xù)探索Element-UI內(nèi)部如何處理的。

二、message組件的內(nèi)部實(shí)現(xiàn)原理

1、設(shè)計思路

Message的調(diào)用方式都是通過this.$message進(jìn)行調(diào)用,通過傳遞不同的options進(jìn)行組件樣式和內(nèi)容的控制,展示的html是動態(tài)的插入到document中并在duration之后移除,組件的展示通過vue實(shí)例訪問并控制。

組件的整體結(jié)構(gòu)分為展示部分和控制部分

展示部分(main.vue):單獨(dú)抽離出一個組件,將組件的展示邏輯和交互封裝集中處理

控制部分(main.js):是承接vue實(shí)例和組件展示

2、展示部分,即main.vue

首先看一下刪減版本之后展示部分的組件內(nèi)容,代碼刪除了容錯和邊界值判斷的代碼,僅僅展示了基本功能。

<template>
  <transition name="el-message-fade" @after-leave="handleAfterLeave">
    <div
      class="el-message"
      :style="positionStyle"
      v-show="visible">
      <slot>
        <p>{{ message }}</p>
      </slot>
    </div>
  </transition>
</template>

<script type="text/javascript">
export default {
  data() {
    return {
      visible: false,
      message: '',
      duration: 3000,
      onClose: null,
      closed: false,
      verticalOffset: 20,
      timer: null
    };
  },

  computed: {
    positionStyle() { // 控制當(dāng)前組件的顯示位置
      return {
        'top': `${ this.verticalOffset }px`
      };
    }
  },

  watch: {
    // 監(jiān)聽closed的變化,設(shè)置為true時,將組件銷毀
    closed(newVal) {
      if (newVal) {
        this.visible = false;
      }
    }
  },

  methods: {
    // transtion組件的鉤子,觸發(fā)after-leave時執(zhí)行
    handleAfterLeave() {
      this.$destroy(true); // 銷毀組件
      this.$el.parentNode.removeChild(this.$el); // 將組件的DOM移除
    },

    close() {
      this.closed = true; // 組件隱藏
      
      if (typeof this.onClose === 'function') {
        this.onClose(this);
      }
    },
    // 每次手動啟動編譯之后 設(shè)置其展示時間duration之后關(guān)閉
    startTimer() {
      if (this.duration > 0) {
        this.timer = setTimeout(() => {
          if (!this.closed) {
            this.close();
          }
        }, this.duration);
      }
    }
  },
  mounted() {
    this.startTimer();
  }
};
</script>

使用了Vue官方封裝的transition組件,不僅提供了良好的過渡效果,還提供了合適的鉤子便于開發(fā)者控制,組件中使用after-leave鉤子,當(dāng)組件銷毀時進(jìn)行組件的銷毀和DOM的移除,visible用于控制組件的展示與銷毀,計算屬性positionStyle用于設(shè)置組件的展示位置,message為組件展示的內(nèi)容數(shù)據(jù),搞明白這些變量、計算屬性和方法的作用即可。

script部分可參考注釋進(jìn)行理解,需要注意兩個地方

(1)首先需要注意生命周期鉤子mount時做的事情,為何如此做?因?yàn)椴淮嬖趀l選項(xiàng),實(shí)例不會立即進(jìn)入編譯階段,需要顯示調(diào)用$mount 手動開啟編譯

(2)還需要注意的時close函數(shù)中做了兩件事,設(shè)置closed的值觸發(fā)對應(yīng)的watch,關(guān)閉組件,若是存在onClose方法則調(diào)用,注意這個onClose函數(shù)的定義是在控制部分定義,稍后會說明

3、控制部分 至此已經(jīng)清楚Vue中是通過this.$message觸發(fā)組件的展示,而展示部分的組件內(nèi)容也已完成,現(xiàn)在就需要通過控制部分將兩者連接,達(dá)到期望的功能

Vue關(guān)聯(lián)比較簡單,僅僅是定義一個方法并將其導(dǎo)出即可

const Message = options => {
  // 邏輯編寫....
}
export default Message;

這個時候通過this.$message即可調(diào)用,接下來便是將Message函數(shù)與組件關(guān)聯(lián),并控制展示部分

Message核心需要做那些事情

  • 編譯組件,使用渲染并插入到body
  • 控制組件內(nèi)的visible變量,觸發(fā)組件的展示
  • 控制組件內(nèi)的verticalOffset變量,決定組件展示時的位置

手動開啟組件編譯,獲取其實(shí)例訪問內(nèi)部data和渲染到頁面上

// 1. 使用基礎(chǔ) Vue 構(gòu)造器,創(chuàng)建一個“子類”
let MessageConstructor = Vue.extend(Main);
// 2. 組件實(shí)例, 可以通過instance訪問 visible和verticalOffset
instance = new MessageConstructor({
  data: options
});

整個Message方法其余部分就是在做容錯和健壯處理,整體簡潔版代碼如下

let MessageConstructor = Vue.extend(Main);

let instance; // 當(dāng)前組件
let instances = []; // 將所有的message組件收集,用于位置的判斷和銷毀等
let seed = 1; // 每個message實(shí)例都有一個唯一標(biāo)識

const Message = options => {
  options = options || {
    message: 'content' + Date.now(),
    onClose(message){
      console.log('關(guān)閉時的回調(diào)函數(shù), 參數(shù)為被關(guān)閉的 message 實(shí)例',message);
    }
  };

  if (typeof options === 'string') {
    options = {
      message: options
    };
  }

  // 關(guān)閉時的回調(diào)函數(shù), 參數(shù)為被關(guān)閉的 message 實(shí)例
  let userOnClose = options.onClose;
  let id = 'message_' + seed++;
  
  // 增加 onClose 方法,組件銷毀時,在組件內(nèi)部調(diào)用
  options.onClose = function() { 
    Message.close(id, userOnClose);
  };

  // 組件實(shí)例,此時options與組件的data關(guān)聯(lián)
  instance = new MessageConstructor({
    data: options
  });
  instance.id = id; // 設(shè)置ID
  
  instance.$mount(); // 因?yàn)椴淮嬖趀l選項(xiàng),實(shí)例不會立即進(jìn)入編譯階段,需要顯示調(diào)用$mount 手動開啟編譯
  document.body.appendChild(instance.$el); // 將Message 組件插入到body中

  // 設(shè)置組件距離頂部的距離,每個message組件會有16px的間距
  let verticalOffset = options.offset || 20;
  instances.forEach(item => {
    verticalOffset += item.$el.offsetHeight + 16;
  });
  instance.verticalOffset = verticalOffset;

  instance.visible = true; // 控制展示
  instance.$el.style.zIndex = 99; // 控制層級
  instances.push(instance);
  return instance;
};

this.$message.error('')的實(shí)現(xiàn)

Message組件支持this.$message.error('錯了哦,這是一條錯誤消息');調(diào)用使用,到目前為止還不支持,代碼比較簡單直接上代碼

// 為每個 type 定義了各自的方法,如 Message.success(options),可以直接調(diào)用
['success', 'warning', 'info', 'error'].forEach(type => {
  Message[type] = options => {
    if (typeof options === 'string') {
      options = {
        message: options
      };
    }
    options.type = type;
    return Message(options);
  };
});

展示組件內(nèi)部會調(diào)用this.onClose(this),組件內(nèi)部設(shè)置this.visible=false關(guān)閉彈框,并且移除其對應(yīng)的DOM結(jié)構(gòu),但是頁面展示多個組件時需要修改其余組件的位置

onClose函數(shù)是在Message函數(shù)中定義

// 關(guān)閉時的回調(diào)函數(shù), 參數(shù)為被關(guān)閉的 message 實(shí)例
let userOnClose = options.onClose;

// 增加 onClose 方法,組件銷毀時,在組件內(nèi)部調(diào)用
options.onClose = function() { 
  Message.close(id, userOnClose);
};

onClose函數(shù)最終調(diào)用的是Message上的靜態(tài)方法close

函數(shù)Message.close內(nèi)部主要做了幾件事情

  • 在頁面顯示的組件數(shù)組中找到需要關(guān)閉的組件,將其移除
  • 重新計算剩余組件的位置

三、總結(jié)

至此基礎(chǔ)版本的Message已經(jīng)完成,組件的代碼不到200行,通過源碼的簡單閱讀和分析,知識點(diǎn)并不是很多,但是優(yōu)秀組件封裝的思路還是值得學(xué)習(xí)和借鑒

到此這篇關(guān)于vue中this.$message的實(shí)現(xiàn)過程詳解的文章就介紹到這了,更多相關(guān)vue中this.$message實(shí)現(xiàn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評論

建始县| 柘城县| 延边| 邹平县| 都江堰市| 华安县| 铅山县| 东安县| 天台县| 庆元县| 云霄县| 微博| 兰溪市| 顺昌县| 孟津县| 定襄县| 区。| 崇州市| 盐城市| 新乐市| 临武县| 曲沃县| 保山市| 武宣县| 上高县| 永城市| 新巴尔虎左旗| 尼玛县| 化德县| 吉安县| 行唐县| 东海县| 望城县| 丹棱县| 丰县| 江达县| 女性| 上饶县| 海南省| 都匀市| 突泉县|