天天看點

vue中@change為什麼要綁定一個回調函數_34 條我能告訴你的 Vue 之實操篇

這是我學習整理的關于

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

inject

的綁定對于原始類型來說并不是可響應的。這是刻意為之的。然而,如果你傳入了一個可監聽的對象,那麼其對象的 property 還是可響應的。這也就是為什麼在孫子元件中改變了

title

,但是父元件不會重新渲染的原因。

EventBus

以上三種方式都是隻能從父到子方向或者子到父方向進行元件的通信,而我就比較牛逼了😀,我還能進行兄弟元件之間的通信,甚至任意2個元件間通信。利用

Vue

執行個體實作一個

EventBus

進行資訊的釋出和訂閱,可以實作在任意2個元件之間通信。有兩種寫法都可以初始化一個

eventBus

對象:

  1. 通過導出一個

    Vue

    執行個體,然後再需要的地方引入:

    使用

    EventBus

    訂閱和釋出消息:
  2. 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

元件:

繼續閱讀