vue自定義元件實現雙向繫結
場景:
我們比較常用的父子元件之間的互動方式:
父元件通過props將資料流入到子元件;
子元件通過$emit將更新後的陣列傳送的父元件;
今天,我們通過另一種方式實現互動,參考input框的v-model,實現自定義元件的雙向資料繫結。
即:父元件值改變,子元件的值跟著改變;反之,子元件值發生變化,父元件值隨之變化
子元件定義:
由於不能直接修改props屬性值,我們這裡定義valueData,通過監聽實時接收value值,通過click方法修改valueData。
這裡注意model語法糖prop 是接收的props屬性value,保持一致。event是先上傳遞的事件名。
程式碼如下:
<template> <div> <div>{{ `子元件值: ${value}` }}</div> <div @click="click">點選此處修改值</div> </div> </template> <script> export default { name: "",model: { prop: "value",event: "change" },props: { value: Number },components: {},data() { return { valueData: "" }; },watch: { value(newValue,oldValue) { this.valueData = newValue; console.log(`子元件值:${newValue}`); } },created() { },mounted() { },methods: { click() { this.valueData++; this.$emit("change",this.valueData); } } }; </script> <style lang='less' scoped> </style>
父元件定義:
父元件通過v-model繫結text值,名稱不一定是value,可以是其他任意符合命名規範的字串,這裡是text。
子元件通過change事件更新資料後,v-mode繫結值隨之變化。
或者父元件修改text值後,子元件value值隨之變化。
程式碼如下:
<template> <div> <div>{{ `父元件值:${text}` }}</div> <div @click="click">點選此處修改值</div> <span>-----------------------------------------------------------</span> <test-children v-model="text"></test-children> </div> </template> <script> import TestChildren from "@/views/TestChildren"; export default { name: "",components: { TestChildren },data() { return { text: 1 }; },watch: { text(newValue,oldValue) { console.log(`父元件值:${newValue}`); } },methods: { click() { this.text--; } } }; </script> <style lang='less' scoped> </style>
結果:
直接copy程式碼到自己專案測試。無論是通過父元件改變值,還是子元件改變值。兩個元件通過v-mode繫結的值始終保持一致。
答疑:
有同學就問了 ,這不是和通過props向下流入資料,再通過$emit方式向上傳遞資料一樣麼也能實現我這種雙向繫結的效果。 其實不然,如果不通過v-model,那麼我們勢必會在父元件寫這樣的程式碼:
<test-children @change="changeText"></test-children>
然後在通過定義changeText方法修改text值。
試想,當我們的頁面比較複雜,引用元件量比較龐大,頁面中就需要多定義這樣十幾、二十幾個方法。可閱讀行大大降低,增加了維護成本。
擴充套件:
vue2.3之後提供了sync方式,也能實現雙向繫結
父元件中的寫法:
<test-children :value.sync="text"></test-children>
子元件中不需要使用下面model定義,直接刪除即可。
model: { prop: “value”,event: “change” },
向父元件傳遞資料使用如下方式:
this.$emit("update:value",this.valueData);
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。