你不知道的Vue技巧之--開發(fā)一個可以通過方法調(diào)用的組件(推薦)
Vue作為最近最炙手可熱的前端框架,其簡單的入門方式和功能強(qiáng)大的API是其優(yōu)點。而同時因為其API的多樣性和豐富性,所以他的很多開發(fā)方式就和一切基于組件的React不同,如果沒有對Vue的API(有一些甚至文檔都沒提到)有一個全面的了解,那么在開發(fā)和設(shè)計一個組件的時候有可能就會繞一個大圈子,所以我非常推薦各位在學(xué)習(xí)Vue的時候先要對Vue核心的所有API都有一個了解。
舉個例子,通知組件notification基本是現(xiàn)代web開發(fā)標(biāo)配,在很多地方都能用到。而在以Vue作為核心框架的前端項目中,因為Vue本身是一個組件化和虛擬Dom的框架,要實現(xiàn)一個通知組件的展示當(dāng)然是非常簡單的。但因為通知組件的使用特性,直接在模板當(dāng)中書寫組件并通過v-show或者props控制通知組件的顯示顯然是非常不方便的,而且如果要在action或者其他非組件場景中要用到通知,那么純組件模式的用法也無法實現(xiàn)。那么有沒有辦法即用到Vue組件化特性方便得實現(xiàn)一個通知組件的展現(xiàn),又能夠通過一個簡單的方法調(diào)用就能顯示通知呢?本文就是來講述這個實現(xiàn)方法的。
目標(biāo)
實現(xiàn)一個Vue的通知組件,可以直接在組件內(nèi)調(diào)用
通過方法調(diào)用,比如Vue.$notify({...options})來調(diào)用通知組件
結(jié)合上述兩種方式,復(fù)用代碼
實現(xiàn)通知組件
這一步非常的簡單,我相信做過一點Vue開發(fā)的同學(xué)都能寫出一個像模像樣的通知組件,在這里就不贅述,直接上代碼
<template>
<transition name="fade" @after-leave="afterLeave" @after-enter="setHeight">
<div
v-show="visible"
:class="['notification']"
:style="style"
@mouseenter="clearTimer"
@mouseleave="createTimer"
>
<span class="content">{{content}}</span>
<a class="btn" @click="handleClose">{{btn || '關(guān)閉'}}</a>
</div>
</transition>
</template>
<script>
export default {
name: 'Notification',
props: {
content: {
type: String,
default: ''
},
btn: {
type: String,
default: ''
}
},
data () {
return {
visible: true
}
},
computed: {
style () {
return {}
}
},
methods: {
handleClose (e) {
e.preventDefault()
this.doClose()
},
doClose () {
this.visible = false
this.$emit('close')
},
afterLeave () {
this.$emit('closed')
},
clearTimer () {},
createTimer () {},
setHeight () {}
}
}
</script>
<style lang="stylus" scoped> .notification display: flex background-color #303030 color rgba(255, 255, 255, 1) align-items center padding 20px position fixed min-width 280px box-shadow 0px 3px 5px -1px rgba(0, 0, 0, 0.2), 0px 6px 10px 0px rgba(0, 0, 0, 0.14), 0px 1px 18px 0px rgba(0, 0, 0, 0.12) flex-wrap wrap transition all .3s .content padding 0 .btn color #ff4081 padding-left 24px margin-left auto cursor pointer </style>
在這里需要注意,我們定義了一個叫做style的computed屬性,三個方法clearTimer,createTimer,setHeight,但他們的內(nèi)容都是空的,雖然在模板上有用到,但是似乎沒什么意義,在后面我們要擴(kuò)展組件的時候我會講到為什么要這么做。
創(chuàng)建完這個組件之后,我們就可以在模板中使用了<notification btn="xxx" content="xxx" />
實現(xiàn)通過方法調(diào)用該通知組件
繼承組件
在實現(xiàn)通過方法調(diào)用之前,我們需要擴(kuò)展一下這個組件,因為僅僅這些屬性,并不夠我們使用。在使用方法調(diào)用的時候,我們需要考慮一下幾個問題:
- 顯示通知的定位
- 組件的出現(xiàn)和自動消失控制
- 連續(xù)多次調(diào)用通知方法,如何排版多個通知
在這個前提下,我們需要擴(kuò)展該組件,但是擴(kuò)展的這些屬性不能直接放在原組件內(nèi),因為這些可能會影響組件在模板內(nèi)的使用,那怎么辦呢?這時候我們就要用到Vue里面非常好用的一個API,extend,通過他去繼承原組件的屬性并擴(kuò)展他。
我們先來看代碼,創(chuàng)建一個叫做fun-notification.js的文件,內(nèi)容如下:
import Notification from './notification.vue'
export default {
extends: Notification,
computed: {
style () {
return {
position: 'fixed',
right: '20px',
bottom: `${this.verticalOffset + 20}px`
}
}
},
data () {
return {
verticalOffset: 0,
visible: false,
height: 0,
autoClose: 3000
}
},
mounted () {
this.createTimer()
},
methods: {
createTimer () {
if (this.autoClose) {
this.timer = setTimeout(() => {
this.doClose()
}, this.autoClose)
}
},
clearTimer () {
if (this.timer) {
clearTimeout(this.timer)
}
},
setHeight () {
this.height = this.$el.offsetHeight
}
}
}
我們可以看到之前空實現(xiàn)的幾個方法在這里被實現(xiàn)了,那么為什么要在原組件上面加上那些方法的定義呢?因為需要在模板上綁定,而模板是無法extend的,只能覆蓋,如果要覆蓋重新實現(xiàn),那擴(kuò)展的意義就不是很大了。當(dāng)然同學(xué)們可以自己抉擇。
在使用extend的時候注意以下兩個點:
- 方法和屬性的定義是直接覆蓋的
- 生命周期方法類似余mixin,會合并,也就是原組件和繼承之后的組件都會被調(diào)用,原組件先調(diào)用
通過方法調(diào)用該組件
最后我們需要做的就是通過方法調(diào)用這個已經(jīng)繼承過的組件了,我們先來看一下源碼的實現(xiàn):
// function-component.js
import Vue from 'vue'
import Component from './fun-component'
const NotificationConstructor = Vue.extend(Component)
const instances = []
let seed = 1
const removeInstance = (instance) => {
const len = instances.length
if (!instance) return
const index = instances.findIndex(inst => instance.id === inst.id)
instances.splice(index, 1)
if (len <= 1) return
const removedHeight = instance.vm.height
for (let i = index; i < len - 1; i++) {
instances[i].verticalOffset =
parseInt(instances[i].verticalOffset) - removedHeight - 16
}
}
const notify = function (options) {
const {
onClose,
...rest
} = options
if (Vue.prototype.$isServer) return
options = options || {}
const id = `notification_${seed++}`
const instance = new NotificationConstructor({
propsData: {
...rest
}
})
instance.id = id
instance.vm = instance.$mount()
document.body.appendChild(instance.vm.$el)
instance.vm.visible = true
let verticalOffset = 0
instances.forEach(item => {
verticalOffset += item.$el.offsetHeight + 16
})
verticalOffset += 16
instance.verticalOffset = verticalOffset
instances.push(instance)
instance.vm.$on('closed', () => {
if (typeof onClose === 'function') {
onClose(instance)
}
removeInstance(instance)
instance.vm.$destroy()
})
return instance.vm
}
export default notify
首先通過const NotificationConstructor = Vue.extend(Component),我們得到了一個類似于Vue的子類,我們就可以通過new NotificationConstructor({...options})的方式去創(chuàng)建Vue的實例了,同時通過該方式創(chuàng)建的實例,是有組件定義里面的所有屬性的。
在創(chuàng)建實例之后,可以通過instance.$mount()手動將組件掛載到DOM上面,這樣我們可以不依賴Vue組件樹來輸出DOM片段,達(dá)到自由顯示通知的效果。
這中間的實現(xiàn)主要就是維護(hù)一個通知數(shù)組,在創(chuàng)建時推入,在消失時刪除,這個過程并沒有規(guī)定一定要如此實現(xiàn),我就不贅述,以免限制大家的思路,大家可以根據(jù)自己的想法去實現(xiàn)。
使用該方法
要使用這個通知方法非常簡單,我們可以直接import這個文件來使用,比如:
import notify from './function-component.js'
notify({
content: 'xxx',
btn: 'xxx'
})
當(dāng)然我們很多場景是在組件內(nèi)部調(diào)用,為了方便在組件內(nèi)使用,不需要每次都import,我們可以把這個方法包裝成一個Vue的插件。我們創(chuàng)建一個index.js,內(nèi)容如下:
import Notification from './notification.vue'
import notify from './function'
export default (Vue) => {
Vue.component(Notification.name, Notification)
Vue.prototype.$notify = notify
Vue.notify = notify
}
然后在項目內(nèi),我們可以通過:
import notify from '/path/to/notification/module' Vue.use(notify)
這樣之后,在組件內(nèi)就可以直接通過this.$notify({...options})來調(diào)用通知了,同時還可以通過Vue.notify({...options})在其他環(huán)境下調(diào)用,大家可以在自己的項目中嘗試一下。
總結(jié)
到這里,關(guān)于如何實現(xiàn)通過方法調(diào)用一個Vue組件內(nèi)容就差不多了。在這里我們涉及到的Vue技術(shù)點有如下幾點:
- 通過extend配置進(jìn)行組件的擴(kuò)展
- 通過Vue.extend創(chuàng)建一個Vue的子類,用來動態(tài)創(chuàng)建Vue實例
- 通過Vue實例主動將組件內(nèi)容掛載到DOM
Vue擁有非常多的API,如果在使用Vue之前沒有系統(tǒng)的學(xué)習(xí)過Vue的核心知識和API,你可能壓根就不知道有這樣的實現(xiàn)方式,所以想要學(xué)好Vue,系統(tǒng)得對Vue的核心進(jìn)行學(xué)習(xí)是非常重要的一個環(huán)節(jié)。
以上所述是小編給大家介紹的你不知道的Vue技巧之--開發(fā)一個可以通過方法調(diào)用的組件詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
Vue2中無法監(jiān)聽數(shù)組和對象的某些變化問題
這篇文章主要介紹了Vue2中無法監(jiān)聽數(shù)組和對象的某些變化問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-08-08
基于Vue和ECharts實現(xiàn)定時更新與倒計時功能的實戰(zhàn)分享
在前端開發(fā)中,動態(tài)數(shù)據(jù)展示和用戶交互是構(gòu)建現(xiàn)代 Web 應(yīng)用的核心需求之一,在本篇博客中,我們將通過一個簡單的案例,展示如何在 Vue 中結(jié)合 ECharts 實現(xiàn)一個定時更新和倒計時功能,用于實時監(jiān)控和數(shù)據(jù)可視化,需要的朋友可以參考下2025-01-01
vue通過子組件修改父組件prop的多種實現(xiàn)方式
這篇文章主要介紹了vue通過子組件修改父組件prop的幾種實現(xiàn)方式,比較常用的方式是通過Prop單向傳遞的規(guī)則,需要的朋友可以參考下2021-09-09
Vue2.0用 watch 觀察 prop 變化(不觸發(fā))
本篇文章主要介紹了Vue2.0用 watch 觀察 prop 變化(不觸發(fā)),非常具有實用價值,需要的朋友可以參考下2017-09-09
vue中v-for和v-if不能在同一個標(biāo)簽使用的最新解決方案
這篇文章主要介紹了vue中v-for和v-if不能在同一個標(biāo)簽的最新解決方案,這里描述了兩種解決方案,結(jié)合實例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2023-07-07

