上善若水,水善利萬物而不爭。——《道德經》javascript
在平時開發是常常用到一些父子組件通訊,常常用到props
、vuex
等等,這裏面記錄另外的三種方式v-model
、sync
是怎麼使用,再說是怎麼實現,其實v-model
、sync
都是語法糖。還有$attr
、$listener
實現父子組件通訊。html
2.2.0+ 新增vue
v-mode1
其實就是一個語法糖,默認會利用名爲value
的props
和名爲input
的事件,可是像單選框、複選框等類型的輸入龍劍可能會講value
特性用於不一樣的目的。java
v-model
的使用場景:當子組件須要改變父組件經過props
傳入的值react
父組件vuex
v-model
綁定值v-model
傳入的值改變,而觸發其餘更新請經過watch
傳入的值子組件element-ui
model
對象 設置事件event
和prop
字段porps
接受父組件傳送值this.$emit
廣播事件代碼示例:api
父組件代碼跨域
<template>
<children v-model="message"></children>
</template>
<script>
import children from "./children.vue";
export default {
components: {
children
},
data() {
return {
message: "parent"
};
},
watch: {
// 監聽message變化
message(newV, oldV) {
console.log(newV, oldV);
}
}
};
</script>
複製代碼
子組件代碼babel
<template>
<h1>{{ message }}</h1>
</template>
<script>
export default {
model: {
prop: "message", //這個字段,是指父組件設置 v-model 時,將變量值傳給子組件的 msg
event: "input" //這個字段,是指父組件監聽 parent-event 事件
},
props: {
message: String //此處必須定義和model的prop相同的props,由於v-model會傳值給子組件
},
mounted() {
//這裏模擬異步將msg傳到父組件v-model,實現雙向控制
setTimeout(_ => {
this.$emit("input", "children");
//將這個值經過 emit 觸發parent-event,將some傳遞給父組件的v-model綁定的變量
}, 1500);
}
};
</script>
複製代碼
上面這個示例是經過v-model
實現的,下面不經過v-model
實現一樣效果。
代碼示例以下:
父組件代碼修改
<template>
<Children :message="message" @input="(event) => { message = event }"/>
</template>
<script>
// 不變
</script>
複製代碼
子組件代碼修改
<template>
// 不變
</template>
<script>
export default {
props: {
message: String
},
mounted() {
setTimeout(() => {
this.$emit("input", "children");
}, 1500);
}
};
</script>
複製代碼
只是把v-model
拆分爲props
和@input
事件,子組件不須要配置model
,只須要接受props
和經過this.$emit
廣播事件就能夠。 固然這個相對於v-model
方法比較簡便,可是靈活度查不少,選擇使用那種看我的喜愛。 在線地址:
不能放iframe
只能放一放一個連接了本篇代碼實例
2.3.0+ 新增
在有些狀況下,咱們可能須要對一個 prop
進行**「雙向綁定」。不幸的是,真正的雙向綁定**會帶來維護上的問題,由於子組件能夠修改父組件,且在父組件和子組件都沒有明顯的改動來源。
這也是爲何咱們推薦以 update:myPropName
的模式觸發事件取而代之。同時也能夠經過sync
修飾符來實現。
在上面代碼的基礎上大體修改以下:
父組件
input
爲update:myPropName
實現相同效果子組件
this.$emit(update:myPropName)
代碼以下:
父組件代碼修改
// 修改以下
<Children :message="message" @update:input="(event) => { message = event }"/>
複製代碼
子組件代碼修改
// 其餘不變
this.$emit("update:input", "children");
複製代碼
上面的代碼能夠經過sync
簡寫爲下面代碼:
父組件代碼修改
// 修改以下
<Children :messag.sync="message"/>
複製代碼
子組件代碼修改
// 其餘不變
this.$emit("update:messag", "children");
複製代碼
同時sync
也支持對象,要配合v-bind
實現能夠簡寫爲:
,可是要注意這個對象以下兩條:
注意帶有
.sync
修飾符的v-bind
不能和表達式一塊兒使用 (例如v-bind:title.sync=」doc.title + ‘!’」
是無效的)。取而代之的是,你只能提供你想要綁定的屬性名,相似v-model
。 將v-bind.sync
用在一個字面量的對象上,例如v-bind.sync=」{ title: doc.title }」
,是沒法正常工做的,由於在解析一個像這樣的複雜表達式的時候,有不少邊緣狀況須要考慮。
2.4.0 新增
{ [key: string]: string }
prop
被識別 (且獲取) 的特性綁定 (class
和 style
除外)。當一個組件沒有聲明任何 prop
時,這裏會包含全部父做用域的綁定 (class
和 style
除外),而且能夠經過 v-bind="$attrs"
傳入內部組件——在建立高級別的組件時很是有用。2.4.0 新增
{ [key: string]: Function | Array<Function> }
.native
修飾器的) v-on
事件監聽器。它能夠經過 v-on="$listeners"
傳入內部組件——在建立更高層次的組件時很是有用。實現父子組件通訊
父組件代碼
<template>
<div class="parent"> <Children :message="message" @upDate="upDate" type="del" @input="(event) => { message = event }" /> </div> </template>
<script>
import Children from "./Children";
export default {
components: {
Children
},
data() {
return {
message: "parent",
type: "del"
};
},
methods: {
upDate (event) {
console.log(event);
this.type = event;
}
},
watch: {
message: function() {
console.log("更新message值爲" + this.message);
}
}
};
</script>
複製代碼
子組件代碼
<template>
<div v-bind="$attrs" v-on="$listeners" class="children">{{message}} <span @click="$listeners.upDate('data')">{{$attrs.type}}</span></div>
</template>
<script>
export default {
props: {
message: String
},
mounted() {
// console.log(this.$attrs);
// console.log(this.$listeners);
setTimeout(() => {
this.$emit("input", "children");
this.$emit('upDate', 'add')
}, 1500);
}
};
</script>
複製代碼
同時$attrs
、$listeners
都是能夠跨域父子組件,能夠父子子子組件傳遞,相似於react
中的context
,只是一部分設計理念相同。
其實就是檢測到.sync
修飾符,在complier
階段會編譯生成多個prop
,生成多個事件
。其實像這個指令、修飾符、自定義指令都是在vue
編譯是解析成爲v8能執行的代碼。
不管是vue
、babel
、react
的complier
編譯階段大體分爲三個階段:
parse
生成抽象AST
或抽象代碼樹
AST
,好比vue
標記靜態節點,babal
中抽取靜態代碼,這個階段被稱爲optimize
或者優化AST樹
AST
代碼的階段上,生成可執行代碼,這個過程能夠叫作codegen
v-model
、sync
均可以實現父子組件通訊,而且能夠在子組件中修改父組件傳入的值。在日常見解的時候進場能夠用到這兩種方式,具體選擇那種方式看我的喜愛。在element-ui
這個input
組件也用到相關的屬性。