欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Vue $mount實(shí)戰(zhàn)之實(shí)現(xiàn)消息彈窗組件

 更新時(shí)間:2019年04月22日 10:43:19   作者:heath_learning  
這篇文章主要介紹了Vue $mount實(shí)現(xiàn)消息彈窗組件的相關(guān)知識(shí),非常不錯(cuò),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下

之前的項(xiàng)目一直在使用Element-UI框架,element中的Notification、Message組件使用時(shí)不需要在html寫(xiě)標(biāo)簽,而是使用js調(diào)用。那時(shí)就很疑惑,為什么element ui使用this.$notifythis.$message就可以實(shí)現(xiàn)這樣的功能?

1、實(shí)現(xiàn)消息彈窗組件的幾個(gè)問(wèn)題

  • 如何在任何組件中使用this.$message就可以顯示消息?
  • 如何將消息的dom節(jié)點(diǎn)插入到body中?
  • 同時(shí)出現(xiàn)多個(gè)消息彈窗時(shí),消息彈窗的z-index如何控制?

2、效果預(yù)覽

3、代碼實(shí)現(xiàn)

PMessage.vue

<template>
 <transition name="message-fade">
 <div class="p-message"
   :class="[type, extraClass]"
   v-show="show"
   @mouseenter="clearTimer"
   @mouseleave="startTimer">
  <div class="p-message-container">
  <i class="p-message-icon" :class="`p-message-icon-${type}`"></i>
  <div class="p-message-content">
   <slot class="p-message-content">
   <div v-html="message"></div>
   </slot>
  </div>
  </div>
 </div>
 </transition>
</template>
<script>
 // 綁定事件
 function _addEvent(el, eventName, fn){
 if(document.addEventListener){
  el.addEventListener(eventName, fn, false);
 }else if(window.attachEvent){
  el.attactEvent('on' + eventName, fn);
 }
 };
 // 解綁事件
 function _offEvent(el, eventName, fn){
 if(document.removeEventListener){
  el.removeEventListener(eventName, fn, false);
 }else if(window.detachEvent){
  el.detachEvent('on' + eventName, fn);
 }
 };
 export default {
 name: "PMessage",
 data(){
  return {
  type: 'success',
  duration: 3000,
  extraClass: '',
  message: '',
  timer: null,
  closed: false,
  show: false
  }
 },
 methods: {
  startTimer(){
  if(this.duration > 0){
   this.timer = setTimeout(() => {
   if(!this.closed){
    this.close();
   }
   }, this.duration);
  }
  },
  clearTimer(){
  clearTimeout(this.timer);
  },
  close(){
  this.closed = true;
  if(typeof this.onClose === 'function'){
   // 調(diào)用onClose方法,以從p-message.js中的instances數(shù)組中移除當(dāng)前組件,不移除的話(huà)就占空間了
   this.onClose();
  }
  },
  // 銷(xiāo)毀組件
  destroyElement(){
  _offEvent(this.$el, 'transitionend', this.destroyElement);
  // 手動(dòng)銷(xiāo)毀組件
  this.$destroy(true);
  this.$el.parentNode.removeChild(this.$el);
  },
 },
 watch: {
  // 監(jiān)聽(tīng)closed,如果它為true,則銷(xiāo)毀message組件
  closed(newVal){
  if(newVal){
   this.show = false;
   // message過(guò)渡完成后再去銷(xiāo)毀message組件及移除元素
   _addEvent(this.$el, 'transitionend', this.destroyElement);
  }
  }
 },
 mounted() {
  this.startTimer();
 }
 }
</script>
<style lang="stylus">
@import "p-message.styl"
</style>

p-message.js

import Vue from 'vue';
import PMessage from './PMessage.vue';
import {popupManager} from "../../common/js/popup-manager";
let PMessageControl = Vue.extend(PMessage);
let count = 0;
// 存儲(chǔ)message組件實(shí)例,如需有關(guān)閉所有message的功能就需要將每個(gè)message組件都存儲(chǔ)起來(lái)
let instances = [];
const isVNode = function (node) {
 return node !== null && typeof node === 'object' && Object.prototype.hasOwnProperty.call(node, 'componentOptions');
};
const Message = function (options) {
 options = options || {};
 if(typeof options === 'string'){
 options = {
  message: options
 };
 }
 let id = 'message_' + ++count;
 let userOnClose = options.onClose;
 // PMsesage.vue銷(xiāo)毀時(shí)會(huì)調(diào)用傳遞進(jìn)去的onClose,而onClose的處理就是將指定id的message組件從instances中移除
 options.onClose = function (){
 Message._close(id, userOnClose);
 };
 /* 這里傳遞給PMessageControl的data不會(huì)覆蓋PMessage.vue中原有的data,而是與PMessage.vue中原有的data進(jìn)行合并,類(lèi)似
 * 與mixin,包括傳遞methods、生命周期函數(shù)也是一樣 */
 let instance = new PMessageControl({
 data: options
 });
 // 傳遞vNode
 if(isVNode(instance.message)){
 instance.$slots.default = [instance.message];
 instance.message = null;
 }
 instance.id = id;
 // 渲染元素,隨后使用原生appendChild將dom插入到頁(yè)面中
 instance.$mount();
 let $el = instance.$el;
 // message彈窗的z-index由popupManager來(lái)提供
 $el.style.zIndex = popupManager.getNextZIndex();
 document.body.appendChild($el);
 // 將message顯示出來(lái)
 instance.show = true;
 console.log(instance)
 instances.push(instance);
 return instance;
};
// message簡(jiǎn)化操作
['success','error'].forEach(function (item) {
 Message[item] = options => {
 if(typeof options === 'string'){
  options = {
  message: options
  }
 }
 options.type = item;
 return Message(options);
 }
});
/**
 * 從instances刪除指定message,內(nèi)部使用
 * @param id
 * @param userOnClose
 * @private
 */
Message._close = function (id, userOnClose) {
 for(var i = 0, len = instances.length; i < len; i++){
 if(instances[i].id === id){
  if(typeof userOnClose === 'function'){
  userOnClose(instances[i]);
  }
  instances.splice(i, 1);
  break;
 }
 }
};
// 關(guān)閉所有message
Message.closeAll = function () {
 for(var i = instances.length - 1; i >= 0; i--){
 instances.close();
 }
};
export default Message;

popup-manager.js

let zIndex = 1000;
let hasZIndexInited = false;
const popupManager = {
 // 獲取索引
 getNextZIndex(){
 if(!hasZIndexInited){
  hasZIndexInited = true;
  return zIndex;
 }
 return zIndex++;
 }
};
export {popupManager};
p-index.js
import pMessage from './p-message.js';
export default pMessage;
p-message.styl
.p-message{
 position: fixed;
 top: 20px;
 left: 50%;
 padding: 8px 15px;
 border-radius: 4px;
 background-color: #fff;
 color: #000;
 transform: translateX(-50%);
 transition: opacity .3s, transform .4s;
 &.message-fade-enter,
 &.message-fade-leave-to{
 opacity: 0;
 transform: translateX(-50%) translateY(-30px);
 }
 &.message-fade-enter-to,
 &.message-fade-leave{
 opacity: 1;
 transform: translateX(-50%) translateY(0);
 }
 &.error{
 color: #ff3737;
 }
 .p-message-icon{ /* 使圖標(biāo)與內(nèi)容能夠垂直居中 */
 display: table-cell;
 vertical-align: middle;
 width: 64px;
 height: 45px;
 &.p-message-icon-success{
  background: url("../../assets/images/icons/message-icon/icon_success.png") no-repeat 0 0;
 }
 &.p-message-icon-error{
  background: url("../../assets/images/icons/message-icon/icon_error.png") no-repeat 0 0;
 }
 }
 .p-message-content{ /* 使圖標(biāo)與內(nèi)容能夠垂直居中 */
 display: table-cell;
 vertical-align: middle;
 padding-left: 15px;
 }
}

main.js

// 引入pMessage組件
import pMessage from './components/p-message/p-index.js';
// 將pMessage綁定到Vue.prototype中。這樣在組件中就可以通過(guò)this.$pMessage()的形式來(lái)使用了
Vue.prototype.$pMessage = pMessage;

相關(guān)文章

  • vue2.0 自定義 餅狀圖 (Echarts)組件的方法

    vue2.0 自定義 餅狀圖 (Echarts)組件的方法

    下面小編就為大家分享一篇vue2.0 自定義 餅狀圖 (Echarts)組件的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • Vue全局注冊(cè)與局部注冊(cè)兩種組件注冊(cè)的方式

    Vue全局注冊(cè)與局部注冊(cè)兩種組件注冊(cè)的方式

    本文主要介紹了Vue全局注冊(cè)與局部注冊(cè)兩種組件注冊(cè)的方式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • vue中使用elementUI組件手動(dòng)上傳圖片功能

    vue中使用elementUI組件手動(dòng)上傳圖片功能

    Vue是一套構(gòu)建用戶(hù)界面的框架, 開(kāi)發(fā)只需要關(guān)注視圖層, 它不僅易于上手,還便于與第三方庫(kù)或既有項(xiàng)目的整合。這篇文章主要介紹了vue中使用elementUI組件手動(dòng)上傳圖片,需要的朋友可以參考下
    2019-12-12
  • Vue動(dòng)態(tài)權(quán)限登錄實(shí)現(xiàn)(基于路由與角色)

    Vue動(dòng)態(tài)權(quán)限登錄實(shí)現(xiàn)(基于路由與角色)

    很多應(yīng)用都會(huì)需要對(duì)不同的用戶(hù)進(jìn)行權(quán)限控制,本文主要介紹了Vue動(dòng)態(tài)權(quán)限登錄實(shí)現(xiàn)(基于路由與角色),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • vue3.0+vant3.0快速搭建項(xiàng)目的實(shí)現(xiàn)

    vue3.0+vant3.0快速搭建項(xiàng)目的實(shí)現(xiàn)

    本文主要介紹了vue3.0+vant3.0快速搭建項(xiàng)目的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • vue v-for出來(lái)的列表,點(diǎn)擊某個(gè)li使得當(dāng)前被點(diǎn)擊的li字體變紅操作

    vue v-for出來(lái)的列表,點(diǎn)擊某個(gè)li使得當(dāng)前被點(diǎn)擊的li字體變紅操作

    這篇文章主要介紹了vue v-for出來(lái)的列表,點(diǎn)擊某個(gè)li使得當(dāng)前被點(diǎn)擊的li字體變紅操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-07-07
  • Vue動(dòng)態(tài)獲取width的方法

    Vue動(dòng)態(tài)獲取width的方法

    今天小編就為大家分享一篇Vue動(dòng)態(tài)獲取width的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • vue3 表單搜索內(nèi)容回顯到地址欄的實(shí)例代碼

    vue3 表單搜索內(nèi)容回顯到地址欄的實(shí)例代碼

    這篇文章主要介紹了vue3 表單搜索內(nèi)容回顯到地址欄的實(shí)例代碼,地址欄輸入內(nèi)容回顯到form表單,同理表單輸入內(nèi)容也要回顯到地址欄中,本文結(jié)合實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-09-09
  • Vue利用localStorage本地緩存使頁(yè)面刷新驗(yàn)證碼不清零功能的實(shí)現(xiàn)

    Vue利用localStorage本地緩存使頁(yè)面刷新驗(yàn)證碼不清零功能的實(shí)現(xiàn)

    這篇文章主要介紹了Vue利用localStorage本地緩存使頁(yè)面刷新驗(yàn)證碼不清零功能的實(shí)現(xiàn),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Vue封裝Axios請(qǐng)求和攔截器的步驟

    Vue封裝Axios請(qǐng)求和攔截器的步驟

    這篇文章主要介紹了Vue封裝Axios請(qǐng)求和攔截器的步驟,幫助大家更好的對(duì)axios進(jìn)行封裝并將接口統(tǒng)一管理,同時(shí)為請(qǐng)求和響應(yīng)設(shè)置攔截器interceptors。,感興趣的朋友可以了解下
    2020-09-09

最新評(píng)論