vue 聽說你很會傳值?

大小 vue 項目都離不開組件通訊, 在這裡總結一下vue組件通訊方式並列出, 都是

簡單的例子. 適合像我這樣的小白。如有錯誤,歡迎指正。

溫馨提示: 下文沒有列出 vuex, vuex 也是重要的組件通訊方式。

props

  • 最常用的組件通訊方式
  • 值可以是數組或對象,使用對象時可以配置高級選項,如類型檢測、自定義驗證和設置默認值
  • 方向:父 -> 子

Son.vue

<code>

copyexport

default

{

props

: {

text

: {

type

: String,

required

: true, }, },

mounted

() {

console

.log

(this.text) /<code>

App.vue

<code>copy

<

template

>

<

Son

text

=

'我是父組件提供給子組件的值'

/>

template

>

<

script

>

import

Son

from

'./components/dispatch/Son'

export

default

{

name

:

'app'

,

components

: { Son, }},

script

>

/<code>

$refs

  • 常用的方式
  • 返回註冊過 ref 特性的所有 DOM 元素和組件實例
  • 可以用來操作 DOM
  • 可以用來傳值
  • 方向:子 -> 父

Son.vue

<code>

copyexport

default

{

methods

: {

sonFunc

() { console.

log

(

'我是子組件的值'

) }, },}/<code>

App.vue

<code>copy

<

template

>

<

Son

ref

=

"sonref"

/>

template

>

<

script

>

import

Son

from

'./components/dispatch/Son'

export

default

{

name

:

'app'

,

components

: { Son, }, mounted() {

this

.$refs.sonref.sonFunc() },}

script

>

/<code>

控制檯打印: 我是子組件的值

$emit

  • $emit 用來觸發當前實例上的事件
  • 方向:父 -> 子
  • 參數一:來觸發的當前實例上的事件函數
  • 參數二:附加參數,傳給監聽器回調

Son.vue

<code>copyexport 

default

{ mounted() {

this

.$emit(

'customFunc'

,

'我是子組件傳給父組件的值'

) },}/<code>

App.vue

<code>copy

<

template

>

<

Son

v-on:customFunc

=

"fatherFunc"

/>

template

>

<

script

>

import

Son

from

'./components/dispatch/Son'

export

default

{

name

:

'app'

,

components

: { Son, },

methods

: { fatherFunc(value) {

console

.log(value)

script

>

/<code>

@update

  • 需要配合 .sync 使用
  • 與上面的 $emit 寫法類似
  • 不同之處在於$emit 的第一個參數不在是當前實例上的事件函數
  • 方向:子 -> 父

Son.vue

<code>copyexport  

default

{ mounted() {

this

.$emit(

"update:text"

,

'我是子組件傳給父組件的值'

) }}/<code>

App.vue

<code>copy

<

template

>

<

Son

:text.sync

=

'text'

/>

template

>

<

script

>

import

Son

from

"./components/dispatch/Son"

export

default

{ data() {

return

{

text

:

''

} }, mounted() {

console

.log(

this

.text);

script

>

/<code>

接下來看下面的寫法,上面這種寫法是對如下方式的簡寫, 或者稱之為語法糖。可以不借助 .sync。

Son.vue

<code>copyexport 

default

{ mounted () {

this

.$emit(

'update:text'

,

'我是子組件傳給父組件的值'

) }}/<code>

App.vue

<code>copy /<code>

v-model

  • v-model 常用來給 input 實現雙向數據綁定
  • v-model 也可以用來傳值
  • 有侷限性,只能傳 input value
<code>

copy

"text"> /<code>

等價於:

<code>copyvalue=

"text"

v-

on

:input=

"text = $event.target.value"

>/<code>

接下來看如何通過 v-model 傳值。

Son.vue

<code>copy

<

template

>

<

input

v-bind:value

=

"value"

v-on:input

=

"$emit('input', $event.target.text)"

/>

template

>

<

script

>

export

default

{ data() {

return

{

value

:

'我是子組件傳給父組件的值'

, } }}

script

>

/<code>

App.vue

<code>copy

<

template

>

<

Son

v-model

=

"text"

/>

template

>

<

script

>

import

Son

from

'./components/dispatch/Son'

export

default

{

name

:

'app'

,

components

: { Son, }}

script

>

/<code>
vue 聽說你很會傳值?

$parent $childred

  • $parent: 父實例,如果當前實例有的話
  • $children: 當前實例的直接子組件
  • $parent $childred 通過封裝可以實現不同方向的傳值

$children 並不保證順序,也不是響應式的。可以使用一個數組配合 v-for 來生成子組件,使用 Array 作為真正的來源。

App.vue

<code>copyexport 

default

{

data

() {

return

{ value:

'我是父組件的值'

, } },/<code>

Son.vue

<code>

copyexport

default

{

mounted

: { console.

log

(this.$parent.value) // 我是父組件的值 this.$parent.value =

666

console.

log

(this.$parent.value) //

666

},}/<code>

簡單封裝一下即可實現$parent 配合 $emit 實現跨級向上傳值。

main.js

<code>copyVue.prototype.$dispatch = 

function

(event, value)

{ let

parent

= this.$parent

while

(

parent

) {

parent

.$emit(event, value)

parent

=

parent

.$parent }}/<code>

這樣使用: this.$dispatch('event',value)

簡單封裝一下即可實現$children 配合 $emit 實現向下傳值。

<code>copyVue.prototype.$broadcast = 

function

(event, value)

{

const

broadcast = children => { children.

forEach

(child => { child.$emit(event, value)

if

(child.$children) { broadcast(child.$children) } }) } broadcast(this.$children)}/<code>

這樣使用: this.$broadcast('event',value)

$attrs

  • 獲取父組件通過 v-bind 傳過去的所有值
  • class 和 style 除外
  • 可以通過 v-bind="$attrs" 傳入內部組件
  • 只能在 中使用
  • 方向:子 -> 父

App.vue

<code>copy  

<

Son

:value1

=

"123"

:value2

=

"456"

/>

template

>

import

Son

from

'./components/dispatch/Son'

export

default

{

name

:

'app'

,

components

: { Son, },}/<code>

Son.vue

<code>copy

<

template

>

<

div

>

{{$attrs}}

div

>

template

>

<

script

>

export

default

{

inheritAttrs

:

false

,}

script

>

/<code>
vue 聽說你很會傳值?

$listener

  • 獲取父作用域中的 () v-on 事件監聽器。
  • 不含 .native 修飾器修飾的時間監聽器。
  • 可以通過 v-on="$listeners" 傳入內部組件(孫子組件)。
  • 方向:父 -> 子

App.vue

<code>copy

<

template

>

<

Son

@

customFunc

=

"fatherFunc"

/>

template

>

<

script

>

import

Son

from

'./components/dispatch/Son'

export

default

{

name

:

'app'

,

components

: { Son, },

methods

: { fatherFunc() {

console

.log(

'666'

) }, },}

script

>

/<code>

Son.vue

<code>copy

<

template

>

<

button

@

click

=

"$listeners.customFunc()"

>

button

>

template

>

/<code>

provide inject

  • provide 和 inject 不推薦直接用於應用程序代碼中
  • 與 React 的上下文特性很相似。這對選項需要一起使用,以允許一個祖先組件向其所有子孫後代注入一個依賴,不論組件層次有多深,並在起上下游關係成立的時間裡始終生效
  • provide 選項應該是一個對象或返回一個對象的函數。該對象包含可注入其子孫的屬性。在該對象中你可以使用 ES2015 Symbols 作為 key,但是隻在原生支持 Symbol 和 Reflect.ownKeys 的環境下可工作
  • provide 和 inject 綁定並不是可響應的。這是 vue 刻意為之
  • 如果你傳入了一個可監聽的對象,那麼其對象的屬性還是可響應的

這裡有一個簡單的示例:

App.vue

<code>copy

<

template

>

<

Son

/>

template

>

<

script

>

import

Son

from

'./components/dispatch/Son'

export

default

{

name

:

'app'

,

components

: { Son, }, provide() {

return

{

text

:

'我是父組件的值'

, } },}

script

>

/<code>

Son.vue

<code>

copyexport

default

{

inject

: [

'text'

],

mounted

() { console.

log

(this.text) // 我是父組件的值 },}/<code>

事件總線

  • EventBus 又稱為事件總線
  • 不是一個具體的 API,EventBus 代表一種思路
  • 可以看作 vuex 的究極壓縮版

App.vue

<code>copy

<

template

>

<

div

>

<

Son

/>

div

>

template

>

<

script

>

import

Son

from

'./components/dispatch/Son'

export

default

{

name

:

'app'

,

components

: { Son, }, mounted() {

this

.$EventBus.$emit(

'event'

,

'app.vue'

) },}

script

>

/<code>

Son.vue

<code>copyexport 

default

{ mounted() {

this

.$EventBus.$on(

'event'

,

function

(

v

)

{

console

.log(v) }) },}/<code>

Observable

  • observable 可以讓一個對象可響應
  • vue 內部會用它來處理 data 函數返回的對象
  • 返回的對象可以直接用於渲染函數和計算屬性內,並且會在發生改變時觸發相應的更新
  • 可以作為最小化的跨組件狀態存儲器,用於簡單的場景

store.js

<code>copyimport Vue 

from

'vue'

export

const

store = Vue.observable({

text

:

'我是store裡的'

})

export

const

mutations = { setText(text) { store.text = text },}/<code>

App.vue

<code>copyimport { store, mutations } 

from

'../store'

export

default

{ mounted() {

console

.log(store.text)

//

我是store裡的 mutations.setText(

'我在App.vue中將你改變'

)

console

.log(store.text)

//

我在App.vue將你改變 },}/<code>

composition-api

  • composition-api 包含 vue3 的新特性
  • provide 和 inject 可以實現嵌套組件之間的數據傳遞
  • 這兩個函數只能在 setup 函數中使用
  • 父級組件中使用 provide 函數向下傳遞數據
  • 子級組件中使用 inject 獲取上層傳遞過來的數據
  • 不限層級。

App.vue

<code>copy

<

template

>

<

provideAndInject

/>

template

>

<

script

>

import

{ provide }

from

"@vue/composition-api"

import

provideAndInject

from

"./components/provideAndInject"

export

default

{

name

:

"app"

,

components

: { provideAndInject }, setup() {

script

>

/<code>

Son.vue

<code>copy

<

template

>

<

h3

>

{{ customVal }}

h3

>

template

>

<

script

>

import

{ inject }

from

"@vue/composition-api"

;

export

default

{ setup() {

script

>

/<code>

父組件可以通過 ref

創建響應式數據通過 provide 共享給子組件。


分享到:


相關文章: