在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
任何一个项目发展到一定复杂性的时候,必然会面临逻辑复用的问题。在 Mixin这或许是刚从 广义的 mixin 方法,就是用赋值的方式将 mixin 对象中的方法都挂载到原对象上,来实现对象的混入,类似 ES6 中的 Object.assign()的作用。原理如下: const mixin = function (obj, mixins) { const newObj = obj newObj.prototype = Object.create(obj.prototype) for (let prop in mixins) { // 遍历mixins的属性 if (mixins.hasOwnPrototype(prop)) { // 判断是否为mixin的自身属性 newObj.prototype[prop] = mixins[prop]; // 赋值 } } return newObj }; 在 React 中使用 Mixin假设在我们的项目中,多个组件都需要设置默认的 const DefaultNameMixin = { getDefaultProps: function () { return { name: "Joy" } } } 为了使用 const ComponentOne = React.createClass({ mixins: [DefaultNameMixin] render: function () { return <h2>Hello {this.props.name}</h2> } }) 写好的 由于 const DefaultFriendMixin = { getDefaultProps: function () { return { friend: "Yummy" } } } const ComponentOne = React.createClass({ mixins: [DefaultNameMixin, DefaultFriendMixin] render: function () { return ( <div> <h2>Hello {this.props.name}</h2> <h2>This is my friend {this.props.friend}</h2> </div> ) } }) 我们甚至可以在一个 比如写一个新的 const DefaultPropsMixin = { mixins: [DefaultNameMixin, DefaultFriendMixin] } const ComponentOne = React.createClass({ mixins: [DefaultPropsMixin] render: function () { return ( <div> <h2>Hello {this.props.name}</h2> <h2>This is my friend {this.props.friend}</h2> </div> ) } }) 至此,我们可以总结出
但是在不同场景下,优势也可能变成劣势:
除此之外, 高阶组件由于
默认情况下,必须是经过
const withRouter = (Component) => { const displayName = `withRouter(${Component.displayName || Component.name})` const C = props => { const { wrappedComponentRef, ...remainingProps } = props return ( <RouterContext.Consumer> {context => { invariant( context, `You should not use <${displayName} /> outside a <Router>` ); return ( <Component {...remainingProps} {...context} ref={wrappedComponentRef} /> ) }} </RouterContext.Consumer> ) } 使用代码: import React, { Component } from "react" import { withRouter } from "react-router" class TopHeader extends Component { render() { return ( <div> 导航栏 {/* 点击跳转login */} <button onClick={this.exit}>退出</button> </div> ) } exit = () => { // 经过withRouter高阶函数包裹,就可以使用this.props进行跳转操作 this.props.history.push("/login") } } // 使用withRouter包裹组件,返回history,location等 export default withRouter(TopHeader) 由于 例如: 写一个赋能唱歌的高阶函数 import React, { Component } from 'react' const widthSinging = WrappedComponent => { return class HOC extends Component { constructor () { super(...arguments) this.singing = this.singing.bind(this) } singing = () => { console.log('i am singing!') } render() { return <WrappedComponent /> } } } 写一个赋能跳舞的高阶函数 import React, { Component } from 'react' const widthDancing = WrappedComponent => { return class HOC extends Component { constructor () { super(...arguments) this.dancing = this.dancing.bind(this) } dancing = () => { console.log('i am dancing!') } render() { return <WrappedComponent /> } } } 使用以上高阶组件 import React, { Component } from "react" import { widthSing, widthDancing } from "hocs" class Joy extends Component { render() { return <div>Joy</div> } } // 给Joy赋能唱歌和跳舞的特长 export default widthSinging(withDancing(Joy)) 由上可见,只需使用高阶函数进行简单的包裹,就可以把原本单纯的 Joy 变成一个既能唱歌又能跳舞的夜店小王子了! 使用 HOC 的约定
HOC 的优缺点至此我们可以总结一下
当然
Render Props
The term “render prop” refers to a technique for sharing code between React components using a prop whose value is a function. 这是 官方示例: <DataProvider render={(data) => <h1>Hello {data.target}</h1>} /> 如上, 读者或许会疑惑,“我们为什么需要调用
我们在项目开发中可能需要频繁的用到弹窗,弹窗 UI 可以千变万化,但是功能却是类似的,即 import { Modal, Button } from "antd" class App extends React.Component { state = { visible: false } // 控制弹窗显示隐藏 toggleModal = (visible) => { this.setState({ visible }) }; handleOk = (e) => { // 做点什么 this.setState({ visible: false }) } render() { const { visible } = this.state return ( <div> <Button onClick={this.toggleModal.bind(this, true)}>Open</Button> <Modal title="Basic Modal" visible={visible} onOk={this.handleOk} onCancel={this.toggleModal.bind(this, false)} > <p>Some contents...</p> </Modal> </div> ) } } 以上是最简单的 <MyModal> <Button>Open</Button> <Modal title="Basic Modal" onOk={this.handleOk}> <p>Some contents...</p> </Modal> </MyModal> 可以通过 import { Modal, Button } from "antd" class MyModal extends React.Component { state = { on: false } toggle = () => { this.setState({ on: !this.state.on }) } renderButton = (props) => <Button {...props} onClick={this.toggle} /> renderModal = ({ onOK, ...rest }) => ( <Modal {...rest} visible={this.state.on} onOk={() => { onOK && onOK() this.toggle() }} onCancel={this.toggle} /> ) render() { return this.props.children({ Button: this.renderButton, Modal: this.renderModal }) } } 这样我们就完成了一个具备状态和基础功能的 以上可以看出,
在 比如: // 不好的示例 class MouseTracker extends React.Component { render() { return ( <Mouse render={mouse => ( <Cat mouse={mouse} /> )}/> ) } } 这样写是不好的,因为 所以更好的写法应该是将传入 // 好的示例 class MouseTracker extends React.Component { renderCat(mouse) { return <Cat mouse={mouse} /> } render() { return ( <Mouse render={this.renderTheCat} /> ) } }
优点
缺点
如下代码: const MyComponent = () => { return ( <Mouse> {({ x, y }) => ( <Page> {({ x: pageX, y: pageY }) => ( <Connection> {({ api }) => { // yikes }} </Connection> )} </Page> )} </Mouse> ) } Hook
而 React Hooks 的设计目的,就是加强版函数组件,完全不使用"类",就能写出一个全功能的组件。 为什么说 import React, { Component } from "react" export default class Button extends Component { constructor() { super() this.state = { buttonText: "Click me, please" } this.handleClick = this.handleClick.bind(this) } handleClick() { this.setState(() => { return { buttonText: "Thanks, been clicked!" } }) } render() { const { buttonText } = this.state return <button onClick={this.handleClick}>{buttonText}</button> } } 以上是一个简单的按钮组件,包含最基础的状态和点击方法,点击按钮后状态发生改变。 本是很简单的功能组件,但是却需要大量的代码去实现。由于 import React, { useState } from "react" export default function Button() { const [buttonText, setButtonText] = useState("Click me, please") function handleClick() { return setButtonText("Thanks, been clicked!") } return <button onClick={handleClick}>{buttonText}</button> } 相较而言, 在上述例子中引入了第一个钩子
Hook 优缺点优点
缺点
总结除了 参考文档: 到此这篇关于React 代码共享最佳实践方式的文章就介绍到这了,更多相关React 代码共享内容请搜索极客世界以前的文章或继续浏览下面的相关文章希望大家以后多多支持极客世界! |
请发表评论