前言css
哈嘍你們好啊,又有一週不見了呢,這周咱們要講的是個內容一個是上上週講到的VueBusevent的組件vue-happy-bus的源碼解讀另外就是手擼一個toast提示框組件。vue
vue-happy-bus源碼解讀vue-router
若是沒有看過vue-happy-bus使用方法的同窗請去看看個人這個文章,裏面講vue-happy-bus的使用方法仍是比較適合初學者的。瀏覽器
Vue eventbus 使用中的重複觸發解決方案及存在的Bug首先說明下面對源碼的解讀僅表明個人我的觀點,若是你們有興趣仍是本身去理解源碼,或者在下面討論區積極評論和討論,我會隨時關注和修改該內容的。bash
這裏注意一下下面的註釋,我把個人理解寫在下面的註釋裏面熱,可是仍是有些不盡人意的,這裏歡迎你們指正。app
(function (global, factory) {
//這裏其實就是在判斷數據類型,爲下面的function準備參數Vue$和exports這兩個將要傳入下面的function
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('vue')) :
typeof define === 'function' && define.amd ? define(['exports', 'vue'], factory) :
(factory((global['happy-bus'] = {}),global.Vue$));
// 這裏規定對象爲window,則能夠判斷window對象是不是綁定了Vue原型,注意這裏是嚴格模式
}(this, (function (exports,Vue$) { 'use strict';
//嚴格模式下Vue$和Vue$判斷自身是否存在default屬性,存在Vue$就是efaul,不然只是Vue$自己
Vue$ = Vue$ && Vue$.hasOwnProperty('default') ? Vue$['default'] : Vue$;
//定義版本號
var version = "0.1.0";
//判斷window對象是否綁定Vue
var Vue = Vue$;
if (typeof window !== 'undefined' && window.Vue) {
Vue = window.Vue;
}
// 記錄全部的事件類型與事件函數,這裏新建了一個Vue做爲事件總集
var EventStore = {};
var Bus = new Vue();
// 移除全部事件的方法
var destroyHandler = function destroyHandler() {
// this 爲調用此方法的vue組件
var currentEventObj = EventStore[this._uid];
if (typeof currentEventObj === 'undefined') {
return;
}
for (var type in currentEventObj) {
var key = Array.isArray(type) ? type.join(',') : type;
// Bus 解綁事件,在調用bus.$emit後直接調用bus.$off事件
Bus.$off(type, currentEventObj[key]);
}
// 刪除記錄的事件集合
delete EventStore[this._uid];
};
//定義BusFactory的總體使用方法,分爲四個$on,$off,$once,$emit四種。
var BusFactory = function BusFactory(vm) {
// 當前調用組件的 destroyed 鉤子,以銷燬方法
var destroyed = vm.$options.destroyed;
// 當前組件的惟一標示(vue生成的自增ID),自增id能夠作項目的時候看看好比css樣式上就有顯示
var uid = vm._uid;
// 初始化當前組件的事件集合對象
EventStore[uid] = {};
// 爲當前組件掛載destroyed鉤子
!destroyed.includes(destroyHandler) && destroyed.push(destroyHandler);
return {
$on: function $on(type, handler) {
//取到全部的bus.$emit
console.log(type, handler)
var key = Array.isArray(type) ? type.join(',') : type;
// 循環取出bus.$emit的鍵值
console.log(key)
EventStore[uid][key] = handler;
//找出bus.$on的使用方法相似於(em) => {
// console.log(em)//這樣的
// }
//這個方法也是取到bus.$on的自己
console.log(EventStore[uid][key])
Bus.$on(type, handler);
},
//刪除合集就不用說了吧,判斷type的true或者false便可,就能刪除事件合集
$off: function $off(type, handler) {
// $off() 時 type 爲空,移除全部事件
if (!type) {
// 刪除該uid下事件集合
delete EventStore[uid];
Bus.$off();
return;
}
//其實每一個key刪除合集都是對應的那個鍵值刪除。刪除整個事件合集便可。
var key = Array.isArray(type) ? type.join(',') : type;
// 刪除對應的事件
delete EventStore[uid][key];
Bus.$off(type, handler);
},
$once: function $once() {
//相信我不用多說了吧ones方法只能被調用一次因此也是不存在什麼刪除的方法的,不過爲了以防萬一和內存過多的佔用只能刪除合集才行
return Bus.$once.apply(Bus, arguments);
},
$emit: function $emit() {
//這個就更好說了,傳遞方式直接進行傳遞就行.
return Bus.$emit.apply(Bus, arguments);
}
};
};
BusFactory.$emit = function () {
//定義emit方法
return Bus.$emit.apply(Bus, arguments);
};
BusFactory.$once = function () {
//定義once方法
return Bus.$once.apply(Bus, arguments);
};
exports['default'] = BusFactory;
exports.version = version;
Object.defineProperty(exports, '__esModule', { value: true });
//最後講一下BusFactory方法能夠經過main.js進行全局綁定這個上上週的文章裏已經講過,能夠去看看我上上週的文章
})));
複製代碼
注意一下這裏面註冊了四個方法$on,$off,$once,$emit,比較重要的是$off事件在使用完$on事件以後直接在destroyed自動註冊了一個銷燬事件,這樣的方式是比較好的不用咱們手動註冊銷燬它自動進行匹配和銷燬操做,在這裏銷燬以後不用擔憂二次觸發的問題,只要安心去管理好你的傳輸的值就好。函數
這裏比較好的一個寫法我認爲是在建立$emit事件的時候它自動註冊了一個$off方法在使用完$emit方法以後直接使用循環查出正在使用$on方法接收的參數,以後在使用完$on方法以後直接在內部進行了銷燬,並不會影響二次調用,不過這個組件在解決小項目的時候比較適用,或者在解決項目前期解決緊急上線的時候使用比較好。post
手擼一個vue toast提示框組件ui
講一下思路,初始是在想瀏覽器的默認彈出框太難看了,因此要作一個不用點擊的全局提示,因此toast提示框組件就應運而生了,下面講講總體思路。this
首先咱們在某個驗證狀況下須要,有各類不一樣的提示好比,綠色的完成提示,又或者是紅色的錯誤提示,那麼咱們思路有了,提示都是由一個提示語和顯示的顏色組成的,那麼這個組件就是須要傳入兩個參數,第一個提示標題框的顏色,第二個提示語。
首先建立一個toast.js,裏面的寫法跟普通的js寫法相同
//這裏就是兩個參數傳入一個顏色一個提示語
function toast(color, text){
//建立一個div以後把參數上的提示語放上去再加入顏色
const body = document.getElementsByTagName('body')
const toast = document.createElement("div")
toast.innerText = text
toast.className = 'toast' +" "+ color
document.body.appendChild(toast)
//定義一個顯示時間多少秒以後消失
setTimeout(function(){
document.body.removeChild(toast)
}, 5000)
}
exports.toast= toast;
複製代碼
接下來就是css
.toast {
position: fixed;
top: -100px;
left: 50%;
margin-left: -199px;
width: 398px;
height: 50px;
animation: myfirst 5s;
animation-direction:alternate;
z-index: 9999999999;
text-align: center;
}
.toast.red {
background-color: #fbe7ea;
border: 1px solid #e57785;
line-height: 50px;
color: #e57785;
}
.toast.blue {
background-color: #c5eafb;
border: 1px solid #0083ae;
line-height: 50px;
color: #0083ae;
}
.toast.green {
background-color: #dff0d7;
border: 1px solid #378d4e;
line-height: 50px;
box-sizing: border-box;
color: #378d4e;
}
#toast_close{
cursor: pointer;
display: block;
float: right;
width: 50px;
height: 50px;
text-align: center;
font-size: 30px;
position: absolute;
top: 0;
right: 0;
}
@keyframes myfirst
{
0% {top: -200px;display: block;}
25% {top: 100px;}
50% {top: 100px;}
75% {top: 100px;}
100% {top: -200px;}
}
複製代碼
以後是在全局引入
//main.js
...
//這裏部分的就不作演示了,只演示引入部分
import './lib/toast/toast.css'
import toast from './lib/toast/toast.js'
//把toast.js掛載在原型上進行引用
Vue.prototype.$toast = toast;
複製代碼
建立a.vue
<template>
<button v-on:click="toast()">提示</button>
</template>
export default {
name: '',
data: function () {
},
methods: {
toast:function(){
this.$toast.toast('green', '看到了嗎,這就是toast提示框')
}
}
}
<script>
</script>
<style>
</style>
複製代碼
這樣調用就完成了,其實很是簡單封裝vue組件,可是我這個僅適用於個人項目使用,封裝還不夠完美,另外能夠用mixinsqu封裝,也能夠用vue專門暴露出的方法進行封裝,我這裏只是做爲一個演示,並不表明只有這一種方法可行,另外有興趣能夠去了解一下我以前寫過的Vue mixins淺談使用方法及須要注意的點,下面有連接。
Vue mixins淺談使用方法及須要注意的點後記
感受今天講的 有些少,可是文章不在於寫多少字而在於它的質量是否精湛,只有這點就足夠了,好了有問題須要討論的個位,請在下面評論區討論,謝謝,我先閃了去擼vue-router了,這裏作個預告下週我會淺析講解vue-router的使用。