前端 | 自定義組件 v-model:Vue 如何實現雙向綁定


v-model 是 Vue 中一個常用的指令,常用於表單中的數據綁定。如下基本用法想必大家都很熟悉,data 中的 checked 屬性的值就會隨着多選框的狀態實時變化。

<el-checkbox v-model="checked" />

但你或許聽說過,Vue 組件之間是“單向數據流”,即通過 props 從父組件向子組件單向傳遞數據。那么,v-model 的“雙向綁定”效果是如何實現的呢?

自定義組件實現 v-model

首先來看一個實際應用的例子,需求如下:在創建試卷頁面 paperCreate 中,通過選擇題目組件 questionSelect 查詢並選擇題目組成試卷,效果如下圖所示。

選擇試題

為了方便使用,希望能在選擇題目組件上使用 v-model 指令進行雙向綁定:

<!-- 選擇題目組件 -->
<question-select v-model="formData.questions" />

<!-- 顯示已選擇題目 -->
<div v-for="item in formData.questions" :key="item.id" >
    <question :question="item" />
</div>

value 屬性和 input 事件

自定義支持 v-model 的組件只需要滿足兩個條件:

  • value 屬性作為傳入數據
  • 數據改變時,將新數據作為 payload,向上 emit 一個 input 事件

就是這么簡單,相關代碼為:

export default {
  props: {
    value: Array,	// 類型根據實際需要
  },
  methods: {
    handelChange() {
      this.$emit("input", newValue);
    },
  },
};

如果不想使用默認的 value 屬性和 input 事件,也可以通過 model 對象自定義相應屬性和事件:

model: {
  prop: 'checked',
  event: 'change',
},

單向數據流

需要注意的是,prop 傳值是單向的,即父組件中的數據改變會反映到子組件中,但在子組件內部不能主動改變 prop 的值。具體來說就是,子組件中不能使用類似於 v-model="value" 之類試圖改變 value 值的操作。

因此表格中的 checkbox,也只單向傳入 value 來控制是否選中的狀態,然后在選中狀態改變時手動處理改變后的結果。

  • 對於表格中的一行(即一道題目),如果傳入的 value 數組(即已選中的題目列表)中包含它的 id,則顯示為選中狀態
  • 不能直接改變原數組 value,直接構造新列表傳出:
    • 如果新增了一個選項,傳原列表 + 所選對象
    • 如果取消了一個選項,傳原列表 - 所選對象

(PS:組件庫中提供的 el-checkbox 實際上也是另一個自定義組件,可以同理分析)

<el-table :data="questionList">
  <el-table-column>
    <template slot-scope="scope">
      <el-checkbox
        :value="selectedIds.includes(scope.row.id)"
        @change="(value) => handelChange(scope.row, value)"
      />
    </template>
  </el-table-column>
  <!-- 其他屬性 -->
</el-table>
props: {
  value: Array,
},
computed: {
  selectedIds() {
    return this.value.map((item) => item.id);
  },
},
methods: {
  handelChange(item, checked) {
    if (checked) {
      this.$emit("input", [...this.value, item]);
    } else {
      this.$emit(
        "input",
        this.value.filter((element) => element.id != item.id)
      );
    }
  },
},

具體寫法與組件庫的具體實現有關,簡單說明一下此處的 element 語法:

  • scope.row 為 el-table 表格當前行對應的對象
  • el-checkbox 的 change 事件的負載為復選框點擊后的新值

然后就結束了,父組件使用選擇題目組件時就能正常使用 v-model 了。本例中綁定的數據是完整的題目列表,原因是需要在頁面中顯示已選擇題目的具體信息;如果只需要 id 數據(例如 select 那樣的組件),則 emit 時只傳 id 列表即可,寫法完全一致。

雙向綁定

通過上面的例子想必你已經看出來了,v-model 指令的“雙向綁定”實際上是一個語法糖:它將父組件的數據通過 prop 傳入子組件,再監聽子組件的輸入事件來更新父組件中的數據,從而實現雙向綁定的效果。

v-model

結語&參考資料

以上是個人對 Vue 中 v-model 指令的一些理解與思考,希望能給你提供幫助。如果有問題或疏漏之處,歡迎在評論中討論與指正。

我將繼續在個人博客中更新自己的學習筆記,以前端技術(Vue框架)為主,感興趣的話歡迎關注!

參考資料:Vue 官方文檔


免責聲明!

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



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