
Vue 与 React 有个非常明显的区别,就是 props 自带响应式,并混入 render 作用域
一方面这是针对“防止组件刷新”的性能优化,但是另一方面,也造成了响应式传递的负担
比如:
const [state,setState] = useState({})
<Child state={state} setState={setState}/>
<Child hook={[state,setState]}/>
在 react 中,响应式 hook 可以直接传递给子组件,注意这并非直接赋值的双向绑定,但是要注意的有两点:
- 如果 setState 有其他副作用,需要用 useEffect 处理
- 子组件没必要用 useMemo 包裹防止重绘,毕竟影响重绘的只是参数,做同一的参数对象也可以实现相同效果
但是明显,在 Vue 中这招不生效了
因为凡是传入 props 中的数据,不管是不是响应式数据(响应式也会拆包),都会自动进行变更检测,填充响应式
const state = ref({})
<Child state={state.value}/>
const name = ''
<Child name={name}/>
所以一旦你从响应式的开发范式着手,每次都会纠结于这样的设计,但是如果基于纯数据开发角度,又会丢掉响应式开发的优势,变得非常啰嗦和麻烦
怎么办?
依赖注入呗~
比如一个虚拟滚动组件,封装后只需要这样使用就可以了:
const virtualScroll = new VirtualScroll(arr);
virtualScroll.defaultHeight = 100;
return () => (
<VirtualContainer>
{virtualScroll.displayItems.map((el, key) => (
<div/>
))}
</VirtualContainer>
);
只有一个 VirtualContainer 组件,不需要你去传参数
为什么不需要传参呢?
因为只需要在相关服务的 constructor 中 :
class VirtualScroll {
// ...
constructor(){
// ...
provide('virtual-scroll', this)
}
}
就完成了服务注册
在组件中只需要:
const virtualScroll = inject("cdk-virtual-scroll")! as VirtualScroll;
就完成了服务注入,之后,该对象的所有属性,方法,都能很轻松地使用,尤其是搭配 Typescript 使用时
Vue 的依赖注入相比 React 要方便很多,毕竟 React 需要出现 Provider Element 才行,不过这也很方便在 类服务中直接声明服务提供商
换句话说,更方便支持面向对象
所以如果你觉得一个问题用组件参数处理起来非常麻烦,或者需要多组件多层级协作实现的话
放心好了,没有依赖注入解决不了的问题