关于vue组件通信的疑惑

子组件传递数据给父组件有一种办法是通过子组件触发$emit来实现。
但是像react一样,通过props把父组件的方法作为属性传递给子组件,子组件直接调用父组件方法也能实现数据传递。为什么我看了很多文章,都没有这种写法,是有什么缺陷吗?

阅读 4.3k
5 个回答

原因其实就是 Vue 把事件监听单独从 props 里摘了出来,而 React 把 event handler 当作 props 看一视同仁,其实不光 event hanlder 是 props,children 也可以用 props 语法绑定, ref 更加独特。(这里真是要吐槽,一切皆 props 这玩意儿就很迷 <C children={'1'}>2</C> ref 还单独处理)

Vue 下你完全可以弃用 $emit 那一套,组件间事件改用 props 来传递,只是最终的 DOM 事件你不得不用 Vue 的语法。但既然 Vue 有单独的处理机制,个人觉得那就最好遵从 Vue 的规范。

下面来说说两种方案的优缺点。

Vue 的方案优点
  • 事件可以看做组件的输出接口,和作为输入的 props 分开处理,使用时也需要用不同的语法,让人一眼便识别,更加清晰明确。而 React 使用相同的 <C prop={value} onClick={handleClick}/> 语法, 需要依赖命名约定才能知道是输入还是输出。
  • 组件触发事件时不用关心使用者是否绑定了此事件。而 React 中组件并不存在自定义事件的概念,组件有的只是 props,虽然 ?.() 语法一定程度上缓解了问题,但是心智负担还是在的。
  • Event modifier 用起来还是很香的。而 React 将事件混在 props 中是享受不到这种语法糖的快乐,达不到 @click.prevent='handleClick' 这种优雅程度。
  • 保留了动态绑定事件 $on / $off 的能力
React 方案的优点
  • 不需要额外的语法和概念,组件对外就只有 props,至于 props 里要放什么你自己决定,callback只是刚好可以模拟事件这个概念。
  • 适配 Typescript 简直 easy。反正事件接口只是函数类型的 props,定义 type 顺理成章。反观 Vue,不说事件回调如何上 typescript,如果 $emit 乱飞的话,你打开一个复杂组件的代码,都不知道它一共能产生多少种事件,更别提一眼看出每种事件需要 emit 什么样的数据。所以 Vue3 里事件这块必然要动刀才能上 typescript 。

其实是都可以的,只是从父组件层面去理解的化,等待一个事件显得更直观罢了。
如果传递一个method下去,光看父组件你是不知道这个method子组件用来做什么,也许是可变的计算方法,也许是传递额外的属性,也许是用于返回数据。

看是什么方法了,如果就是暴露给父组件的 API 方法,那可以,比如很多 Dialog 组件都可以这么传参,比如是 this.$refs['dialog'].open({ title: '标题', content: '正文', callback: () => {} });。你说这个 callback 是不是变成事件、子组件用 $emit 传递、父组件用 @callback= 接收也行?

如果是一个子组件内部自己用的方法,那就是反模式了。

因为实际上父组件是不应该知道子组件的内部实现细节的(包括 datacomputedwatchmethod、生命周期这些),只应该通过暴露的 props 来使用子组件。

要怪就怪在 JS 这弱鸡语言没法设成员作用域(# 修饰私有成员的这个提案还没有哪个浏览器支持),要是能明确知道哪些成员是 private 的、哪些是 public 的,这个问题也就很好解决了。凡是 public 的,你就放心调;凡是 private 的,你想调也调不到,直接抛异常了就。


P.S. Vue 3 + TypeScript 能一定程度上缓解上面的问题。

子组件传数据给父组件,实质上有两个过程:
1.子组件自身触发影响到父组件的数据
2.父组件数据受到子组件影响
所以是通过 emit,让子组件自身参与这个过程。如果,直接把 method 给子组件,子组件再调用这个 method,那么子组件自身在这个过程,本质是没有参与的。

这不是缺陷不缺陷的问题,是解决具体问题的实现策略不同而已。同样一个回调,有可能是用if去写,也有可能是用switch去写,还有可能通过for去写,写法本来就是很随意的,看你自己更偏好哪一种,写框架的也是人,是人就有自己的偏好,但偏好是没有对错的,只是看你更喜欢哪种而已,合适就好。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题