作者 混元霹靂手-ziksang
現在發覺睡覺的時間越來越少,專案越來越多,元件越寫越停不下來,因為過段時間要做一個技術分享,還有很多趕著急的專案等著我,今天不睡覺也要把這個教程寫完分享給大家,如果大家想參加我的技術分享請用微信開啟我的分享會,歡迎大家收聽
gitbook.cn/m/mazi/acti…
接下來還是按著我們約定的來
2.程式碼執行vue-cli 2.1版本
3.元件程式碼都在components資料夾裡
4.主程式碼邏輯都在 App.vue資料夾裡
我什麼都不要我只要
贊
學之前我給大家補幾個知識點,用菊花想也知道如果我們用toast元件肯定是插入一個toast節點,那我們原本用jquery如何實現,那就是定義好一個基本的toast dom節構,然後插入到根節點裡,那其實vue-toast也是這麼實現的
學之前我們先補兩個知識點。這個兩個知識點學會了你就學會了,先看一個官方給的一個例子,我也是看這個東西才明白一些東西的
使用基礎 Vue 構造器,建立一個“子類”。引數是一個包含元件選項的物件。
data 選項是特例,需要注意 - 在 Vue.extend() 中它必須是函式
<div id="mount-point"></div>
// 建立構造器
var Profile = Vue.extend({
template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
data: function () {
return {
firstName: 'Walter',
lastName: 'White',
alias: 'Heisenberg'
}
}
})
// 建立 Profile 例項,並掛載到一個元素上。
new Profile().$mount('#mount-point')
//結果如下:
<p>Walter White aka Heisenberg</p>複製程式碼
如果我們想建立一個例項,就是所謂的dom結構,我們是在vue實列上建立一個'子類',可以包含,所有的選項物件,那我們就要那到vue.extend(),並掛到已經現在的一個dom節點上,那就是#mount-point節點
//在下次 DOM 更新迴圈結束之後執行延遲迴調。在修改資料之後立即使用這個方法,獲取更新後的 DOM。
// 修改資料
vm.msg = 'Hello'
// DOM 還沒有更新
Vue.nextTick(function () {
// DOM 更新了
})複製程式碼
這個知識點,其實vue講起來是資料驅動,本質上還是在改變dom,但是我們在改變資料的時候。dom會從新渲染,在dom從新渲染的時候,你想拿到你想得到的dom或者改變dom ,比方說remove dom,為了確保一定能執行正確的操作,因此vue有一個更新dom的事件佇列,等到這個佇列完成,你再進行dom操作
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>y</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<script>
(function(doc, win) {
var docEl = doc.documentElement,
resizeEvt = 'orientationchange' in window ? 'orientationchange' : 'resize',
recalc = function() {
var clientWidth = docEl.clientWidth;
if (!clientWidth) return;
if (clientWidth >= 640) {
docEl.style.fontSize = '100px';
} else {
docEl.style.fontSize = 100 * (clientWidth / 640) + 'px';
}
};
if (!doc.addEventListener) return;
win.addEventListener(resizeEvt, recalc, false);
doc.addEventListener('DOMContentLoaded', recalc, false);
})(document, window);
</script>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>複製程式碼
還是跟上期的spinner元件一樣,先把html的適配給做一下
components/toast/toast.vue
<template>
<transition name='fade'>
<div v-show='visible' :class='position' class='toast'>
<i>{{message}}</i>
</div>
</transition>
</template>
<script>
export default {
data() {
return {
visible: false,
message : '',
position : ''
};
}
}
</script>
<style>
.toast {
position: fixed;
left:50%;
transform:translate(-50%,-50%) scale(1);
word-wrap:break-word;
padding:10px;
text-align: center;
z-index:9999;
font-size:.3rem;
max-width:80%;
color: #fff;
border-radius: 5px;
background: rgba(0,0,0,0.7);
overflow: hidden;
}
.toast.middle{
top:50%;
}
.toast.top{
top:10%;
}
.toast.bottom{
top:90%;
}
.fade-enter-active, .fade-leave-active {
transition: transform .5s
}
.fade-enter, .fade-leave-active {
transform:translate(-50%,-50%) scale(0);
}
</style>複製程式碼
我們在toast.vue先設計一個你想要的toast元件的樣子,我們在data裡宣告瞭三個資料
一.visible 對toast的顯示和隱藏
二.message 顯示的文字
三.positon 我們寫在動態class裡,根據不同的資料改變不同的位置
components/toast/toast.js
import Vue from 'vue'
const ToastConstructor = Vue.extend(require('./toast.vue'))
let removeDom = event => {
event.target.parentNode.removeChild(event.target);
};
ToastConstructor.prototype.close = function() {
this.visible = false;
this.$el.addEventListener('transitionend', removeDom);
};
const Toast = (options = {}) => {
var instance = new ToastConstructor().$mount(document.createElement('div'))
let duration = options.duration || 2500;
instance.message = typeof options === 'string' ? options : options.message
instance.position = options.position || 'middle'
document.body.appendChild(instance.$el);
instance.visible = true;
Vue.nextTick(() => {
instance.timer = setTimeout(function() {
instance.close();
}, duration);
})
return instance
}
export default Toast複製程式碼
首先我們要先import vue 因為我們Vue.extend()依賴於vueconst ToastConstructor = Vue.extend(require('./toast.vue'))
這段程式碼就像我前面講的一樣,我們用vue.extend()建立toast子實列
那問題來了,我們缺少一個掛載點,怎麼辦,不要急,看後面
在Toast函式裡,我們用了es6語法(options = {}),我們把options先用了一個預設引數,預設引數是一個物件,用來傳不同的方式,顯示 不同toast的樣式var instance = new ToastConstructor().$mount(document.createElement('div'))
當我們執行Toast()的時候,我們肯定就要開始執行Toast函式了,如果執行下去我們一行一行看
這裡我們就用到前面我所說的,如何去把子實列掛載的問題,我們先把這子實列new出來,然後用$mount方法去掛到我們自己建立的dom節點上,那就解決了掛載的問題,
此時的instance就是toast元件的實列了,我們再看看官方的一個說法,如何拿到實列上的資料,如何改變例項上的資料,兩者是否同步更新
ar data = { a: 1 }
var vm = new Vue({
data: data
})
vm.a === data.a // -> true
// 設定屬性也會影響到原始資料
vm.a = 2
data.a // -> 2
// ... 反之亦然
data.a = 3
vm.a // -> 3複製程式碼
這個官方例子,已經很明確的告訴了我們,通過例項改變資料,此時例項內部資料會同時改變
那OK我們接下去看let duration = options.duration || 2500;
當我們如果沒有設定顯示時長,那我們則使用預設2500,這個時長,我們沒有必要放到data資料裡,因為這個不關於toast任何顯示操作
instance.message = typeof options === 'string' ? options : options.message複製程式碼
我們此時要顯示toast元件上提示文字的時候,我們傳資料有兩種形式,第一就是直接Toast('aaaa'),那此時我們傳的引數就不是一個物件,而是一個字串,所以我們進行判斷,當我們引數是一個字串則直接使用options這個引數當作message
還有一種可能是傳參是一個物件,Toast({message:'aaaa'})此時我們就要用options.message了instance.position = options.position || 'middle'
這個很好理解,當我們傳物件的時候,裡面有postion這個屬性的時候這用傳的屬性,不然用預設的document.body.appendChild(instance.$el);
所有的我們要toast所顯示的引數我們都配置好了,接下來我們就要把這個toast整個節點給新增到body裡面,那我們會奇怪,$el是什麼鬼東西,如果我們console.log(instance.$el)你會發現,是一整個toast的dom結構,那就對了,我們需要的就是這個東西新增到body裡
然後我們讓visible = true 別人都說這個是多此一舉,因為我要做transition動畫。所以這個必須要做一個顯示隱藏操作,
Vue.nextTick(() => {
instance.timer = setTimeout(function() {
instance.close();
}, duration);
})複製程式碼
接下來很簡單,我們等一個時間等待操作,當多少時間後我們再進行刪除這個toast元件
ToastConstructor.prototype.close = function() {
this.visible = false;
this.$el.addEventListener('transitionend', removeDom);
};複製程式碼
我們還是在子實列的原型上寫了一個close方法,可以拿到實列上的屬性,我們對$el進行transitionend
動畫結束監聽,當動畫結束時的,我們才進行刪除節點,呼叫的是removeDom方法
最後return instance,可以對實列再進行操作
最後我們在App.vue
<template>
<div>
<button @click='a'>點選1</button>
<button @click='b'>點選2</button>
</div>
</template>
<script>
import Toast from './components/zk-toast/toast.js'
export default {
methods : {
a () {
Toast('只是一個文字彈出')
},
b() {
Toast({
message : "有位置的設定和時間設定",
position: 'top',
duration : 1000
})
}
}
}
</script>
<style>
</style>複製程式碼
你們就可以點選檢視效果了
一套啪啪啪拳已經打完收工,在這個原理上,我們可以再去建立一個些messagebox這種元件,其實本質就上就是類似的東西,每天都在夢想而奮鬥,晚安大家!
渣渣前端開發工程師,喜歡鑽研,熱愛分享和講解教學, 微信 zzx1994428 QQ494755899
支援我繼續創作和感到有收穫的話,請向我打賞點吧
如果轉載請標註出自@混元霹靂手ziksang