在vue2中,子组件上使用v-model的值默认绑定到子组件的props.value属性上,由于子组件不能改变父组件传来的属性,所以需要通过$emit触发事件使得父组件中数据的变化,然后再同步到子组件。vue2默认触发v-model数据变化的事件为input。
使用如下:
子组件MySon
- <template>
- <div>
- <div>双向数据绑定:{{$props.value}}div>
- <div><button @click="addValue">点击++button>div>
- div>
- template>
-
- <script>
- export default {
- name: "MySon",
- props: ['value'],
- methods: {
- addValue() {
- // 触发父组件中v-model绑定数据的变化,由于不能改变props数据中的值,所以不要写this.$props.value++这样的操作
- this.$emit('input', this.$props.value + 1)
- }
- }
- }
- script>
如果希望改变接收v-model的属性或改变触发v-model数据变化的事件,可通过model:{}配置实现,如:
- <template>
- <div>
- <div>双向数据绑定:{{$props.value666}}div>
- <div><button @click="addValue666">点击++button>div>
- div>
- template>
-
- <script>
- export default {
- name: "MySon",
- props: ['value666'],
- // --> 配置接收v-model数据的属性以及改变数据的事件 <--
- model: {
- prop: 'value666',
- event: 'updateValue666'
- },
- methods: {
- addValue666() {
- this.$emit('updateValue666', this.$props.value666 + 1)
- }
- }
- }
- script>
父组件
- <template>
- <div id="app">
- <MySon v-model="num">MySon>
- div>
- template>
-
- <script>
- import MySon from "@/components/MySon.vue";
- export default {
- name: 'App',
- components: {
- //注册子组件
- MySon
- },
- watch: {
- // 监视num数据的变化
- num(newValue, oldValue) {
- console.log('num: ' + oldValue + ' -> ' + newValue)
- },
- },
- data() {
- return {
- num: 10,
- }
- },
- }
- script>
在Vue2中使用v-model只能使用一次,如果要实现多个双向数据绑定,可以借助.sync修饰,使用语法为 :属性.sync="数据" ,用这种绑定代替v-model,触发数据改变的事件为update:属性名
使用如下:
子组件
- <template>
- <div>
- <div>sync双向数据绑定:{{$props.data}}div>
- <div><button @click="addData">点击++button>div>
- div>
- template>
-
- <script>
- export default {
- name: "MySon",
- // 用props.data属性接收双向绑定的数据
- props: ['data'],
- methods: {
- addData() {
- // 触发 update:data 事件改变父组件中绑定的值
- this.$emit('update:data', this.$props.data + 1)
- }
- }
- }
- script>
父组件
- <template>
- <div id="app">
-
- <MySon :data.sync="num">MySon>
- div>
- template>
-
- <script>
- import MySon from "@/components/MySon.vue";
- export default {
- name: 'App',
- components: {
- MySon
- },
- watch: {
- num(newValue, oldValue) {
- console.log('num: ' + oldValue + ' -> ' + newValue)
- }
- },
- data() {
- return {
- num: 10
- }
- },
- }
- script>
至于为什么子组件要通过$emit('update:属性名', 数据);来触发父组件数据变化,原因如下:
- <MySon :data.sync="num">MySon>
- ||
- \/
- 等价于
- <MySon :data="num" @update:data="(newData) => {num = newData}">MySon>
在Vue3中,v-model可以实现多个数据双向数据绑定,同时.sync修饰符已经不再生效。
vue3中子组件上使用v-model绑定的数据默认传到子组件的props.modelValue属性上(vue2是props.value属性),并且默认触发数据变化的事件为update:modelValue (vue2为input)
使用如下:
子组件
- <template>
- <div>
- <div>双向数据绑定modelValue:{{props.modelValue}}div>
- <div><button @click="addModelValue">点击++button>div>
- div>
- template>
- <script setup>
- // props.modelValue接收v-model绑定的数据
- const props = defineProps(['modelValue'])
- const emit = defineEmits(['update:modelValue'])
- function addModelValue(){
- // 触发父组件中双向绑定数据的变化
- emit('update:modelValue', props.modelValue + 1)
- }
- script>
父组件
- <template>
- <Son v-model="num">Son>
- template>
-
- <script setup>
- import {ref, watch} from "vue";
- import Son from "@/components/Son.vue";
-
- const num = ref(0)
- // 监视num数据变化
- watch(num, (newValue, oldValue) => {
- console.log('num: ' + oldValue + '->' + newValue)
- })
- script>
v-model: 属性 实现多个数据双向绑定数据绑定语法:v-model:属性="数据"
触发数据变化的事件:update:属性
使用如下:
子组件
- <template>
- <div>
- <div>双向数据绑定data:{{props.data}}div>
- <div><button @click="addData">点击++button>div>
- div>
- template>
-
- <script setup>
- const props = defineProps(['data'])
- const emit = defineEmits(['update:data'])
- const addData = () => {
- emit('update:data', props.data + 1)
- }
- script>
父组件
- <template>
-
- <Son v-model:data="num">Son>
- template>
- <script setup>
- import {ref, watch} from "vue";
- import Son from "@/components/Son.vue";
- const num = ref(0)
- watch(num, (newValue, oldValue) => {
- console.log('num: ' + oldValue + '->' + newValue)
- })
- script>