理解 Vue3 里的 defineProps 和 defineEmits


大家请先看这个问题:https://segmentfault.com/q/1010000041497872/a-1020000041498716,看看你们能不能给出答案。

Vue3 增加了 Composition API,是一个很大的改进。一方面可以提升代码复用效率,另一方面通过更好的 tree-shaking,打包体积也会小很多:作为参考,前面博客中提到 mywordle.org,打包后 vendor.js 只有区区 96kB,里面可是用到了 vue3 全家桶。

最初的 Composition API 是在 Options API 基础上改进的,不仅需要使用 setup() 函数,还要在 setup() 末尾返回所有模版需要用到的变量和函数,使用起来相当繁琐。于是后面就增加了 <script setup> 语法糖:

  1. 从生命周期来讲,相当于 created
  2. 支持顶层 await(因为实际上这还是个 setup() 函数)
  3. 所有 import 的内容、声明的变量和函数默认都返回
  4. 至少省了两层缩进

但是由于少了 export,没法传参,也不方便暴露接口,所以作者就增加了三个工具方法:

  • defineProps
  • defineEmits
  • defineExpose

注意,这三个工具方法只是帮助 Vue 编译器构建组件,它们不会出现在最终代码里,我们也不能预期它们会像普通函数那样工作。比如下面这段代码,就得不到常见的结果:

const props = defineProps({
  userMenu: {
    type: Array,
    default() {
      return []
    }
  }
})
console.log(props) // 该对象中的 userName 总是有值
console.log(props.userMenu) // 该对象始终是一个空数据

因为 Vue 是 MVVM 框架,它的视图会在数据变化后自动渲染,于是通常情况下,props 里的值什么时候被填充并不重要,Vue 开发团队也不想追求 defineProps 工作的一般化。所以使用目前版本,上面这段代码,访问到的 props 是的 reactive 对象,数据被填充后就能看到 userName 里有值;而 props.userMenu 在访问时还没有被填充,所以得到的是 default() 返回的默认值,一直是空的。

同时大家还要知道,console.log() 输出的是对象的指针,而非快照。所以里面的值只跟你展开时有关,跟运行时关系不大。


欢迎吐槽,共同进步

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

%d 博主赞过: