1.真正理解v-modelhtml
input元素上的v-model實際上是一個語法糖,其真正做用有兩個:(1)建立一個props,其鍵爲value;(2)監聽input事件,改變value。鍵名與事件名均可以另外設置。vue
當定義一個組件時,v-model是綁定在input的外層的,因此須要手動實現v-model。ide
2.provide / injectthis
provide屬性在祖先組件定義,能夠向其全部子孫組件傳遞一個對象。子孫組件能夠經過inject接收這些屬性,達成注入。雙向綁定
一個簡單的實現:單獨的radio組件能夠綁定v-model,disabled和change事件。也能夠在radio-group中統一綁定。code
radio-group組件htm
<template> <div class="control"> <slot></slot> <!-- radio組件會插入其中 --> </div> </template> <script> export default { name: "XRadioGroup", provide() { return { xRadioGroup: this //將組件自己的vue對象傳遞給下級 }; }, props: { value: null, //v-model綁定的值 disabled: Boolean }, created() { this.$on("handleChange", value => { //監聽自身的handleChange事件 this.$emit("change", value); //觸發自身的change事件 }); } }; </script>
radio組件對象
<template> <label class="radio"> <input type="radio" v-model="model" :name="name" :value="label" :disabled="_disabled" @change="handleChange"> <slot></slot> <template v-if="!$slots.default">{{label}}</template> </label> </template> <script> export default { name: "XRadio", inject: { //得到從祖先組件定義的xRadioGroup xRadioGroup: { default: "" //默認爲'' } }, props: { name: String, disabled: Boolean, label: [String, Number, Boolean], value: null //v-model綁定的值 //size: String }, computed: { isGroup() { return this.xRadioGroup !== ""; //是否包含與radio-group中 }, model: { get() { //獲取時觸發 return this.isGroup ? this.xRadioGroup.value : this.value;//實現了在group和radio上均可以綁定v-model }, set(val) { //賦值時觸發 this.isGroup ? this.xRadioGroup.$emit("input", val) //經過input完成雙向綁定 : this.$emit("input", val); } }, _disabled() { return this.isGroup ? this.xRadioGroup.disabled : this.disable; } }, methods: { handleChange() { this.$nextTick(() => { this.$emit("change", this.model); this.isGroup && this.xRadioGroup.$emit("handleChange", this.model); //如xRadioGroup存在,觸發其handleChange事件 }); } } }; </script>