前言
Vue中v-model
和sync
一样都是实现双向绑定的语法糖,可以让开发者少些一些代码,两者编译后都会产生一个属性和一个事件,不过两者规则不大一样。
sync
sync
实现双向绑定主要用于子组件修改父组件的数据的一种便捷操作,常用于分页器
等组件。要想使用sync
,子组件需要有如下规则:
要想使用sync作为数据的双向绑定的修饰符,子组件必须向外抛出的时间满足规则:$emit(“update:{propName}”, {newValue}),其中propName
是修改的prop名字,newValue是传递给父组件数据count的新数据
子组件:
<template>
<div class="hello">
<span>{{count}}</span>
<button @click="$emit('update:count', count + 1)">+1</button>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: ['count']
}
</script>
父组件:
父组件接收时可以使用传统的方式进行接收,也可以使用sync
修饰符修饰绑定的数据count
<template>
<div id="app">
<HelloWorld :count="count" @update:count="count=$event"/>
<HelloWorld :count.sync="count"/>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
},
data() {
return {
count: 1
}
}
}
</script>
v-model
v-model实现和sync类似,其最终结果也会生成一个事件和一个属性,先看一下如下代码输出
<template>
<div class="hello">
<input type="text" v-model="data" />
</div>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
data: ''
};
},
mounted() {
console.log(this._vnode);
}
};
</script>
输出如下:
我们可以清楚地看到,在HelloWorld
组件中input
输入框所绑定的数据中,on
有一个input
事件,domProps
有一个value
事件,所以上面的组件等效于如下代码:
<template>
<div class="hello">
<input type="text" :value="data" @input="data=$event.target.value" />
</div>
</template>
<script>
export default {
name: "HelloWorld",
data() {
return {
data: ''
};
},
mounted() {
console.log(this._vnode);
}
};
</script>
v-model作用于表单
Vue中v-model常用作用于表单元素
,vue会根据所绑定的表单元素类型,合成合适的事件和属性,例如作用于文本框时生成一个value
属性和一个input
事件,而当其绑定单选框或多选框时,它会生成checked
属性和change
事件
v-mode作用于组件
v-model也可以作用于组件实例,例如:
父组件:
<template>
<div id="app">
<HelloWorld v-model="count"/>
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld.vue'
export default {
name: 'App',
components: {
HelloWorld
},
data() {
return {
count: 1
}
}
}
</script>
子组件:
<template>
<div class="hello">
</div>
</template>
<script>
export default {
name: "HelloWorld",
mounted() {
console.log(this.$vnode);
}
};
</script>
我们先看一下console输出什么:
可以很明显地看到,在子组件形成的虚拟dom中,data有个model
对象。接下来我们改造一下子组件。
我们将props
中声明一个value
,
<template>
<div class="hello">
{{value}}
<button @click="$emit('input', value + 1)">+1</button>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: ["value"],
mounted() {
console.log(this.$vnode);
}
};
</script>
我们可以很清楚地看到,count数据会改变,这是为啥呢???
v-model默认值是value
属性和input
事件,这从我们最开始的那个v-model截图和测试就可以看出来。
当然我们也可以改变其默认值。在组件中加入如下配置:
子组件
<template>
<div class="hello">
{{ count }}
<button @click="$emit('update', count + 1)">+1</button>
</div>
</template>
<script>
export default {
name: "HelloWorld",
model: {
prop: "count",
event: "update",
},
props: ["count"],
mounted() {
console.log(this);
},
};
</script>
我们也可以看到视图是能够正常进行更新的。