写给vue转react的同志们(5)
写给vue转react的同志们(4)
我们知道 React 中使用高阶组件(下面简称HOC)来复用一些组件的逻辑。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式。具体而言,高阶组件是参数为组件,返回值为新组件的函数。
组件是将 props 转换为 UI,而高阶组件是将组件转换为另一个组件。
const EnhancedComponent = higherOrderComponent(WrappedComponent);
上面出自 React 官方文档。
那在 Vue 中 复用组件逻辑实际上比较简单,利用 Mixins 混入复用组件逻辑,当 Mixins 中的逻辑过多时(比如方法和属性),在项目当中使用时追述源代码会比较麻烦,因为他在混入后没有明确告诉你哪个方法是被复用的。
//mixins.js(Vue 2 举例)
export defalut {
data() {
return {
text: 'hello'
}
}
}
// a.vue
import mixins from './mixins.js'
export defalut {
mixins: [mixins]
computed: {
acitveText() {
return `来自mixins的数据:${this.text}`
}
}
}
复制代码
可以看到除了在开头引入并挂载混入,并没有看到this.text
是从哪里来的,混入虽然好用,但当逻辑复杂时,其阅读起来是有一定困难的。
那你想在 Vue 中强行使用像 React 那样的高阶组件呢?那当然可以。只是 Vue 官方不怎么推崇 HOC,且 Mixins 本身可以实现 HOC 相关功能。
简单举个例子:
// hoc.js
import Vue from 'Vue'
export default const HOC = (component, text) => {
return Vue.component('HOC', {
render(createElement) {
return createElement(component, {
on: { ...this.$listeners },
props: {
text: this.text
}
})
},
data() {
return {
text: text,
hocText: 'HOC'
}
},
mounted() {
// do something ...
console.log(this.text)
console.log(this.hocText)
}
})
}
使用高阶组件:
// user.vue
<template>
<userInfo/>
</template>
<script>
import HOC from './hoc.js'
// 引入某个组件
import xxx from './xxx'
const userInfo = HOC(xxx, 'hello')
export default {
name: 'user',
components: {
userInfo
}
}
</script>
是不是相比 Mixins 更加复杂一点了?在 Vue 中使用高阶组件所带来的收益相对于 Mixins 并没有质的变化。不过话又说回来,起初 React 也是使用 Mixins 来完成代码复用的,比如为了避免组件的非必要的重复渲染可以在组件中混入 PureRenderMixin
。
const PureRenderMixin = require('react-addons-pure-render-mixin')
const component = React.createClass({
mixins: [PureRenderMixin]
})
后来 React 使用shallowCompare
来 替代 PureRenderMixin
。
const shallowCompare = require('react-addons-shallow-compare')
const component = React.createClass({
shouldComponentUpdate: (nextProps, nextState) => {
return shallowCompare(nextProps, nextState)
}
})
这需要你自己在组件中实现 shouldComponentUpdate
方法,只不过这个方法具体的工作由 shallowCompare
帮你完成,我们只需调用即可。
再后来 React 为了避免总是要重复调用这段代码,React.PureComponent
应运而生,总之 React 在慢慢将 Mixins 脱离开来,这对他们的生态系统并不是特别的契合。当然每种方案都各有千秋,只是是否适合自己的框架。
那我们回归 HOC,在 React 中如何封装 HOC 呢?
实际上我在往期篇幅有提到过:
点击传送
但是我还是简单举个例子:
封装 HOC:
// hoc.js
export default const HOC = (WrappedComponent) => {
return Class newComponent extends WrappedComponent {
constructor(props) {
super(props)
// do something ...
this.state = {
text: 'hello'
}
}
componentDidMount() {
super.componentDidMount()
// do something ...
console.log('this.state.text')
}
render() {
// init render
return super.render()
}
}
}
使用 HOC:
// user.js
import HOC from './hoc.js'
class user extends React.Component {
// do something ...
}
export defalut HOC(user)
装饰器写法更为简洁:
import HOC from './hoc.js'
@HOC
class user extends React.Component {
// do something ...
}
export defalut user
可以看到无论 Vue 还是 React 亦或是 HOC 或 Mixins 他们都是为了解决组件逻辑复用应运而生的,具体使用哪一种方案还要看你的项目契合度等其他因素。
技术本身并无好坏,只是会随着时间推移被其他更适合的方案取代,技术迭代也是必然的,相信作为一个优秀的程序员也不会去讨论一个技术的好或坏,只有适合与否。
作者:饼干_
链接:https://juejin.cn/post/7020215941422137381