likes
comments
collection
share

vue实现model新方式:defineModel为啥要用defineModel v-model作为vue提供的用于实现

作者站长头像
站长
· 阅读数 25

为啥要用defineModel

v-model作为vue提供的用于实现双向绑定的指令,大大简化了我们的工作,不需要写<Child :modelValue="value" @update:modelValue="(payload) => value = payload" />这么一长串,只要<Child v-model="value" />就行了。在子组件内部,需要定义props和emits的,父子组件通信还是靠这套。

Vue 3.4开始,出现了一种新写法:defineModel,这也是官方推荐的实现方式:

vue实现model新方式:defineModel为啥要用defineModel v-model作为vue提供的用于实现 其实,最主要的还是defineModel可以简化我们的代码。

新与旧的比较

通常情况下,我们在自定义组件中使用v-model有2种情况:1. 自定义的Modal/Dialog 2. 自定义的表单组件。这2种其实也可以归为一类,就是第三方的组件(UI库)上使用了v-model,我们基于它们实现自己的组件时,也会使用v-model实现显示/隐藏、数据绑定这些。

以Modal/Dialog为例,web端的SaaS系统中,添加、修改这些功能是十分常见的:一个模态框,内容部分是表单。除了表单项很少的情况下,比如只有2、3项,会直接写在当前页面中;大部分情况下都是单独使用一个子组件实现。

之前如何写

// 父组件
<ChildModal v-model="visible" /> 

子组件中,需要使用definePropsdefineEmits来分别定义props和event:

// ChildModal
const props = defineProps({
  modelValue: {
    type: String,
    default: false
  }
})
const emit = defineEmits<{
  (e: 'update:modelVal', visible: boolean): void
}>()

传过来的modelValue不能直接使用在Modal/Dialog的v-model上,根据单项数据流的原则,我们要修改props,必须通过emit自定义事件(虽然当某个prop是Object时,直接修改也不会报错,也能实现我们想要的结果)。所以通常我们还得用computed处理下:

// ChildModal
const visible = computed({
  get: () => props.modelValue,
  set: (val: boolean) => emit('update:modelValue', val)
})

defineModel写法

虽然之上的实现方式并没有很麻烦,但是defineModel更加的简单:const model = defineModel(),然后直接用这个model就可以了,我们不需要再去定义props、emits,使用computed/watch跟随变化,它自动会帮我们处理,这样是不是就简单多了。

vue实现model新方式:defineModel为啥要用defineModel v-model作为vue提供的用于实现 定义类型和默认值也很简单:defineModel({type: String, default: ''})或者defineModel<string>({ default: '' })。选项和定义props是一样的,毕竟defineModel只是一个便利宏,内部实现还是声明props、emits、watch这些,传递的选项肯定就和定义props一样了,毕竟就是给props用的。

vue实现model新方式:defineModel为啥要用defineModel v-model作为vue提供的用于实现 参数写法:比如参数是visible,就是这样:defineModel('visible', {type: Boolean, default: false}),父组件中使用没啥变化v-model:visible多个v-model绑定,就只是多写几个defineModel而已,和单个没啥区别 修饰符

// 官网
const [model, modifiers] = defineModel()
console.log(modifiers) // { capitalize: true }
const [model, modifiers] = defineModel({
  set(value) {
    if (modifiers.capitalize) {
      return value.charAt(0).toUpperCase() + value.slice(1)
    }
    return value
  }
})

官网:cn.vuejs.org/guide/compo…

最后

vue3.4开始,defineModel就是官方推荐的写法了,新项目中(最新版本已经3.5.8了)赶紧用起来,省出来的时间都是自己的😏。还有vue3.5的props解构,方便了使用的同时,也感觉特性越来越多,咋整呢...

转载自:https://juejin.cn/post/7418065939347980323
评论
请登录