Mixins
React Mixin通过将共享的方法包装成Mixins方法,然后注入各个组件来实现,官方已经不推荐使用,但仍然可以学习一下,了解为什么被遗弃。
React MiXin只能通过React.createClass()来使用,如下:
const mixinDefaultProps = {
}
const ExampleComponent = React.createClasss({
mixins: [mixinDefaultProps],
render: function(){
}
})
Mixins实现
import React from 'react'
var createReactClass = require('create-react-class')
const mixins = {
onMouseMove: function(e){
this.setState({
x: e.clientX,
y: e.clientY
})
}
}
const Mouse = createReactClass({
mixins: [mixins],
getInitialState: function() {
return {
x: 0,
y: 0
}
},
render() {
return (<div onMouseMove={
this.onMouseMove} style={
{
height: '300px'}}>
<p>the current mouse position is ({
this.state.x},{
this.state.y})</p>
</div>)
}
})
Mixins问题
- Mixins引入了隐式的依赖关系
你可能会写一个有状态的组件,然后你的同事可能添加一个读取这个组件state
的mixin
。几个月之后,你可能希望将该state
移动到父组件,以便与其兄弟组件共享。你会记得更新这个mixin
来读取props
而不是state
吗?如果此时,其它组件也在使用这个mixin
呢?
- Mixins引起名称冲突
无法保证两个特定的mixin
可以一起使用。例如,如果FluxListenerMixin
和WindowSizeMixin
都定义来handleChange()
,则不能一起使用它们。同时,你也无法在自己的组件上定义具有此名称的方法。
- Mixins导致滚雪球式的复杂性
每一个新的需求都使得mixins
更难理解。随着时间的推移,使用相同mixin
的组件变得越来越多。任何mixin
的新功能都被添加到使用该mixin
的所有组件。没有办法拆分mixin的“更简单”的部分,除非或者引入更多依赖性和间接性。逐渐,封装的边界被侵蚀,由于很难改变或者删除现有的mixins,它们不断变得更抽象,直到没有人了解它们如何工作。
高阶组件
高阶组件(HOC)是React中复用组件逻辑的一种高级技巧。HOC自身不是React API的一部分,它是一种基于React的组合特性而形成的设计模式。
高阶组件是参数为组件,返回值为新组件的函数
组件是将props
转换为UI
,而高阶组件是将组件转换为另一个组件。
const EnhancedComponent = higherOrderComponent(WrappedComponent)
HOC的实现
Props Proxy
: HOC对传给WrappedComponent的props进行操作Inheritance Inversion
HOC继承WrappedComponent,官方不推荐
Props Proxy
import React from 'react'
class Mouse extends React.Component {
render() {
const {
x, y } = this.props.mouse
return (
<p>The current mouse position is ({
x}, {
y})</p>
)
}
}
class Cat extends React.Component {
render() {
const {
x, y } = this.props.mouse
return (<div style={
{
position: 'absolute', left: x, top: y, backgroundColor: 'yellow',}}>i am a cat</div>)
}
}
const MouseHoc = (MouseComponent) => {
return class extends React.Component {
constructor(props) {
super(props)
this.state = {
x: 0,
y: 0
}
}
onMouseMove = (e) => {
this.setState({
x: e.clientX,
y: e.clientY
})
}
render() {
return (
<div style={
{
height: '300px'}} onMouseMove={
this.onMouseMove}>
<MouseComponent mouse={
this.state}/>
</div>
)
}
}
}
const WithCat = MouseHoc(Cat)
const WithMouse = MouseHoc(Mouse)
const MouseTracker = () => {
return (
<div>
<WithCat/>
<WithMouse/>
</div>
)
}
export default MouseTracker
请注意:HOC不会修改传入的组件,也不会使用继承来复制其行为。相反,HOC通过将组件包装在容器组件中来组成新组件。HOC是纯函数,没有副作用。
在Props Proxy模式下,我们可以做什么?
- 操作Props
在HOC里面可以对props进行增删改查操作,如下:
参考 React面试题详细解答
const MouseHoc = (MouseComponent, props) => {
props.text = props.text + '--I can operate props'
return class extends React.Component {
render() {
return (
<div style={
{
height: '100%' }} onMouseMove={
this.handleMouseMove}>
<MouseComponent {
...props} mouse={
this.state} />
</div>
)
}
}
MouseHoc(Mouse, {
text: 'some thing...'
})
- 通过Refs访问组件
const MouseHoc = (MouseComponent) => {
return class extends React.Component {
...
render() {
const props = {
...this.props, mouse: this.state }
return (
<div style={
{
height: '300px'}} onMouseMove={
this.onMouseMove}>
<MouseComponent {
...props}/>
</div>
)
}
}
}
class Mouse extends React.Component {
componentDidMounted() {
this.props.onRef(this)
}
render() {
const {
x, y } = this.props.mouse
return (
<p>The current mouse position is ({
x}, {
y})</p>
)
}
}
const WithMouse = MouseHoc(Mouse)
<