Vue 組件傳參的八種方式總結

Vue 組件的使用無論是在日常工做仍是在面試面試中,都是頻繁出現的。所以系統的梳理一下組件之間的傳參仍是很是有必要的html

1、props 傳參

子組件定義 props 有三種方式:

// 第一種數組方式
props: [xxx, xxx, xxx]
// 第二種對象方式
props: { xxx: Number, xxx: String}
// 第三種對象嵌套對象方式
props: {
    xxx: {
        //類型不匹配會警告
        type: Number,
        default: 0,
        required: true,
        // 返回值不是 true,會警告
        validator(val) { return val === 10}
    }
}
複製代碼

第三種對象默認支持 4 種屬性,而且都是非必填的。能夠隨意使用面試

父組件傳參的倆種方式

第一種靜態屬性傳參數組

注意:bash

  1. 在不定義 props 類型的狀況下 props 接受到的均爲 String。
  2. 當 props 屬性指定爲 Boolean 時,而且只有屬性 key 沒有值 value 時接受到的是 true
<!--props 接受到的均爲 String -->
<children xxx="123"></children>

<!-- 有隻有屬性沒有值, 這種狀況 props 指定類型是 Boolean 則接收到的是 true -->
<children xxx></children>
複製代碼

第二種動態屬性傳參閉包

注意:ui

  1. 須要區分非簡寫形式傳入的值是對象,則會對應 props 中多個值
  2. 會保留傳入值的類型
  3. 若是是表達式則獲取到的是表達式的計算結果
<!-- prop 接收到 Number 類型的 123-->
<children :xxx="123"></children>

<!-- prop 接收到 Array 類型的 [1, 2, 3]-->
<children v-bind:xxx="[1, 2, 3]"></children>

<!-- prop 會接收到 xxx1 和 xxx2 倆個參數。這種不支持簡寫形式-->
<children v-bind="{xxx1: 1, xxx2: 2}"></children>
複製代碼

2、attrs 和listeners

$attrsthis

$attrs 會獲取到 props 中未定義的屬性(class 和 style 屬性除外),支持響應式。經常使用的場景有倆種:spa

  1. 組件嵌套組件時可使用 $attrs 來支持過多的屬性支持。好比 elementUI 的 table 組件。支持的屬性十幾個,而日常封裝的時候用的最多的也就一倆個。
  2. 屬性默認是添加在父組件上的,有時候想把多餘的屬性添加在子組件上(能夠結合 inheritAttrs: false 屬性,讓父屬性不接受多餘的屬性)

$listeners 定義的事件都在子組件的根元素上,有時候想加到其餘元素上。就可使用 $listerners。它包含了父組件中的事件監聽器(除了帶有 .native 修飾符的監聽器)code

3、$emit 通知

Vue 默認有 $on $emit $once $off 幾種方法來實現發佈訂閱模式,這也應用在了組件傳參上。在組件上添加的特殊方法 @abc="methods" 就至關於使用了 $on 來監聽這個方法。所以組件內可使用 $emit 來進行通知。htm

這裏有一道考題: for 循環的時候如何拿到子組件的傳值和 for 中循環的值

答案有倆種,一是 $event, 二是 閉包。只是須要注意 $event 只能獲取到第一個值

<template v-for="item in [1, 2, 3]">
    <children @abc="((val, val2) => getValue(val, item))"></children>
</template>
複製代碼

4、v-model

這個實際上是一種經過 emit,on 的組合方式。優勢再於同步值方便,寫法優雅。下面三種寫法實際上是一個意思

// 寫法 1
<children v-model="a"></children>
{
    model: {
        prop: 'value',
        event: 'update:a',
    },
    methods: {
        a() { this.$emit('update:a', 1)}
    }
}

// 寫法 2
<children :a="a" @update:a="a = $event"></children>
{
    props: ['a']
    methods: {
        a() { this.$emit('update:a', 1)}
    }
}
// 寫法 3 
// 1. 事件名必須是 update: + 屬性名
// 2. 參數不能是表達式,最好是 data 裏面的屬性
<children :a.sync="a"></children>
{
    props: ['a']
    methods: {
        a() { this.$emit('update:a', 1)}
    }
}
複製代碼

5、插槽

<template>
    <div>
        <!--默認插槽-->
        <slot></slot>
        <!--另外一種默認插槽的寫法-->
        <slot name="default"></slot>
        <!--具名插槽-->
        <slot name="footer"></slot>
        <!--傳參插槽-->
        <slot v-bind:user="user" name="header"></slot>
    </div>
</template>

<!--使用-->
<children>
    <!--跑到默認插槽中去-->
    <div>123</div>
    <!--另外一種默認插槽的寫法-->
    <template v-slot:default></template>
    <!--跑到具名插槽 footer 中去-->
    <template v-slot:footer></template>
    <!--縮寫形式-->
    <template #footer></template>
    <!--獲取子組件的值-->
    <template v-slot:header="slot">{{slot.user}}</template>
    <!--結構插槽值-->
    <template v-slot:header="{user: person}">{{person}}</template>
    <!--老式寫法,能夠寫到具體的標籤上面-->
    <template slot="footer" slot-scope="scope"></template>
</children>
複製代碼

6、$refs, $root, $parent, $children

  1. $root 獲取根組件
  2. $parent 獲取父組件
  3. $children 獲取子組件(全部的子組件,不保證順序)
  4. $refs 組件獲取組件實例,元素獲取元素

7、project / inject

注意:注入的值是非響應的

<!--父組件 提供-->
{
    project() {
        return {
            parent: this
        }
    }
}
<!--子組件 注入-->
{
    // 寫法一
    inject: ['parent']
    // 寫法二
    inject: { parent: 'parent' }
    // 寫法三
    inject: {
        parent: {
            from: 'parent',
            default: 222
        }
    }
}
複製代碼

8、Vuex

這個至關於單獨維護的一組數據,就不過多的說了。

相關文章
相關標籤/搜索