1、v-model
Vue2
Vue2中得 v-model 默认解析成 :value 与 @input
原理实现
父:
<template><div>{{ count }}<button @click="count++">+1</button><hr /><HelloWorld :value="count" @input="count = $event"></HelloWorld></div>
</template><script>
import HelloWorld from "./components/HelloWorld.vue";export default {name: "App",components: {HelloWorld,},data() {return { count: 0 };}
};
</script><style></style>
子:
<template><div>{{ value }}<button @click="$emit('input', value + 1)">+1</button></div>
</template><script>
export default {name: "HelloWorld",props: {value: Number,},
};
</script>
<style scoped></style>
语法糖实现
父:
<template><div>{{ count }}<button @click="count++">+1</button><hr /><HelloWorld v-model="count" /></div>
</template><script>
import HelloWorld from "./components/HelloWorld.vue";export default {name: "App",components: {HelloWorld,},data() {return { count: 0 };}
};
</script><style></style>
子:
<template><div>{{ value }}<button @click="$emit('input', value + 1)">+1</button></div>
</template><script>
export default {name: "HelloWorld",props: {value: Number,},
};
</script>
<style scoped></style>
Vue3
Vue3中得 v-model 默认解析成 :modelValue 与 @update:modelValue
原理实现
父:
<script setup lang="ts">
import { ref } from 'vue'
const count = ref(0)
</script><template><div>{{ count }}<button @click="count++">+1</button><hr /><HelloWorld:modelValue="count"@update:modelValue="count = $event"></HelloWorld></div>
</template><style lang="scss" scoped></style>
子:
<script setup lang="ts">
defineProps<{modelValue: number
}>()
defineEmits<{(e: 'update:modelValue', newCount: number): void
}>()
</script><template><div>{{ modelValue }}<button @click="$emit('update:modelValue', modelValue + 1)">+1</button></div>
</template><style lang="scss" scoped></style>
语法糖实现
父:
<script setup lang="ts">
import { ref } from 'vue'
const count = ref(0)
</script><template><div>{{ count }}<button @click="count++">+1</button><hr /><HelloWorld v-model="count"></HelloWorld></div>
</template><style lang="scss" scoped></style>
子:
<script setup lang="ts">
defineProps<{modelValue: number
}>()
defineEmits<{(e: 'update:modelValue', newCount: number): void
}>()
</script><template><div>{{ modelValue }}<button @click="$emit('update:modelValue', modelValue + 1)">+1</button></div>
</template><style lang="scss" scoped></style>
2、 .sync
Vue2
Vue2中得 :attr.sync 默认解析成 :attr 与 @update:attr
原理实现
父:
<template><div>{{ count }}<button @click="count++">+1</button><hr /><HelloWorld :count="count" @setCount="count = $event" /></div>
</template><script>
import HelloWorld from "./components/HelloWorld.vue";export default {name: "App",components: {HelloWorld,},data() {return { count: 0 };}
};
</script><style></style>
子:
<template><div class="hello">{{ count }}<button @click="$emit('setCount', count + 1)">+1</button></div>
</template><script>
export default {name: "HelloWorld",props: {count: Number,},
};
</script>
<style scoped></style>
语法糖实现
父:
<template><div>{{ count }}<button @click="count++">+1</button><hr /><HelloWorld :count.sync="count" /></div>
</template><script>
import HelloWorld from "./components/HelloWorld.vue";export default {name: "App",components: {HelloWorld,},data() {return { count: 0 };}
};
</script><style></style>
子:
<template><div class="hello">{{ count }}<button @click="$emit('update:count', count + 1)">+1</button></div>
</template><script>
export default {name: "HelloWorld",props: {count: Number,},
};
</script>
<style scoped></style>
Vue3
Vue3中得 v-model:attr 默认解析成 :attr 与 @update:attr
原理实现
父:
<script setup lang="ts">
import { ref } from 'vue'
const count = ref(0)
</script><template><div>{{ count }}<button @click="count++">+1</button><hr /><HelloWorld :count="count" @setCount="count = $event"></HelloWorld></div>
</template><style lang="scss" scoped></style>
子:
<script setup lang="ts">
defineProps<{count: number
}>()
defineEmits<{(e: 'setCount', newCount: number): void
}>()
</script><template><div>{{ count }}<button @click="$emit('setCount', count + 1)">+1</button></div>
</template><style lang="scss" scoped></style>
语法糖实现
父:
<script setup lang="ts">
import { ref } from 'vue'
const count = ref(0)
</script><template><div>{{ count }}<button @click="count++">+1</button><hr /><HelloWorld v-model:count="count"></HelloWorld></div>
</template><style lang="scss" scoped></style>
子:
<script setup lang="ts">
defineProps<{count: number
}>()
defineEmits<{(e: 'update:count', newCount: number): void
}>()
</script><template><div>{{ count }}<button @click="$emit('update:count', count + 1)">+1</button></div>
</template><style lang="scss" scoped></style>
3、总结
Vue2中得 v-model 默认解析成 :value 与 @input
Vue3中得 v-model 默认解析成 :modelValue 与 @update:modelValue
Vue2中得 :attr.sync 默认解析成 :attr 与 @update:attr
Vue3中得 v-model:attr 默认解析成 :attr 与 @update:attr
作用:用于在自定义组件中实现父子组件之间的双向数据绑定
也就是说在Vue3中只有v-model
,没有.sync
如果父组件只写v-model="xxx"
,子组件中接收到的props为modelValue
,抛出的自定义事件为update:modelValue
如果父组件写v-model:attr="xxx"
(attr
为自定义变量),子组件中接收到的props为attr
,抛出的自定义事件为update:attr
即:Vue3中使用双向数据绑定v-model时props不局限于只能接收modelValue
,可以自定义
使用方式:
父:
<HelloWorld v-model="count"></HelloWorld>子:
defineProps<{modelValue: number
}>()
defineEmits<{(e: 'update:modelValue', newCount: number): void
}>()
$emit('update:modelValue', modelValue + 1)"=====================================================================================父:
<HelloWorld v-model:count="count"></HelloWorld>子:
defineProps<{count: number
}>()
defineEmits<{(e: 'update:count', newCount: number): void
}>()
$emit('update:count', count + 1)">