element-ui Message組件源碼分析整理筆記(八)

来源:https://www.cnblogs.com/fangnianqin/archive/2018/12/11/10103216.html
-Advertisement-
Play Games

main.js main.vue pythod <! 自定義圖標存在時顯示 <! 自定義圖標不存在時根據type顯示圖標 <! 用戶設置的message的參數為字元串時,顯示字元串 {{ message }} <! 用戶設置的message的參數為VNode時,在此處顯示 <! 當用戶設置的關閉按鈕 ...


Message組件源碼:

main.js

import Vue from 'vue';
import Main from './main.vue';
import { PopupManager } from 'element-ui/src/utils/popup';
import { isVNode } from 'element-ui/src/utils/vdom';
let MessageConstructor = Vue.extend(Main);

let instance;
let instances = []; // 存放當前未close的message
let seed = 1;

const Message = function(options) {
  // 當前 Vue 實例是否運行於伺服器
  if (Vue.prototype.$isServer) return;
  options = options || {};
  if (typeof options === 'string') {
    options = {
      message: options
    };
  }
  //userOnClose用來存放用戶設置關閉時的回調函數, 參數為被關閉的 message 實例
  let userOnClose = options.onClose;
  let id = 'message_' + seed++;

  // 重寫options.onClose
  options.onClose = function() {
    Message.close(id, userOnClose);
  };
   // 創建message實例,此時數據還沒有掛載呢,$el 屬性目前不可見,無法訪問到數據和真實的dom
  instance = new MessageConstructor({
    data: options
  });
  instance.id = id;

  //判斷instance.message是不是虛擬節點
  if (isVNode(instance.message)) {
    instance.$slots.default = [instance.message];
    instance.message = null;
  }
   //手動地掛載一個未掛載的實例。$mount(param)中param不存在時,模板將被渲染為文檔之外的的元素,並且你必須使用原生 DOM API 把它插入文檔中。
  instance.vm = instance.$mount();
  //用原生DOM API把它插入body中
  document.body.appendChild(instance.vm.$el);
  instance.vm.visible = true;
  instance.dom = instance.vm.$el;
  // css z-index層級疊加,覆蓋之前已出現但還未close的message
  instance.dom.style.zIndex = PopupManager.nextZIndex();
  instances.push(instance);
  return instance.vm;
};

// 給Message增加四個直接調用的方法
// 支持this.$message.success('xxx')方式調用,等同於this.$message({type: 'success',message: 'xxx'})
['success', 'warning', 'info', 'error'].forEach(type => {
  Message[type] = options => {
    if (typeof options === 'string') {
      options = {
        message: options
      };
    }
    options.type = type;
    return Message(options);
  };
});

// 組件的close方法中調用onClose再調該方法
Message.close = function(id, userOnClose) {
  for (let i = 0, len = instances.length; i < len; i++) {
    if (id === instances[i].id) { // 通過id找到該message實例
      if (typeof userOnClose === 'function') {
        userOnClose(instances[i]);
      }
      instances.splice(i, 1);  // 移除message實例
      break;
    }
  }
};
//關閉所有的消息提示彈窗
Message.closeAll = function() {
  for (let i = instances.length - 1; i >= 0; i--) {
    instances[i].close();
  }
};

export default Message;

main.vue

<template>
  <transition name="el-message-fade">
    <div
      :class="[
        'el-message',
        type && !iconClass ? `el-message--${ type }` : '',
        center ? 'is-center' : '',
        showClose ? 'is-closable' : '',
        customClass
      ]"
      v-show="visible"
      @mouseenter="clearTimer"
      @mouseleave="startTimer"
      role="alert">
        <!--自定義圖標存在時顯示-->
      <i :class="iconClass" v-if="iconClass"></i>
        <!--自定義圖標不存在時根據type顯示圖標-->
      <i :class="typeClass" v-else></i>
      <slot>
          <!--用戶設置的message的參數為字元串時,顯示字元串-->
        <p v-if="!dangerouslyUseHTMLString" class="el-message__content">{{ message }}</p>
        <!--用戶設置的message的參數為VNode時,在此處顯示-->
        <p v-else v-html="message" class="el-message__content"></p>
      </slot>
        <!--當用戶設置的關閉按鈕顯示為true時,顯示關閉圖標-->
      <i v-if="showClose" class="el-message__closeBtn el-icon-close" @click="close"></i>
    </div>
  </transition>
</template>

<script type="text/babel">
  const typeMap = {
    success: 'success',
    info: 'info',
    warning: 'warning',
    error: 'error'
  };

  export default {
    data() {
      return {
        visible: false,
        message: '', //消息文字
        duration: 3000, //顯示時間, 毫秒。設為 0 則不會自動關閉
        type: 'info',
        iconClass: '', //自定義圖標的類名,會覆蓋 type
        customClass: '', //自定義類名
        onClose: null,
        showClose: false, //是否顯示關閉按鈕
        closed: false, //用來判斷消息提示彈窗是否關閉
        timer: null,
        dangerouslyUseHTMLString: false, //是否將 message 屬性作為 HTML 片段處理
        center: false
      };
    },

    computed: {
      // 根據type返回對應的圖標類名
      typeClass() {
        return this.type && !this.iconClass
          ? `el-message__icon el-icon-${ typeMap[this.type] }`
          : '';
      }
    },

    watch: {
      closed(newVal) {
        if (newVal) {
          this.visible = false;
          //transitionend事件在 CSS 完成過渡後觸發。
          this.$el.addEventListener('transitionend', this.destroyElement);
        }
      }
    },

    methods: {
      destroyElement() {
        this.$el.removeEventListener('transitionend', this.destroyElement);
        //完全銷毀一個實例。清理它與其它實例的連接,解綁它的全部指令及事件監聽器。
        // 在vue v1.x中$destroy(true)的參數為true時,則從DOM中刪除其關聯的DOM元素或片段;在vue2.0中不需要加參數
        this.$destroy(true);
        this.$el.parentNode.removeChild(this.$el);
      },

      close() {
        this.closed = true;
        if (typeof this.onClose === 'function') {
          this.onClose(this);
        }
      },
      //滑鼠進入消息提示彈窗時,定時器清空,彈窗一直顯示
      clearTimer() {
        clearTimeout(this.timer);
      },
      // 滑鼠離開消息提示彈窗時,設置定時器,彈窗在this.duration關閉
      startTimer() {
        if (this.duration > 0) {
          this.timer = setTimeout(() => {
            if (!this.closed) {
              this.close();
            }
          }, this.duration);
        }
      },
      // esc關閉消息
      keydown(e) {
        if (e.keyCode === 27) {
          if (!this.closed) {
            this.close();
          }
        }
      }
    },
    mounted() {
      this.startTimer();
      document.addEventListener('keydown', this.keydown);
    },
    beforeDestroy() {
      document.removeEventListener('keydown', this.keydown);
    }
  };
</script>

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • var str=new String(); var arr=new Array(); str="ddd,dsd,3,dd,g,k"; //可以用字元或字元串分割 arr=str.split(','); for(var i=0;i<arr.length;i++) { alert(arr[i]); } ...
  • 1、 去掉字元串前後所有空格: 代碼如下: function Trim(str) { return str.replace(/(^\s*)|(\s*$)/g, ""); } ...
  • 感覺現在許多應用和網站都開始用 骨架屏 了,於是趕緊瞭解一下! 骨架屏實現的方式 目前我瞭解到的骨架屏實現方式,可以歸納為兩種: 1. 組件級別手動調用 2. 通過webpack自動註入到首頁 組件手動調用 這種方法比較簡單通用,適用各種mvvm框架。 具體的實現方式還可以細分: 1. 用UI調好的 ...
  • 前端之盒模型顯隱、定位與流式佈局思想 盒模型的顯隱 定位 相對定位 絕對定位 固定定位 z index 屬性 html <!DOCTYPE html z index .wrap { width: 200px; height: 200px; background: pink; / 父級做相對定位處理, ...
  • 一。 JS簡介 1. JavaScript概述 JavaScript 是世界上最流行的編程語言。這門語言可用於 HTML 和 web,更可廣泛用於伺服器、PC、筆記本電腦、平板電腦和智能手機等設備。 JavaScript是一種面向對象的,動態的腳本語言,主要被作為客戶端腳本語言在用戶的瀏覽器上運行, ...
  • 先放一個樣式圖: 源代碼如下: ————簡單來說,我的做法就是根據需求給每一個按鍵添加一個點擊事件。 先獲取到顯示器部分: ————利用點擊事件將按鍵的值傳給顯示部分,用到這個方法的的按鍵有0~9的數字,小數點,加減乘除和取餘(%)的運算符號 ————給等號按鍵添加的方法如下,eval方法會自動進行 ...
  • 利用canvas將網頁元素生成圖片並保存在本地 首先引入三個文件: > 註:createElementNS() 方法可創建帶有指定命名空間的元素節點。 createElementNS(ns,name)> createElementNS() 方法與 createElement() 方法相似,只是它創建 ...
  • 最近為了準備新工作重新摸出了SSM框架,同時從0學習了JQuery,終於用一周做完了一個包括增刪改查的模塊(主要是屬性太多了,其中一個類50+,複製粘貼耗時)。 從中特意記下了幾個遇到的問題,總結一下。 1. 執行網頁js代碼時, 出現$ is not defined錯誤。 原因:未引入JQuery ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...