以 Toast 爲例講解 Vue 組件的概念

組件是 Vue 的一個極其重要的概念。在移動端網頁開發時,Toast 組件使用也是很是頻繁的。本文便以 Toast 組件爲例,來說解 Vue 組件的部分知識點。javascript

1. 單文件組件

平常開發時,咱們項目文件夾一般都是使用 vue-cli 建立的,以 單文件組件 的方式來組織代碼的。按照平日的開發流程,如今先建立一個 Toast.vue 文件。css

咱們開始關注實現 Toast 組件的一些要點:html

  1. 該組件有兩個 prop : visible 與 msg。visible 控制顯示與隱藏,msg 是顯示的內容
  2. 該組件的位置: 相對於屏幕視口來肯定位置,position 設置爲 fixed,而且把 z-index 值設置大一點。爲了讓元素居中顯示,要用到 translate 屬性
  3. 該組件顯示或者隱藏時添加了動畫: 使用 transition 組件來實現過渡效果

根據上文的分析,如今的代碼以下。vue

<template>
  <transition name="toast-bounce">
    <div class="toast" v-show="visible">
      <p class="toast-msg">{{ msg }}</p>
    </div>  
  </transition>
</template>
<script> export default { name: 'Toast', props: { visible: { type: Boolean, required: true }, msg: { type: String, required: true } } } </script>
<style lang="scss" scoped> // 添加過渡效果 .toast-bounce-enter, .toast-bounce-leave { opacity: 0; } .toast { box-sizing: border-box; position: fixed; max-width: 80%; left: 50%; top: 50%; padding: 20px; z-index: 99; transition: all .3s ease; transform: translate(-50%, -50%); border-radius: 10px; background: rgba(0, 0, 0, 0.7); color: #fff; text-align: center; .toast-msg { text-align: center; } } </style>複製代碼

在須要使用 Toast 組件的頁面,引入該組件,註冊以後就能使用了。java

2. 如何手動建立組件

以單文件組件引入,有幾個不方便的地方。git

  • Toast 每次使用都要導入
  • 父組件的 state 要包含一個 visible 的屬性 (假設咱們沒有使用mixin)
  • 設置 父組件的 visible 爲 true 以後,用一個定時器再把 visible 設置爲 false

相似這樣使用頻率較高的組件,最便捷的方式是經過調用一個函數來完成組件的建立掛載以及銷燬。但而在開發項目過程當中,咱們把精力放在了組件的實現上,忽略了一些這些操做。接下來咱們將演示手動如何建立 Toast 組件,附加到 document.body 下,在顯示一段時間後,銷燬組件,再移除該元素。github

組件的建立與掛載

Vue 單文件的 script 標籤僅僅是導出一個包含組件選項的對象。爲了建立組件,先使用 Vue.extend 獲得一個構造器,接下來經過 new 進行實例化。這裏的構造函數有一個可選參數,類型是 Object,能夠傳入的屬性有 el,propsData等。vue-cli

import ToastConfig from './Toast.vue'
// 構造器
const ToastConstructor = Vue.extend(ToastConfig)
// 經過 new 建立組件
const instance = new ToastConstructor()複製代碼

Toast 組件在建立時,兩個 prop: visible, msg 必需要傳入。在 new 實例化時,配置 propsData 參數來設置組件所需的 prop。element-ui

const instance = new ToastConstructor({
    propsData: {
        msg: 'msg',
        visible: false   
    }
})複製代碼

組件建立與掛載是兩個不一樣的概念,組件建立時,掛載階段還沒開始,DOM 元素中不含該節點。在 掛載 了以後,纔會被瀏覽器渲染。
在建立實例時,不但要設置 propsData屬性,還要設置掛載點 el 屬性,而且將組件附在 document.body 以後。api

const instance = new ToastConstructor({
    el: document.createElement('div'),
    propsData: {,
        msg: 'msg',
        visible: false   
    }
})
// 組件建立成功以後掛載
document.body.appendChild(instance.$el)複製代碼

掛載以後,顯示 toast 組件。再開啓一個定時器,在 3s 以後隱藏組件。

Vue.nextTick(() => {
    instance.visible = true
    setTimeout(() => {
      instance.close()
    }, 3000)
})複製代碼

組件的銷燬

Toast 組件隱藏的動畫結束時,觸發 transitionend 事件。instance.$el 返回組件的根元素,監聽該元素的 transitionend 事件,在回調函數中 銷燬 組件,同時從DOM樹中移除。

// 在 ToastConstructor 上添加兩個銷燬組件與移除DOM元素的函數
// 隱藏組件
ToastConstructor.prototype.close = function () {
  this.visible = false
  this.$el.addEventListener('transitionend', this.destroyeInstance.bind(this))
}
// 銷燬組件,移除DOM元素
ToastConstructor.prototype.destroyeInstance = function () {
  this.$destroy(true)
  this.$el.removeEventListener('transitionend', this.destroyeInstance)
  this.$el.parentNode.removeChild(this.$el)
}複製代碼

完整代碼片斷點擊 這裏

3. 小的調整

若是在短期頻繁調用 toast 函數,document.body 下面存在多個 toast 組件,後一個會覆蓋前一個。考慮到移動端的特色,咱們但願在同一個時間點上,不論 toast 函數調用有多頻繁,document.body 只有會有一個 toast 組件。
接下來的調整思路大體以下:

  1. 檢測是否存在 Toast 組件
  2. 不存在,建立便可
  3. 存在的話,從新設置 state 中的 visible 與 msg,移除銷燬組件的定時器,移除對 transitionend 時間的監聽

代碼須要進行一些的調整。

// 在函數以外,定義兩個變量
// 組件銷燬時,instance 也要置爲 null
let instance = null
let timer = null
function toast (msg = '默認信息') {
  // 判斷 instance 是否存在
  if (instance) {
    instance.visible = true
    instance.msg = msg
    if (timer) {
      clearInterval(timer)
    }
    instance.$el.removeEventListener('transitionend', instance.destroyeInstance)
  } else {
      //... 
  }
  // ...
}複製代碼

完整代碼片斷點擊 這裏

固然咱們也能夠再更進一步,把 toast 函數註冊爲 Vue 插件,在須要的地方經過 this.$toast 調用便可。element-ui 的 message,vux 的 Toast 都支持插件方式調用。

4. 總結

跟一些成熟的 Vue ui 庫,例如:mint-ui 的 Toast 組件相比,如今的 Toast 組件不足之處不少。但經過編寫一個極其簡單的 Toast 組件,瞭解到 Vue 組件的部分概念,知道了到如何手動建立,銷燬組件,如何結合 transition 製做一些簡單的動畫,有助於咱們更好的理解 Vue 組件的思想 ,並且之後在使用第三方庫的一些組件時,能大體知曉其原理。

參考資料

相關文章
相關標籤/搜索