高級 Vue 組件模式 (5)

05 使用 $refs 訪問子組件引用

目標

在以前的文章中,詳細闡述了子組件獲取父組件所提供屬性及方法的一些解決方案,若是咱們想在父組件之中訪問子組件的一些方法和屬性怎麼辦呢?設想如下一個場景:vue

  • 當前的 custom-button 組件中,有一個 input 元素
  • 咱們指望當 toggle 的開關狀態爲時,顯示 input 元素並自動得到焦點

這裏要想完成目標,須要獲取某個組件或者每一個元素的引用,在不一樣的 mvvm 框架中,都提供了相關特性來完成這一點:react

  • angularjs: 可使用依賴注入的 $element 服務
  • Angular: 可使用 ViewChild、ContentChild 或者 template ref 來獲取引用
  • react: 使用 ref 屬性聲明獲取引用的邏輯

在 vue 中,獲取引用的方法與 react 相似,經過聲明 ref 屬性來完成。jquery

實現

首先,在 custom-button 組件中增長一個 input 元素,以下:git

<input v-if="on" ref="input" type="text" placeholder="addtional messages">

注意這裏的 ref="input",這樣在組件內部,能夠經過 this.$refs.input 得到該元素的引用,爲了實現目標中說起的需求,再添加一個新的方法 focus 來使 input 元素獲取焦點,以下:angularjs

focus() {
  this.$nextTick(function() {
    this.$refs.input.focus();
  });
},

注意這裏的 this.$nextTick,正常狀況下,直接調用 input 的 focus 方法是沒有問題的,然而卻不行。由於 input 的渲染邏輯取決於 prop 屬性 on 的狀態,若是直接調用 focus 方法,這時 input 元素的渲染工做極可能還未結束,這時 this.$refs.input 所指向的引用值爲 undefined,繼續調用方法則會拋出異常,所以咱們利用 this.$nextTick 方法,將調用的邏輯延遲至下次 DOM 更新循環以後執行。github

同理,在 app 組件中,爲 custom-button 添加一個 ref 屬性,以下:api

<custom-button ref="customButton" :on="status.on" :toggle="toggle"></custom-button>

以後修改 onToggle 方法中的邏輯以知足目標中的需求,當 toggle 組件狀態爲開時,調用 custom-button 組件的 focus 方法,以下:app

onToggle(on) {
  if (on) this.$refs.customButton.focus();
  console.log("toggle", on);
}

成果

點擊按鈕會發現,每當開關爲開時,input 元素都會顯示,並會自動得到焦點。框架

你能夠下面的連接來看看這個組件的實現代碼以及演示:mvvm

總結

當指望得到子元素或者子組件的引用時,切記使用 ref 和 $refs 來解決問題。文章中所舉例子的交互,在實際場景中很常見,好比:

  • 當經過一個 icon 觸發搜索框時,指望自動得到焦點
  • 當表單校驗失敗時,指望自動得到發生錯誤的表單項的焦點
  • 當複雜列表的篩選器展開時,指望第一個篩選單元得到焦點

這幾種狀況下,均可以使用該模式來高效地解決問題,而不是經過使用 DOM 中的 api 或者引入 jquery 獲取相關元素再進行操做。

目錄

github gist

歡迎關注公衆號 全棧101,只談技術,不談人生

clipboard.png

相關文章
相關標籤/搜索