Vue3 组件 v-model 和 defineModel 使用
vue
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
项目地址:https://gitcode.com/gh_mirrors/vu/vue
免费下载资源
·
v-model 可以在组件上使用以实现双向绑定
简单使用
Home.vue
<template>
<Child v-model="city"></Child>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import Child from '@/views/home/Child'
const city = ref('bj')
</script>
Child.vue
<template>
<input
:value="props.modelValue"
@input="emit('update:modelValue', $event.target.value)"
/>
</template>
<script lang="ts" setup>
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])
</script>
组件 v-model 等同于给子组件传递一个名为 modelValue 的prop;并接受一个名为 update:modelValue 的事件。如:
Home.vue
<template>
<!-- <Child v-model="city"></Child> -->
<!-- 等同于上面的 v-model="city" -->
<Child :modelValue="city" @update:modelValue="handleCity"></Child>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import Child from '@/views/home/Child'
const city = ref('bj')
const handleCity = (value) => {
city.value = value
}
</script>
多属性双向绑定
当子组件中一个变量需要和父组件做成同步时,此时可以通过 computed 实现
Home.vue
<template>
<Child v-model="city" v-model:address="address"></Child>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import Child from '@/views/home/Child'
const city = ref('bj')
const address = ref('haidian')
</script>
Child.vue
<template>
<input v-model="localCity" />
<input v-model="localAddress" />
</template>
<script lang="ts" setup>
import { computed } from 'vue'
type TProps = {
modelValue: string
address: string
}
const props = withDefaults(defineProps<TProps>(), {})
const emit = defineEmits(['update:modelValue', 'update:address'])
const localCity = computed({
get() {
return props.modelValue
},
set(value) {
emit('update:modelValue', value)
}
})
const localAddress = computed({
get() {
return props.address
},
set(value) {
emit('update:address', value)
}
})
</script>
在子组件中通过 computed 的 get 获取 prop 中的值,通过 set 再触发事件修改值
当 v-model 增加参数时,传递到子组件默认的 modelValue 就会变成 传递的参数,如:address,同时触发事件也会由 update:modelValue 变成 update:address
vueuse 库的 useVModel 内部大体也是这样实现的
defineModel 使用
从 Vue 3.4 开始,推荐的实现方式是使用 defineModel() 宏,这个宏可以用来声明一个双向绑定 prop,通过父组件的 v-model 来使用
defineModel() 返回的值是一个 ref。它可以像其他 ref 一样被访问以及修改,不过它能起到在父组件和当前变量之间的双向绑定的作用
- 它的 .value 和父组件的 v-model 的值同步;
- 当它被子组件变更了,会触发父组件绑定的值一起更新。
在底层,这个宏声明了一个 model prop 和一个相应的值更新事件。如果第一个参数是一个字符串字面量,它将被用作 prop 名称;否则,prop 名称将默认为 “modelValue”。在这两种情况下,你都可以再传递一个额外的对象,它可以包含 prop 的选项和 model ref 的值转换选项。
defineModel 底层编译器将其展开为以下内容:
- 一个名为 modelValue 的 prop,本地 ref 的值与其同步;
- 一个名为 update:modelValue 的事件,当本地 ref 的值发生变更时触发。
// 声明 "modelValue" prop,由父组件通过 v-model 使用
const model = defineModel()
// 或者:声明带选项的 "modelValue" prop
const model = defineModel({ type: String })
// 在被修改时,触发 "update:modelValue" 事件
model.value = "hello"
// 声明 "count" prop,由父组件通过 v-model:count 使用
const count = defineModel("count")
// 或者:声明带选项的 "count" prop
const count = defineModel("count", { type: Number, default: 0 })
function inc() {
// 在被修改时,触发 "update:count" 事件
count.value++
}
在 TypeScript 中使用
defineModel 也可以接收类型参数来指定 model 值和修饰符的类型:
const modelValue = defineModel<string>()
// 用带有选项的默认 model,设置 required 去掉了可能的 undefined 值
const modelValue = defineModel<string>({ required: true })
我们再通过 defineModel 来实现上面的功能
Home.vue
<template>
<Child v-model="city" v-model:address="address"></Child>
</template>
Child.vue
<script lang="ts" setup>
import { ref } from 'vue'
import Child from '@/views/home/Child'
const city = ref('bj')
const address = ref('haidian')
</script>
<template>
<input v-model="localCity" />
<input v-model="localAddress" />
</template>
<script lang="ts" setup>
const localCity = defineModel()
// required 是否必传属性 default: 默认值
const localAddress = defineModel('address', {
required: true,
default: 'myAddress'
})
</script>
如此简单
GitHub 加速计划 / vu / vue
207.54 K
33.66 K
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:2 个月前 )
73486cb5
* chore: fix link broken
Signed-off-by: snoppy <michaleli@foxmail.com>
* Update packages/template-compiler/README.md [skip ci]
---------
Signed-off-by: snoppy <michaleli@foxmail.com>
Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 4 个月前
e428d891
Updated Browser Compatibility reference. The previous currently returns HTTP 404. 5 个月前
更多推荐
已为社区贡献2条内容
所有评论(0)