相信普通的vue組件你們都會寫,定義 -> 引入 -> 註冊 -> 使用
,行雲流水,一鼓作氣,可是若是咱們今天是要自定義一個彈窗組件呢?css
首先,咱們來分析一下彈窗組件的特性(需求): 0. 輕量 --一個組件小於 1Kib (實際打包完不到0.8k)vue
<template>
裏面寫 <toast :show="true" text="彈窗消息"></toast>
今天,咱們就抱着上面2個需求點,來實現一個基於vue的toast彈窗組件,下圖是最終完成的效果圖.git
文件位置 /src/toast/toast.vue
github
<template>
<div class="wrap">我是彈窗</div>
</template>
<style scoped>
.wrap{
position: fixed;
left: 50%;
top:50%;
background: rgba(0,0,0,.35);
padding: 10px;
border-radius: 5px;
transform: translate(-50%,-50%);
color:#fff;
}
</style>
複製代碼
<template>
<div id="app">
<toast></toast>
</div>
</template>
<script>
import toast from './toast/toast'
export default {
components: {toast},
}
</script>
複製代碼
能夠看到,已經顯示出一個靜態的彈出層了,接下來咱們就來看看如何實現動態彈出.api
咱們先在 /src/toast/
目錄下面,新建一個index.js
, 而後在index.js裏面,敲入如下代碼(因爲該代碼耦合比較嚴重,因此就不拆開一行一行講解了,改爲行內註釋)bash
文件位置 /src/toast/index.js
app
import vue from 'vue'
// 這裏就是咱們剛剛建立的那個靜態組件
import toastComponent from './toast.vue'
// 返回一個 擴展實例構造器
const ToastConstructor = vue.extend(toastComponent)
// 定義彈出組件的函數 接收2個參數, 要顯示的文本 和 顯示時間
function showToast(text, duration = 2000) {
// 實例化一個 toast.vue
const toastDom = new ToastConstructor({
el: document.createElement('div'),
data() {
return {
text:text,
show:true
}
}
})
// 把 實例化的 toast.vue 添加到 body 裏
document.body.appendChild(toastDom.$el)
// 過了 duration 時間後隱藏
setTimeout(() => {toastDom.show = false} ,duration)
}
// 註冊爲全局組件的函數
function registryToast() {
// 將組件註冊到 vue 的 原型鏈裏去,
// 這樣就能夠在全部 vue 的實例裏面使用 this.$toast()
vue.prototype.$toast = showToast
}
export default registryToast
複製代碼
附一個傳送門 vue.extend 官方文檔函數
到這裏,咱們已經初步完成了一個能夠全局註冊和動態加載的toast組件,接下來咱們來試用一下看看優化
./src/main.js
) 註冊一下組件文件位置 /src/main.js
動畫
import toastRegistry from './toast/index'
// 這裏也能夠直接執行 toastRegistry()
Vue.use(toastRegistry)
複製代碼
第二步
的引用靜態組件的代碼,改爲以下<template>
<div id="app">
<input type="button" value="顯示彈窗" @click="showToast">
</div>
</template>
<script>
export default {
methods: {
showToast () {
this.$toast('我是彈出消息')
}
}
}
</script>
複製代碼
能夠看到,咱們已經不須要
在頁面裏面引入
跟註冊
組件,就能夠直接使用this.$toast()
了.
如今咱們已經初步實現了一個彈窗.不過離成功還差一點點,缺乏一個動畫,如今的彈出和隱藏都很生硬.
咱們再對 toast/index.js
裏的showToast
函數稍微作一下修改(有註釋的地方是有改動的)
文件位置 /src/toast/index.js
function showToast(text, duration = 2000) {
const toastDom = new ToastConstructor({
el: document.createElement('div'),
data() {
return {
text:text,
showWrap:true, // 是否顯示組件
showContent:true // 做用:在隱藏組件以前,顯示隱藏動畫
}
}
})
document.body.appendChild(toastDom.$el)
// 提早 250ms 執行淡出動畫(由於咱們再css裏面設置的隱藏動畫持續是250ms)
setTimeout(() => {toastDom.showContent = false} ,duration - 1250)
// 過了 duration 時間後隱藏整個組件
setTimeout(() => {toastDom.showWrap = false} ,duration)
}
複製代碼
而後,再修改一下toast.vue的樣式
文件位置 /src/toast/toast.vue
<template>
<div class="wrap" v-if="showWrap" :class="showContent ?'fadein':'fadeout'">{{text}}</div>
</template>
<style scoped>
.wrap{
position: fixed;
left: 50%;
top:50%;
background: rgba(0,0,0,.35);
padding: 10px;
border-radius: 5px;
transform: translate(-50%,-50%);
color:#fff;
}
.fadein {
animation: animate_in 0.25s;
}
.fadeout {
animation: animate_out 0.25s;
opacity: 0;
}
@keyframes animate_in {
0% {
opacity: 0;
}
100%{
opacity: 1;
}
}
@keyframes animate_out {
0% {
opacity: 1;
}
100%{
opacity: 0;
}
}
</style>
複製代碼
大功告成,一個toast組件初步完成