需求:父子組件同步數據
實現方式:sync或者v-model
一、sync
原理:
通常我們要父子組件中的數據時刻保持同步,可以這樣:
父組件中的template:
<sycn-son :foo="fatherFoo"></sycn-son>
子組件注冊foo數據:
props:{
foo: String
},
子組件改變:通過點擊按鈕,觸發update事件,將值傳入
<button @click="updateFoo">點擊改變</button>
methods:{ updateFoo(){ this.$emit('update','foo被子組件改變啦') } }
父組件接收:
<sycn-son :foo="fatherFoo" v-on:update="sonFoo => fatherFoo = sonFoo"></sycn-son>
效果:
未點擊:

點擊改變:

父組件來點擊改變:

這樣就實現了父子組件同步數據,sync就是這樣的原理,vue提供了sync修飾符簡化了上面的代碼
因此就可以這樣寫:
父組件:
<sycn-son :foo.sync="fatherFoo"></sycn-son>
子組件:
updateFoo(){ this.$emit('update:foo','foo被子組件改變啦') }
效果:依舊如上圖
代碼:
父組件:
<template> <div> <sycn-son :foo.sync="fatherFoo"></sycn-son> <br> 父組件的foo:{{fatherFoo}} <button @click="syncFatherUpdate">父組件來點擊改變</button> </div> </template> <script> import sycnSon from './sycnSon' export default { name: 'sycnFather', components:{ sycnSon }, data () { return { fatherFoo:'我是一開始的foo' } }, methods:{ syncFatherUpdate (){ this.fatherFoo = '被父組件改變' } } } </script>
子組件:
<template> <div> 子組件的foo:{{foo}} <button @click="updateFoo">點擊改變</button> </div> </template> <script> export default { name: 'sycnSon', props:{ foo: String }, methods:{ updateFoo(){ this.$emit('update:foo','foo被子組件改變啦') } } } </script>
注意:
當sync修飾的prop是個對象或者數組,雖然對象/數組是引用類型的,你直接修改子組件,會同時修改父組件的數據,但是會讓數據流變得更加難以分析!所以要深度復制對象給一個新值,再改變新值傳給父組件。
JSON.parse(JSON.stringify(this.analysisData))
二、v-model---只介紹父子組件雙向綁定
v-model通常用於表單元素的雙向綁定,v-model 是 .sync的一種體現。約定俗成是用於表單類型的雙向綁定。可不可以用於其他的組件呢,當然可以,只是沒有sync這么直觀
1. 表單類型的雙向綁定:
子組件:
<input :value="value" @input="$emit('input', $event.target.value)">
@input是自帶的oninput事件,當輸入框改變時,調用里面的事件。
父組件:
<model-son v-model="fatherMsg"></model-son>
相當於:
效果:
未改變輸入框:

改變輸入框:

點擊父組件來點擊改變:

完整代碼:
父組件:
<template> <div> <model-son v-model="fatherMsg"></model-son> <br> 父組件:{{fatherMsg}} <button @click="modelFatherUpdate">父組件來點擊改變</button> </div> </template> <script> import modelSon from './modelSon' export default { name: 'modelFather', components:{ modelSon }, data () { return { fatherMsg:'父組件一開始定義的fatherMsg' } }, methods:{ modelFatherUpdate (){ this.fatherMsg = 'fatherMsg被父組件改變' } } } </script>
子組件:
<template> <div> 子組件的msg: <input :value="value" @input="$emit('input', $event.target.value)"> </div> </template> <script> export default { name: 'modelSon', // 必須是value props:{ value:String }, } </script>
注意:注冊必須是value
2.自定義組件v-model雙向綁定
官網:
子組件:首先要注冊,和說明model
model: { prop: 'msg', event: 'change' }, props:{ msg:String },
使用model解釋:prop屬性說,我要將msg作為該組件被使用時v-model能取到的值,也就是一開始的值
event說,我emit ‘change’ 的時候,傳入的參數值就是父組件v-model要收到的值。
父組件:使用v-model綁定自己的數據
<model-son v-model="fatherMsg"></model-son>
效果:
未點擊時:

點擊改變:

父組件來點擊改變:

完整代碼:
父組件:
<template> <div> <model-son v-model="fatherMsg"></model-son> <br> 父組件:{{fatherMsg}} <button @click="modelFatherUpdate">父組件來點擊改變</button> </div> </template> <script> import modelSon from './modelSon' export default { name: 'modelFather', components:{ modelSon }, data () { return { fatherMsg:'父組件一開始定義的fatherMsg' } }, methods:{ modelFatherUpdate (){ this.fatherMsg = 'fatherMsg被父組件改變' } } } </script>
子組件:
<template> <div> 子組件的msg:{{msg}} <button @click="modelUpdate">點擊改變</button> </div> </template> <script> export default { name: 'modelSon', model: { prop: 'msg', event: 'change' }, props:{ msg:String }, methods:{ modelUpdate (){ this.$emit('change','msg被子組件改變了!') } } } </script>
待補充。。。