hi,你好!欢迎访问本站!登录
本站由简数采集腾讯云宝塔系统阿里云强势驱动
当前位置:首页 - 文章 - 后端开发 - 正文 看Cosplay古风插画小姐姐,合集图集打包下载:炫龙网 · 炫龙图库

【WEB前端开辟】4个开辟React运用的实用技巧

2019-11-27后端开发ki4网42°c
A+ A-

背景

Hooks 自推出以来就很火, 它改变了我们编写React 代码的体式格局, 有助于我们写更简约的代码。

本日这边文章不是说Hooks的,Hooks以外, 另有许多有用的技能可以协助我们编写简约清楚的代码。

本日我就整理了几个运用的技能,个中有些也是我在公司项目中实践的,如今整理出来分享给人人, 愿望对人人有所启示

正文

1. 运用字符串来定义一个React元素

举个简朴的例子:

// 我们可以经由过程把一个字符串'p' 赋值给一个变量, 就像:
import React from 'react'

const MyComponent = 'p'

function App() {
  return (
    <>
      <MyComponent>
        <h3>I am inside a {'<p />'} element</h3>
      </MyComponent>
    </>
  )
}

React 内部会挪用 React.createElement, 运用这个字符串来生成这个元素。

别的, 你也可以显式的定义component 来决议衬着的内容, 比方:

// 定义一个MyComponent
function MyComponent({ component: Component = 'p', name, age, email }) {
  
  return (
    <Component>
      <h1>Hi {name} </h1>
      <>
        <h6>You are {age} years old</h6>
        <small>Your email is {email}</small>
      </>
    </Component>
  )
}

实用体式格局:

function App() {
  return (
    <>
      <MyComponent component="p" name="KK" age={18} email="xxx@gmail.com">
    </>
  )
}

这类体式格局, 你也可以传入一个自定义的组件, 比方:

function Dashboard({ children }) {
  return (
    <p style={{ padding: '25px 12px' }}>
      {children}
    </p>
  )
}

function App() {
  return (
    <>
      <MyComponent component={Dashboard} name="KK" age={18} email="xxx@gmail.com">
    </>
  )
}

假如你碰到处置惩罚一类相似的元素也许组件,可以经由过程这类自定义的体式格局笼统出来,简化你的代码。

举个实际的例子:

比方我们如今要做一个货色打包的需求, 可以单个打, 也可以批量打, 针对共同点可以写自定义组件:

import React from 'react'
import withTranslate from '@components/withTranslate'
import PackComponent from './PackComponent'
import usePack, { check } from './usePack'

let PackEditor = (props) => {
  const packRes = usePack(props)
  return (
    <PackComponent
      {...packRes}
    />
  )
}

PackEditor = withTranslate(PackEditor)
PackEditor.check = check

export default PackEditor

如许在差别的营业模块中, 就可以天真的运用了, 非常轻易。

2. 定义毛病边境

在Javascript里,我们都是运用 try/catch 来捕获可以发生的非常,在catch中处置惩罚毛病。 比方:

function getFromLocalStorage(key, value) {
  try {
    const data = window.localStorage.get(key)
    return JSON.parse(data)
  } catch (error) {
    console.error
  }
}

如许, 即使发生了毛病, 我们的运用也不至于崩溃白屏。

React 归根结柢也是Javascript,本质上没什么差别, 所以一样的运用try/catch 也没有题目。

但是, 由于React 完成机制的缘由, 发生在组件内部的Javascript 毛病会损坏内部状况, render会发生毛病:

https://github.com/facebook/react/issues/4026

基于以上缘由,React 团队引入了Error Boundaries:

https://reactjs.org/docs/error-boundaries.html

Error boundaries, 实在就是React组件, 你可以用找个组件来处置惩罚它捕获到的任何毛病信息。

当组件树崩溃的时刻,也可以显现你自定义的UI,作为回退。

看 React 官方供应的例子:
https://reactjs.org/docs/error-boundaries.html#introducing-error-boundaries

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props)
    this.state = { hasError: false }
  }
  
  static getDerivedStateFromError(error) {
    // Update state so the next render will show the fallback UI.
    return { hasError: true }
  }
  
  componentDidCatch(error, errorInfo) {
    // You can also log the error to an error reporting service
    logErrorToMyService(error, errorInfo)
  }
  
  render() {
    if (this.state.hasError) {
      // You can render any custom fallback UI
      return <h1>Something went wrong.</h1>
    }
    return this.props.children
  }
}

运用体式格局:

<ErrorBoundary>
  <MyWidget />
</ErrorBoundary>

Live Demo By Dan Abramov:

https://codepen.io/gaearon/pen/wqvxGa?editors=0010

3.高阶组件

浅显点讲, 所谓高阶组件就是, 你丢一个组件进去, 增添一些属性或操纵, 再丢出来。

一般来说, 你可以把一些具有共同点的组件笼统成一个高阶组件, 然后再差别的模块中复用

比方, 我们的体系中, 有一类按钮要加个border, 许多处所都要用到, 我们把它笼统出来:

import React from 'react'

// Higher order component
const withBorder = (Component, customStyle) => {
  class WithBorder extends React.Component {
    render() {
      const style = {
        border: this.props.customStyle ? this.props.customStyle.border : '3px solid teal'
      }
      return <Component style={style} {...this.props} />
    }
  }
  
  return WithBorder
}

function MyComponent({ style, ...rest }) {
  return (
    <p style={style} {...rest}>
        <h2>
          This is my component and I am expecting some styles.
        </h2>
    </p>
  )
}

export default withBorder(MyComponent, { border: '4px solid teal' })

经由withBorder装潢的MyComponent组件, 就具有了一致border这项功用, 背面假如假如要做修正, 就可以在这个中间层一致处置惩罚, 非常轻易。

在我的项目里, 也用了一些高阶组件, 举个细致的例子:

PackEditor = withTranslate(PackEditor)

我们的这个 PackEditor 就是一个增强过的组件, 增添了什么功用呢?

正如名字表述的, withTranslate, 增添了一个翻译功用, 下面也给人人看看这个组件是怎样完成的:

import React from 'react'
import { Provider } from 'react-redux'
import { injectIntl } from 'react-intl'
import { store } from '@redux/store'
import { Intl } from './Locale'

const withTranslate = BaseComponent => (props) => {
  // avoid create a new component on re-render
  const IntlComponent = React.useMemo(() => injectIntl(
    ({ intl, ...others }) => (
      <BaseComponent
        intl={intl}
        translate={(id, values = {}) => { // 注入翻译要领
          if (!id) { return '' }
          return intl.formatMessage(
            typeof id === 'string' ? { id } : id,
            values
          )
        }}
        {...others}
      />
    )
  ), [])

  IntlComponent.displayName = `withTranslate(${BaseComponent.displayName || 'BaseComponent'})`
  
  return (
    <Provider store={store}>
      <Intl>
        <IntlComponent
          {...props}
        />
      </Intl>
    </Provider>
  )
}

export default withTranslate

用法很灵过:

const Editor = withTranslate(({
  // ...
  translate,
}) => {
  // ...
   return (
     <>
      {translate('xxx')}}
     </>
   )
})

非常的轻易。

4. Render props

Rrender prop 是指一种在 React 组件之间运用一个值为函数的 prop 同享代码的简朴手艺, 和 HOC 相似, 都是组件间的逻辑复用题目

更细致地说,Render prop 是一个用于示知组件须要衬着什么内容的函数。

下面看一下简朴的例子:

以下组件跟踪 Web 运用程序中的鼠标位置:

class Mouse extends React.Component {
  state = { x: 0, y: 0 };

  handleMouseMove = (event) => {
    this.setState({
      x: event.clientX,
      y: event.clientY
    });
  }

  render() {
    return (
      <p style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>
        <p>The current mouse position is ({this.state.x}, {this.state.y})</p>
      </p>
    );
  }
}

class MouseTracker extends React.Component {
  render() {
    return (
      <>
        <h1>挪动鼠标!</h1>
        <Mouse />
      </>
    );
  }
}

当光标在屏幕上挪动时,组件显现其(x,y)坐标。

如今的题目是:

我们如安在另一个组件中复用这个行动?

换个说法,若另一个组件须要晓得鼠标位置,我们可否封装这一行动,以便轻松地与其他组件同享它 ??

假定产物想要如许一个功用: 在屏幕上显现一张在屏幕上追逐鼠标的猫的图片。

我们也许会运用 <Cat mouse={{ x, y }} prop 来通知组件鼠标的坐标以让它晓得图片应该在屏幕哪一个位置。

class Cat extends React.Component {
  render() {
    const mouse = this.props.mouse;
    return (
      <img src="/cat.jpg" style={{ position: 'absolute', left: mouse.x, top: mouse.y }} />
    );
  }
}

这个需求云云简朴,你可以就直接修正Mouse组件了:

class Mouse extends React.Component {
  state = { x: 0, y: 0 };

  handleMouseMove = (event) => {
    this.setState({
      x: event.clientX,
      y: event.clientY
    });
  }

  render() {
    return (
      <p style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>
        <Cat mouse={this.state} />
      </p>
    );
  }
}

巴适~ 简朴粗犷, 一分钟完成任务。

但是,假如下次产物再要想加条狗呢

以上的例子,虽然可以完成了猫追鼠标的需求,还没有到达以可复用的体式格局真正封装行动的目的。

当我们想要鼠标位置用于差别的用例时,我们必需建立一个新的组件,特地为该用例显现一些东西.

这也是 render prop 的来源:

我们可以供应一个带有函数 prop 的 <Mouse> 组件,它可以动态决议什么须要衬着的,而不是将 <Cat> 硬编码到 <Mouse> 组件里.

修正一下上面的代码:

class Cat extends React.Component {
  render() {
    const mouse = this.props.mouse;
    return (
      <img src="/cat.jpg" style={{ position: 'absolute', left: mouse.x, top: mouse.y }} />
    );
  }
}

class Mouse extends React.Component {
  state = { x: 0, y: 0 };

  handleMouseMove = (event) => {
    this.setState({
      x: event.clientX,
      y: event.clientY
    });
  }

  render() {
    return (
      <p style={{ height: '100%' }} onMouseMove={this.handleMouseMove}>
        {this.props.render(this.state)}
      </p>
    );
  }
}

class MouseTracker extends React.Component {
  render() {
    return (
      <p>
        <h1>挪动鼠标!</h1>
        <Mouse render={mouse => (
          <Cat mouse={mouse} />
        )}/>
      </p>
    );
  }
}

供应了一个render 要领,让动态决议什么须要衬着。

事实上,render prop 是由于形式才被称为 render prop ,不一定要用名为 render 的 prop 来运用这类形式。

任何被用于示知组件须要衬着什么内容的函数 prop, 在手艺上都可以被称为 "render prop".

别的,关于 render prop 一个风趣的事变是你可以运用带有 render prop 的通例组件来完成大多数高阶组件 (HOC)。

比方,假如你更喜好运用 withMouse HOC 而不是 <Mouse> 组件,你可以运用带有 render prop 的通例 <Mouse> 轻松建立一个:

function withMouse(Component) {
  return class extends React.Component {
    render() {
      return (
        <Mouse render={mouse => (
          <Component {...this.props} mouse={mouse} />
        )}/>
      );
    }
  }
}

也是非常的简约清楚。

有一点须要注重的是, 假如你在定义的render函数里建立函数, 运用 render prop 会抵消运用 React.PureComponent 带来的上风。

由于浅比较 props 的时刻总会获得 false,并且在这类情况下每一个 render 关于 render prop 将会生成一个新的值

class Mouse extends React.PureComponent {
  // 与上面雷同的代码......
}

class MouseTracker extends React.Component {
  render() {
    return (
      <>
        <Mouse render={mouse => ( // 这是不好的! 每一个衬着的 `render` prop的值将会是差别的。
          <Cat mouse={mouse} />
        )}/>
      </>
    );
  }
}

在如许例子中,每次 <MouseTracker> 衬着,它会生成一个新的函数作为 <Mouse render> 的 prop,因而在同时也抵消了继续自 React.PureComponent 的 <Mouse> 组件的结果.

为了绕过这一题目,偶然你可以定义一个 prop 作为实例要领,相似如许:

class MouseTracker extends React.Component {
  renderTheCat(mouse) {
    return <Cat mouse={mouse} />;
  }

  render() {
    return (
      <p>
        <h1>Move the mouse around!</h1>
        <Mouse render={this.renderTheCat} />
      </p>
    );
  }
}

5.组件机能

机能优化是永久的主题, 这里不逐一细说, 供应积分资本供你参考:

  • React.memo https://reactjs.org/docs/reac...
  • React.useMemo https://flaviocopes.com/react...
  • React.useCallback https://reactjs.org/docs/hook...
  • React.PureComponent https://reactjs.org/docs/reac...
  • Optimizing performance https://reactjs.org/docs/opti...

总结

以上几点都是我们常常要运用的技能, 简朴有用, 分享给人人, 愿望能给人人带来一些协助或启示,感谢。

引荐浏览:React在线手册

以上就是4个开辟React运用的有用技能的细致内容,更多请关注ki4网别的相干文章!

  选择打赏方式
微信赞助

打赏

QQ钱包

打赏

支付宝赞助

打赏

  选择分享方式
  移步手机端
【WEB前端开辟】4个开辟React运用的实用技巧

1、打开你手机的二维码扫描APP
2、扫描左则的二维码
3、点击扫描获得的网址
4、可以在手机端阅读此文章

发表评论

选填

必填

必填

选填

请拖动滑块解锁
>>