Vue中的$attrs和$listeners


Vue中的 $attrs 和 $listeners

最近在研究 Vue 的組件庫,之前也用過 $attrs 和 $listeners,官方文檔描述的不太詳細,也沒有太好的例子,就沒有深入的研究過這兩個屬性。最近生病在家,正好有時間好好研究一下 Vue 的高階用法,寫了幾個 demo,下面我們來看看這兩個屬性到底有什么奧秘。

$attrs

我們先來看看官方文檔的 api 描述是怎樣描述 $attrs 的

乍一看可能有點懵,下面我們結合下面的例子來看看 $attrs 的作用

普通的 props 傳值

先來看看下面的例子,我自己寫了一個雙向綁定的 input 的組件,來驗證一下。

<!-- 父組件 -->
<mxx-input v-model="user.username" type="text" foo="foo"></mxx-input>
<!-- 子組件 -->
<div>
  <input v-bind="$attrs" :type="type" :value="value">
</div>
// 子組件
export default {
  name: 'MxxInput',
  props: {
    type: {
      type: String,
      default: 'text'
    },
    value: {
      type: String,
    }
  },
}

我們來看看子組件渲染的 DOM 結構

我們會發現 foo 這個屬性加在了 MxxInput 組件的最外層。
如果你仔細看過 Vue 的官方文檔的話,你會發現我們在使用 props 的方式向子組件傳值的時候,子組件沒有使用 props 作為接受的話,那么這個屬性會自動設置在子組件的最外層的 HTML 標簽上。如果是 class 和 style 的話,會合並最外層標簽的 class 和 style。

$attrs 的作用

如果子組件中不想繼承父組件傳入的非 prop 屬性,可以使用 inheritAttrs 禁用繼承,然后通過 v-bind="$attrs" 把外部傳入的非 prop 屬性設置給希望的標簽上。
也就是你不想將沒有設置 props 的屬性自動繼承到組件最外層的標簽上那么你就需要將 inheritAttrs 這個屬性設置為 false,但是這不會改變 class 和 style。

// 子組件
export default {
  name: 'MxxInput',
  inheritAttrs: false,
  props: {
    type: {
      type: String,
      default: 'text'
    },
    value: {
      type: String,
    }
  },
}

我們再來看看新的 DOM 結構

我們可以看到最外層的 DOM 結構上沒有 foo 這個屬性了!
而 $attrs 的值就是 { "foo": "foo" },這樣我們就可以利用這個特性實現組件的屬性透傳,更多有趣的用法,你可以自己去摸索一下。

$listeners

普通 $emit 傳值

我們先來看看如果我們想從一個組件向組件外傳值,一種方法就是使用 $emit 向組件外暴露一個事件,然后通過事件方法的參數傳值。

<input
  type="text"
  v-bind="$attrs"
  @focus="$emit('focus', $event)"
  @input="$emit('input', $event)"
>

$listeners 的作用

其實 $attrs 的一個作用就是可以批量向組件內傳值,但是如果我們想批量向組件外傳值怎么辦呢,這個時候我們就可以使用 $listeners

<input
  type="text"
  v-bind="$attrs"
  v-on="$listeners"
>

$listeners 實際就相當於上面的多個 $emit 了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM