>[success] # 子传父语法糖拆解 ~~~ 1.子传父,这个语法糖,是对 vue是单向数据流绑定的因此,你子组件直接去改父组件 的值就会产生vue警告,这种的解决方法除了官方介绍'$emit'这种传统的方法,也有提供 的语法糖'sync'和'v-model' ,本章节就是对这两个语法糖的讲解 ~~~ >[info] ## v-model 组件语法糖 ~~~ 1.当'input' 作为组件的一部分并且还要需要和父组件联动的时候,整个子组 件内的'input' 就已经不能在使用v-model 的形式,因为vue数据传递是单向 的,在子组件中使用了v-model 的形式就会出现,没有触发改变父组件值 的问题 2.'v-model' 作为语法糖时候,在父组件调用的子组件上只能用一次 ~~~ >[danger] ##### 不使用的效果 ~~~ 1.利用传统的写法,父组件给子组件传入,子组件用'props'接受,然后子组 件再用'$emit'绑定父组件方法,通过父组件的方法改变自己的值 ~~~ * 子组件 ~~~ <template> <div> <input @input="handleChange" :value="username"/> </div> </template> <script> export default { name: "MyInput", props:{ username:String, }, methods:{ handleChange(e){ this.$emit('change',e.target.value) } } } </script> <style scoped> </style> ~~~ * 父组件 ~~~ <template> <div> <MyInput @change="pChange" :username="pUserName"></MyInput> {{pUserName}} </div> </template> <script> import MyInput from '@/components/MyInput.vue' export default { components: { MyInput }, data() { return { pUserName:'' }; }, methods:{ pChange(val){ this.pUserName = val } } }; </script> ~~~ >[danger] ##### 使用语法糖v-model -- 配合model属性 ~~~ 1.首先'v-model'我们都知道是'@input' 和 ':value'的缩写,但不是绝对唯一, 当我们想重新规定,我们自己的'v-model'触发条件的时候可以使用'model' 2.下面案例就是定义了监听的值从'value' 变成了'username',触发的事件 'input'变成'change' ~~~ * 子组件 ~~~ 1.子组件规定了调用的时候'v-model' 将触发双向绑定的值和事件,分别是 'username'属性 和'change'事件会触发 ~~~ ~~~ <template> <div> <input @input="handleChange" :value="username"/> </div> </template> <script> export default { name: "MyInput", model: { prop: "username", // 默认 value event: "change" // 默认 input }, props:{ username:String, }, methods:{ handleChange(e){ console.log(this.username) this.$emit('change',e.target.value) } } } </script> <style scoped> </style> ~~~ * 父组件 ~~~ <template> <div> <MyInput v-model="username"></MyInput> {{username}} </div> </template> <script> import MyInput from '@/components/MyInput.vue' export default { components: { MyInput }, data() { return { username:'' }; }, }; </script> ~~~ >[danger] ##### 不要被输入框的案例限制思路 ~~~ 1.也可以通过点击按钮形成v-mdoel的语法糖,但前提要注意需要配 置'model' 默认使用'change' 事件 ~~~ * 子组件、 ~~~ <template> <div> <input :value="username"/> <a @click="handleChange">111</a> </div> </template> <script> export default { name: "MyInput", model: { prop: "username", // 默认 value event: "change" // 默认 input }, props:{ username:String, }, methods:{ handleChange(e){ this.$emit('change','111') } } } </script> <style scoped> </style> ~~~ * 父组件同上 >[danger] ##### sync 的语法糖解决v-mdoel只能出现一次的问题 ~~~ 1.sync 的语法糖其实是@input的缩写 2.下面案例直接是一个'v-model' 和'sync'的缩写和非缩写的案例 ~~~ * 子组件 ~~~ <template> <div> <select :value="phoneInfo.areaCode" placeholder="区号" @change="handleAreaCodeChange" > <option value="+86">+86</option> <option value="+60">+60</option> </select> <input :value="phoneInfo.phone" type="number" placeholder="手机号" @input="handlePhoneChange" /> <input :value="zipCode" type="number" placeholder="邮编" @input="handleZipCodeChange" /> </div> </template> <script> export default { name: "PersonalInfo", // v-model 定义使用的 model: { prop: "phoneInfo", // 默认 value event: "change" // 默认 input }, props: { phoneInfo: Object, zipCode: String }, methods: { handleAreaCodeChange(e) { this.$emit("change", { ...this.phoneInfo, areaCode: e.target.value }); }, handlePhoneChange(e) { this.$emit("change", { ...this.phoneInfo, phone: e.target.value }); }, handleZipCodeChange(e) { this.$emit("update:zipCode", e.target.value); } } }; </script> ~~~ * 父组件 ~~~ <template> <div> <PersonalInfo v-model="phoneInfo" :zip-code.sync="zipCode" /> <PersonalInfo :phone-info="phoneInfo" :zip-code="zipCode" @change="val => (phoneInfo = val)" @update:zipCode="val => (zipCode = val)" /> phoneInfo: {{ phoneInfo }} <br /> zipCode: {{ zipCode }} </div> </template> <script> import PersonalInfo from '@/components/test.vue' export default { components: { PersonalInfo }, data() { return { phoneInfo: { areaCode: "+86", phone: "" }, zipCode: "" }; } }; </script> ~~~