這是我學習整理的關于
Vue.js
系列文章的第一篇,另外還有兩篇分别是關于優化和原理的。希望讀完這3篇文章,你能對
Vue
有個更深入的認識。
7種元件通信方式随你選
元件通信是
Vue
的核心知識,掌握這幾個知識點,面試開發一點問題都沒有。
props/@on+$emit
用于實作父子元件間通信。通過
props
可以把父元件的消息傳遞給子元件:
這樣一來
this.title
就直接拿到從父元件中傳過來的
title
的值了。注意,你不應該在子元件内部直接改變
prop
,這裡就不多贅述,可以直接看官網介紹。
而通過
@on+$emit
組合可以實作子元件給父元件傳遞資訊:
和listeners
Vue_2.4
中新增的
$attrs/$listeners
可以進行跨級的元件通信。
$attrs
包含了父級作用域中不作為
prop
的屬性綁定(
class
和
style
除外),好像聽起來有些不好了解?沒事,看下代碼就知道是什麼意思了:
在上面的父元件
index.vue
中我們給子元件
list.vue
傳遞了4個參數,但是在子元件内部
props
裡隻定義了一個
list
,那麼此時
this.$attrs
的值是什麼呢?首先要去除
props
中已經綁定了的,然後再去除
class
和
style
,最後剩下
title
和
desc
結果和列印的是一緻的。基于上面代碼的基礎上,我們在給
list.vue
中加一個子元件:
在子元件中我們定義了一個
v-bind="$attrs"
可以把父級傳過來的參數,去除
props
、
class
和
style
之後剩下的繼續往下級傳遞,這樣就實作了跨級的元件通信。
$attrs
是可以進行跨級的參數傳遞,實作父到子的通信;同樣的,通過
$listeners
用類似的操作方式可以進行跨級的事件傳遞,實作子到父的通信。
$listeners
包含了父作用域中不含
.native
修飾的
v-on
事件監聽器,通過
v-on="$listeners"
傳遞到子元件内部。
provide/inject組合拳
provide/inject
組合以允許一個祖先元件向其所有子孫後代注入一個依賴,可以注入屬性和方法,進而實作跨級父子元件通信。在開發高階元件群組件庫的時候尤其好用。
❝和
provide
的綁定對于原始類型來說并不是可響應的。這是刻意為之的。然而,如果你傳入了一個可監聽的對象,那麼其對象的 property 還是可響應的。這也就是為什麼在孫子元件中改變了
inject
title
,但是父元件不會重新渲染的原因。
❞
EventBus
以上三種方式都是隻能從父到子方向或者子到父方向進行元件的通信,而我就比較牛逼了😀,我還能進行兄弟元件之間的通信,甚至任意2個元件間通信。利用
Vue
執行個體實作一個
EventBus
進行資訊的釋出和訂閱,可以實作在任意2個元件之間通信。有兩種寫法都可以初始化一個
eventBus
對象:
- 通過導出一個
Vue
執行個體,然後再需要的地方引入:
使用
訂閱和釋出消息:EventBus
- 在
main.js
中初始化一個全局的事件總線:
使用:
如果想要移除事件監聽,可以這樣來:
上面介紹了兩種寫法,推薦使用第二種全局定義的方式,可以避免在多處導入
EventBus
對象。這種元件通信方式隻要訂閱和釋出的順序得當,且事件名稱保持唯一性,理論上可以在任何 2 個元件之間進行通信,相當的強大。但是方法雖好,可不要濫用,建議隻用于簡單、少量業務的項目中,如果在一個大型繁雜的項目中無休止的使用該方法,将會導緻項目難以維護。
Vuex進行全局的資料管理
Vuex
是一個專門服務于
Vue.js
應用的狀态管理工具。适用于中大型應用。
Vuex
中有一些專有概念需要先了解下:
-
:用于資料的存儲,是State
中的唯一資料源;store
-
:類似于計算屬性,就是對Getter
中的資料進行二次的處理,比如篩選和對多個資料進行求值等;State
-
:類似事件,是改變Mutation
中資料的唯一途徑,隻能進行同步操作;Store
-
:類似Action
,通過送出Mutation
來改變資料,而不直接操作Mutation
,可以進行異步操作;State
-
:當業務複雜的時候,可以把Module
分成多個子產品,便于維護;store
對于這幾個概念有各種對應的
map
輔助函數用來簡化操作,比如
mapState
,如下三種寫法其實是一個意思,都是為了從
state
中擷取資料,并且通過計算屬性傳回給元件使用。
又比如
mapMutations
, 以下兩種函數的定義方式要實作的功能是一樣的,都是要送出一個
mutation
去改變
state
中的資料:
接下來就用一個極簡的例子來展示
Vuex
中任意2個元件間的狀态管理。1、 建立
store.js
2、 建立一個帶
store
的
Vue
執行個體
3、 任意元件
A
實作點選遞增
4、 任意元件
B
實作點選遞減
以上隻是用最簡單的
vuex
配置去實作元件通信,當然真實項目中的配置肯定會更複雜,比如需要對
State
資料進行二次篩選會用到
Getter
,然後如果需要異步的送出那麼需要使用
Action
,再比如如果子產品很多,可以将
store
分子產品進行狀态管理。對于
Vuex
更多複雜的操作還是建議去看Vuex 官方文檔,然後多寫例子。
Vue.observable實作mini vuex
這是一個
Vue2.6
中新增的
API
,用來讓一個對象可以響應。我們可以利用這個特點來實作一個小型的狀态管理器。
children/root
通過給子元件定義
ref
屬性可以使用
$refs
來直接操作子元件的方法和屬性。
比如子元件有一個
getList
方法,可以通過如下方式進行調用,實作父到子的通信:
除了
$refs
外,其他3個都是自
Vue
執行個體建立後就會自動包含的屬性,使用和上面的類似。
6類可以掌握的修飾符
表單修飾符
表單類的修飾符都是和
v-model
搭配使用的,比如:
v-model.lazy
、
v-model-trim
以及
v-model.number
等。
-
:對表單輸入的結果進行延遲響應,通常和.lazy
搭配使用。正常情況下在v-model
裡輸入内容會在input
标簽裡實時的展示出來,但是加上p
後則需要在輸入框失去焦點的時候才觸發響應。.lazy
-
:過濾輸入内容的首尾空格,這個和直接拿到字元串然後通過.trim
去除字元串首尾空格是一個意思。str.trim()
-
:如果輸入的第一個字元是數字,那就隻能輸入數字,否則他輸入的就是普通字元串。.number
事件修飾符
Vue
的事件修飾符是專門為
v-on
設計的,可以這樣使用:
@click.stop="handleClick"
,還能串聯使用:
@click.stop.prevent="handleClick"
。
-
:阻止事件冒泡,和原生.stop
是一樣的效果。如上代碼,當點選event.stopPropagation()
标簽的時候,p
上的點選事件也會觸發,加上div
後事件就不會往父級傳遞,那父級的事件就不會觸發了。.stop
-
:阻止預設事件,和原生的.prevent
是一樣的效果。比如一個帶有event.preventDefault()
的連結上添加了點選事件,那麼事件觸發的時候也會觸發連結的跳轉,但是加上href
後就不會觸發連結跳轉了。.prevent
-
:預設的事件流是:捕獲階段-目标階段-冒泡階段,即事件從最具體目标元素開始觸發,然後往上冒泡。而加上.capture
後則是反過來,外層元素先觸發事件,然後往深層傳遞。.capture
-
:隻觸發自身的事件,不會傳遞到父級,和.self
的作用有點類似。.stop
-
:隻會觸發一次該事件。.once
-
:當頁面滾動的時候就會一直觸發.passive
事件,這個其實是存在性能問題的,尤其是在移動端,當給他加上onScroll
後觸發的就不會那麼頻繁了。.passive
-
:現在在元件上使用.native
隻會監聽自定義事件 (元件用v-on
觸發的事件)。如果要監聽根元素的原生事件,可以使用$emit
修飾符,比如如下的.native
,如果不加el-input
當回車的時候就不會觸發.native
函數。search
❝
串聯使用事件修飾符的時候,需要注意其順序,同樣2個修飾符進行串聯使用,順序不同,結果大不一樣。
會阻止所有的點選事件,而
@click.prevent.self
@click.self.prevent
隻會阻止對自身元素的點選。
❞
滑鼠按鈕修飾符
-
:滑鼠左鍵點選;.left
-
:滑鼠右鍵點選;.right
-
:滑鼠中鍵點選;.middle
鍵盤按鍵修飾符
Vue
提供了一些常用的按鍵碼:
-
.enter
-
.tab
-
(捕獲“删除”和“倒退”鍵).delete
-
.esc
-
.space
-
.up
-
.down
-
.left
-
.right
另外,你也可以直接将
KeyboardEvent.key
暴露的任意有效按鍵名轉換為
kebab-case
來作為修飾符,比如可以通過如下的代碼來檢視具體按鍵的鍵名是什麼:
.exact修飾符
.exact
修飾符允許你控制由精确的系統修飾符組合觸發的事件。
.sync修飾符
.sync
修飾符常被用于子元件更新父元件資料。直接看下面的代碼:
子元件可以直接通過
update:title
的形式進行更新父元件中聲明了
.sync
的
prop
。上面父元件中的寫法其實是下面這種寫法的簡寫:
❝
注意帶有 .sync 修飾符的 v-bind 不能和表達式一起使用
❞
如果需要設定多個
prop
,比如:
可以通過
v-bind.sync
簡寫成這樣:
Vue
内部會自行進行解析把
person
對象裡的每個屬性都作為獨立的
prop
傳遞進去,各自添加用于更新的
v-on
監聽器。而從子元件進行更新的時候還是保持不變,比如:
6種方式編寫可複用子產品
今天需求評審了一個需求,需要實作一個詳情頁,這個詳情頁普通使用者和管理者都能進去,但是展示的資料有稍有不同,但絕大部分是一樣的;最主要的差別是詳情對于普通使用者是純展示,而對于管理者要求能夠編輯,然後管理者還有一些别的按鈕權限等。需求看到這裡,如果在排期的時候把使用者的詳情分給開發A做,而把管理者的詳情分給B去做,那這樣做的結果就是開發A寫了一個詳情頁,開發B寫了一個詳情頁,這在開發階段、提測後的修改
bug
階段以及後期疊代階段,都需要同時維護這 2 個檔案,浪費了時間浪費了人力,是以你可以從中意識到編寫可複用子產品的重要性。
而
Vue
作者尤大為了讓開發者更好的編寫可複用子產品,提供了很多的手段,比如:元件、自定義指令、渲染函數、插件以及過濾器等。
元件
元件是
Vue
中最精髓的地方,也是我們平時編寫可複用子產品最常用的手段,但是由于這塊内容篇幅很多,是以不在這裡展開,後續會寫相關的内容進行詳述。
使用混入mixins
什麼是混入呢?從代碼結構上來看,混入其實就是半個元件,一個
Vue
元件可以包括
template
、
script
和
style
三部分,而混入其實就是
script
裡面的内容。一個混入對象包含任意元件選項,比如
data
、
methods
、
computed
、
watch
、生命周期鈎子函數、甚至是
mixins
自己等,混入被設計出來就是旨在提高代碼的靈活性、可複用性。
什麼時候應該使用混入呢?當可複用邏輯隻是
JS
代碼層面的,而無
template
的時候就可以考慮用混入了。比如需要記錄使用者在頁面的停留的時間,那我們就可以把這段邏輯抽出來放在
mixins
裡:
然後在需要統計頁面停留時間的地方加上:
使用混入的時候要注意群組件選項的合并規則,可以分為如下三類:
-
将進行遞歸合并,對于鍵名沖突的以元件資料為準:data
- 對于生命周期鈎子函數将會合并成一個數組,混入對象的鈎子将先被執行:
- 值為對象的選項,例如
、methods
和components
,将被合并為同一個對象。兩個對象鍵名沖突時,取元件對象的鍵值對。directives
自定義指令
除了
Vue
内置的一些指令比如
v-model
、
v-if
等,
Vue
還允許我們自定義指令。在
Vue2.0
中,代碼複用和抽象的主要形式是元件。然而,有的情況下,你仍然需要對普通
DOM
元素進行底層操作,這時候就會用到自定義指令。比如我們可以通過自定義一個指令來控制按鈕的權限。我們期望設計一個如下形式的指令來控制按鈕權限:
通過在按鈕的指令裡傳入一組權限,如果該按鈕隻有
admin
權限才可以送出,而我們傳入一個别的權限,比如
user
,那這個按鈕就不應該顯示了。接下來我們去注冊一個全局的指令:
然後我們需要在
main.js
裡通過安裝插件的方式來啟用這個指令:
使用渲染函數
這裡将使用渲染函數實作上面介紹過的的權限按鈕。使用方式如下,把需要控制權限的按鈕包在權限元件
authority
裡面,如果有該權限就顯示,沒有就不顯示。
然後我們用渲染函數去實作一個
authority
元件: