Vue2.0 進階組件篇 3 值得一看的(Toast 組件)

做者 混元霹靂手-ziksangjavascript


如今發覺睡覺的時間愈來愈少,項目愈來愈多,組件越寫越停不下來,由於過段時間要作一個技術分享,還有不少趕着急的項目等着我,今天不睡覺也要把這個教程寫完分享給你們,若是你們想參加個人技術分享請用微信打開個人分享會,歡迎你們收聽
gitbook.cn/m/mazi/acti…

接下來仍是按着咱們約定的來html

2.代碼運行vue-cli 2.1版本前端

3.組件代碼都在components文件夾裏vue

4.主代碼邏輯都在 App.vue文件夾裏java

我什麼都不要我只要jquery

git

學以前我給你們補幾個知識點,用菊花想也知道若是咱們用toast組件確定是插入一個toast節點,那咱們本來用jquery如何實現,那就是定義好一個基本的toast dom節構,而後插入到根節點裏,那其實vue-toast也是這麼實現的es6

學以前咱們先補兩個知識點。這個兩個知識點學會了你就學會了,先看一個官方給的一個例子,我也是看這個東西才明白一些東西的vue-cli

使用基礎 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()依賴於vue
const 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

相關文章
相關標籤/搜索