在2023年12月28日,尤大发布了vue3.4
版本,这个版本主要对一些实验性特性的改进(比如defineModel
),大量重写了模板编译器并重构了响应式系统,可以说是大大提升了运行速度和效率。
之前在vue3.3中defineModel是实验特性,但vue3.4版本中已经是稳定特性了!!
不过在Vue3.4中,与之前的使用会有一些区别。
这个编译器宏,主要用于值的双向绑定上。(关于编译器宏的介绍:什么是编译器宏?)
props的设计原则是要符合单向数据流,所以不能直接修改props, 需要emit一个事件来告诉父组件,在父组件中修改。
举个栗子:父子组件的弹窗控制显示
1.最初进行值的双向绑定的写法
<!--子组件:EditForm.vue --> <template> <el-drawer v-model="visible" > ... </el-drawer> </template> <script setup lang="ts"> const props = withDefaults( defineProps<{ visible: boolean; }>(), { visible: false,//设置默认值,不然控制台会出现警告 }, ); const emit = defineEmits([ 'update:visible']); const visible = computed({ get: () => props.visible, set: () => emit('update:visible'), }); </script>
复制
<!-- 父组件 --> <EditForm ref="editFormRef" v-model:visible="state.editFormVisible"></EditForm>
复制
2.vue3.4之前
<!--子组件:EditForm.vue --> <template> <el-drawer v-model="visible" > ... </el-drawer> </template> <script setup lang="ts"> const visible = defineModel<boolean>('visible',{local:true});// local:true表示如果引用多个子组件,值不共享 </script>
复制
<!-- 父组件 --> <EditForm ref="editFormRef" v-model:visible="state.editFormVisible"></EditForm>
复制
3.vue3.4中
<!--子组件:EditForm.vue --> <el-drawer v-model="visible" > ... </el-drawer> <script> const visible = defineModel<boolean>('visible'); </script>
复制
<!-- 父组件 --> <EditForm ref="editFormRef" v-model:visible="state.editFormVisible"></EditForm>
复制
vue3.4中defineModel
中第二个配置项去掉了local
这个属性。目前options
可以传的的参数:
defineModel
中默认值是基本数据类型:
const inputValue = defineModel<string>({ default: '' });
复制
之前在vue3.4之前默认值是复杂数据类型的写法:
const drillFields = defineModel<string[]>('drillFields', { default: () => []) });
复制
vue3.4中defineModel
中默认值是复杂数据类型 (注意!!!)
const drillFields = defineModel<string[]>('drillFields', { get(val) { return reactive(val || []); }, }); const drillTitles = defineModel<string[]>('drillTitles', { get(val) { return reactive(val || []); }, });
复制
稳定版本的里面 defineModel 更类似是一个语法糖:
const foo = defineModel('foo'); // 上面的类似于: const props = defineProps(['foo']); const emits = defineEmits(['update:foo']);
复制
所以在子组件中操作defineModel中的值,比如像这种 foo.value.push(‘test’); 的代码就有问题,相当于直接:props.foo.push(‘test’)
vue3.4 还有一些其它比较大的变动可以查看:
https://blog.vuejs.org/posts/vue-3-4#other-removed-features(尤大博客原文)
https://blog.ninja-squad.com/2023/12/29/what-is-new-vue-3.4/
https://cn.vuejs.org/guide/components/v-model.html
https://cn.vuejs.org/api/sfc-script-setup.html#definemodel