子组件传递数据给父组件有一种办法是通过子组件触发$emit来实现。
但是像react一样,通过props把父组件的方法作为属性传递给子组件,子组件直接调用父组件方法也能实现数据传递。为什么我看了很多文章,都没有这种写法,是有什么缺陷吗?
子组件传递数据给父组件有一种办法是通过子组件触发$emit来实现。
但是像react一样,通过props把父组件的方法作为属性传递给子组件,子组件直接调用父组件方法也能实现数据传递。为什么我看了很多文章,都没有这种写法,是有什么缺陷吗?
其实是都可以的,只是从父组件层面去理解的化,等待一个事件显得更直观罢了。
如果传递一个method下去,光看父组件你是不知道这个method子组件用来做什么,也许是可变的计算方法,也许是传递额外的属性,也许是用于返回数据。
看是什么方法了,如果就是暴露给父组件的 API 方法,那可以,比如很多 Dialog 组件都可以这么传参,比如是 this.$refs['dialog'].open({ title: '标题', content: '正文', callback: () => {} });
。你说这个 callback
是不是变成事件、子组件用 $emit
传递、父组件用 @callback=
接收也行?
如果是一个子组件内部自己用的方法,那就是反模式了。
因为实际上父组件是不应该知道子组件的内部实现细节的(包括 data
、computed
、watch
、method
、生命周期这些),只应该通过暴露的 props 来使用子组件。
要怪就怪在 JS 这弱鸡语言没法设成员作用域(#
修饰私有成员的这个提案还没有哪个浏览器支持),要是能明确知道哪些成员是 private
的、哪些是 public
的,这个问题也就很好解决了。凡是 public
的,你就放心调;凡是 private
的,你想调也调不到,直接抛异常了就。
P.S. Vue 3 + TypeScript 能一定程度上缓解上面的问题。
子组件传数据给父组件,实质上有两个过程:
1.子组件自身触发影响到父组件的数据
2.父组件数据受到子组件影响
所以是通过 emit
,让子组件自身参与这个过程。如果,直接把 method
给子组件,子组件再调用这个 method
,那么子组件自身在这个过程,本质是没有参与的。
这不是缺陷不缺陷的问题,是解决具体问题的实现策略不同而已。同样一个回调,有可能是用if去写,也有可能是用switch去写,还有可能通过for去写,写法本来就是很随意的,看你自己更偏好哪一种,写框架的也是人,是人就有自己的偏好,但偏好是没有对错的,只是看你更喜欢哪种而已,合适就好。
10 回答11.1k 阅读
6 回答3k 阅读
5 回答4.8k 阅读✓ 已解决
4 回答3.1k 阅读✓ 已解决
2 回答2.6k 阅读✓ 已解决
3 回答5.1k 阅读✓ 已解决
3 回答1.8k 阅读✓ 已解决
原因其实就是 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 的方案优点
<C prop={value} onClick={handleClick}/>
语法, 需要依赖命名约定才能知道是输入还是输出。?.()
语法一定程度上缓解了问题,但是心智负担还是在的。@click.prevent='handleClick'
这种优雅程度。$on
/$off
的能力React 方案的优点