前言:見多了父組件向子組件傳遞數據,子組件向父組件傳遞數據,現在來玩玩父組件與子組件之間雙向數據綁定,還有通過.sync修飾符,來優化這種寫法。
方法一:對象的引用關係
<body>
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.js"></script>
<div id="box">
<new-input v-bind:person="freddy" ></new-input>
{{freddy.name}}
</div>
<script>
Vue.component('new-input',{
props: ['person'],
template:'<label><input type="text" v-model="person.name" /> 你的名字:</label>'
});
new Vue({
el:'#box',
data: {
freddy: {
name:'nick'
}
}
});
</script>
</body>
運行結果:
該方法運用的是對象的引用關係,來實現的。雖然實現起來很簡單,但是還是存在數據混亂的隱患。使用時要比較小心。
方法二:父子組件之間的數據傳遞
<body>
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.js"></script>
<div id="box">
<new-input v-bind:name="name" v-on:update:name="getNewName"></new-input>
{{name}}
</div>
<script>
Vue.component('new-input',{
props: ['name'],
data: function(){
return {
newName: this.name
}
},
template:'<label><input type="text" @keyup="changeName" v-model="newName" /> 你的名字:</label>',
methods: {
changeName: function(){
this.$emit('update:name',this.newName);
}
}
});
new Vue({
el:'#box',
data: {
name:'nick'
},
methods:{
getNewName: function(newName){
this.name = newName;
}
}
});
</script>
</body>
運行結果:
稍微提一下的是,通過props,父組件向子組件傳遞了那麼name值,然後通過註冊'update:name'事件給父組件傳遞新的name值。
這裏爲什麼要註冊一個'update:name'這麼複雜的事件名稱呢?這其實跟下面要說的.sync修飾符有關
還有一點比較重要的是
<new-input v-bind:name="name" v-on:update:name="getNewName"></new-input>
可以簡寫成
<new-input v-bind:name="name" v-on:update:name="name = $event"></new-input>
方法三: .sync
<body>
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.js"></script>
<div id="box">
<new-input v-bind:name.sync="name"></new-input>
{{name}}
</div>
<script>
Vue.component('new-input',{
props: ['name'],
data: function(){
return {
newName: this.name
}
},
template:'<label><input type="text" @keyup="changeName" v-model="newName" /> 你的名字:</label>',
methods: {
changeName: function(){
this.$emit('update:name',this.newName);
}
}
});
new Vue({
el:'#box',
data: {
name:'nick'
},
methods:{
getNewName: function(newName){
this.name = newName;
}
}
});
</script>
</body>
運行結果
通過與方法一進行比較:會發現
<new-input v-bind:name="name" v-on:update:name="name = $event"></new-input>
被簡化成了
<new-input v-bind:name.sync="name"></new-input>
而其他代碼不變。
所以我們在使用.sync修飾符的時候,只需要注意,v-bind:xx,v-on:update:xx,v-bind:xx.sync的差異就行了。
而且註冊事件的時候一定要用this.$emit( 'update:xx' );
方法四: v-model
<body>
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.js"></script>
<div id="box">
<new-input v-model="name"></new-input>
{{name}}
</div>
<script>
Vue.component('new-input',{
props: ['value'],
template:'<label><input type="text" v-model="newValue" /> 你的名字:</label>',
computed:{
newValue: {
get:function() {
return this.value;
},
set:function(value) {
this.$emit('input', value);
}
}
},
});
new Vue({
el:'#box',
data: {
name:'nick'
}
});
</script>
</body>
要理解該方法的關鍵是要知道v-model是怎麼去實現的。
模仿v-model
<body>
<script src="https://cdn.bootcss.com/vue/2.5.16/vue.js"></script>
<div id="box">
<input :value="name" @input="changeValue($event.target.value)"/>
{{ name }}
</div>
<script>
new Vue({
el:'#box',
data: {
name:'nick'
},
methods:{
changeValue:function(value){
this.name = value;
}
}
});
</script>
</body>
這時就可以看出來了,我們通過['value']可以獲取到父組件給子組件傳遞的值,也可以用過註冊input方法方法來通過子組件給父組件傳值。