美文网首页
React深入(一)

React深入(一)

作者: 老夫当年也是神一般的少年 | 来源:发表于2021-01-18 18:09 被阅读0次

    Context

    使用场景

    1. 为了解决props的繁琐传递问题,Context提供一种组件间共享值的方式,不必显示通过组件数逐层传递props;
    2. 很多不同层级的组件需要访问同样一些的数据,例如获取当前认证的用户、主题或首选语言,类似于全局缓存;
    3. Context有时候可由组件组合(component composition,即把组件当做props传递)代替。

    使用步骤

    1. 创建context:
      const ThemeContext = React.createContext({theme: 'light', text: '按钮'});
      ThemedButton.contextType = ThemeContext;

    2. 赋值context:
      <ThemeContext.Provider value={{theme: 'primary', text: '提交'}}>
      这里的value值可以传字符串,数字或者对象;
      如要更新context,可以通过更新state再把state传入context的方式实现。

    3. 渲染context:
      static contextType = ThemeContext;
      // React 会往上找到最近的 theme Provider,然后使用它的值。
      return <div className={'btn '+this.props.theme}>{this.props.value}</div>

      <ThemeContext.Consumer>
      {
      context => (
      <div className={'btn '+this.context.theme}>{this.context.text}</div>
      )
      }
      </ThemeContext.Consumer>

    4. context嵌套:
      <ThemeContext.Provider value={theme}>
      <UserContext.Provider value={signedInUser}>
      <Layout />
      </UserContext.Provider>
      </ThemeContext.Provider>

      // 一个组件可能会消费多个 context
      function Content() {
      return (
      <ThemeContext.Consumer>
      {theme => (
      <UserContext.Consumer>
      {user => (
      <ProfilePage user={user} theme={theme} />
      )}
      </UserContext.Consumer>
      )}
      </ThemeContext.Consumer>
      );

    Refs转发

    使用场景

    1. 需要将 ref 自动地通过组件传递到其一子组件;
    2. 父组件通过React.createRef()生成传入,子组件通过React.forwardRef((props, ref) => ())接收渲染。

    Fragments

    1. 一个组件返回多个元素。Fragments 允许你将子列表分组,而无需向 DOM 添加额外节点,
      如return (
      <React.Fragment>
      <ChildA />
      <ChildB />
      <ChildC />
      </React.Fragment>
      );
    2. 循环时key可以加在React.Fragment节点标签上。

    高阶组件(HOC)

    1. 高阶组件是参数为组件,返回值为新组件的函数。

    2. 使用方法:
      class ShowUserPermit extends React.Component {
      constructor(props) {
      super(props);
      }
      render() {
      return (
      <div>showUserPermit... {this.props.VIP}</div>
      )
      }
      }
      class ShowUserVipInfo extends React.Component {
      constructor(props) {
      super(props);
      }
      render() {
      return (
      <div>showUserVipInfo... {this.props.VIP}</div>
      )
      }
      }

      function wrap(WrappedComponent) {
      return class reComponent extends React.Component {
      constructor(props) {
      super(props);
      this.state = {
      VIP: 1000
      }
      }
      render() {
      return <WrappedComponent VIP={this.state.VIP}/>
      }
      }
      }

      const id = document.getElementById('example');
      const OtherShowUserVipInfo = wrap(ShowUserVipInfo);
      const OtherShowUserPermit = wrap(ShowUserVipInfo);
      const ele = <React.Fragment>
      <OtherShowUserVipInfo />
      <OtherShowUserPermit />
      </React.Fragment>
      ReactDOM.render(ele, id);

    3. HOC 不会修改传入的组件,也不会使用继承来复制其行为。相反,HOC 通过将组件包装在容器组件中来组成新组件。HOC 是纯函数,没有副作用;

    4. 不要在 render 方法中使用 HOC;

    深入JSX

    1. 在 JSX 类型中使用点语法:
      const MyComponents = {
      DatePicker: function DatePicker(props) {
      return <div>Imagine a {props.color} datepicker here.</div>;
      }
      }

      function BlueDatePicker() {
      return <MyComponents.DatePicker color="blue" />;
      }

    2. 用户定义的组件必须以大写字母开头;

    3. 在运行时选择类型:
      function Story(props) {
      // 错误!JSX 类型不能是一个表达式。
      return <components[props.storyType] story={props.story} />;
      }
      function Story(props) {
      // 正确!JSX 类型可以是大写字母开头的变量。
      const SpecificStory = components[props.storyType];
      return <SpecificStory story={props.story} />;
      }

    4. JavaScript 表达式可作为 Props,如<MyComponent foo={1 + 2 + 3 + 4} />;

    5. if 语句以及 for 循环不是 JavaScript 表达式,所以不能在 JSX 中直接使用,但是可以在JSX之外用;

    6. Props 默认值为 True

    7. props展开:
      const props = {firstName: 'Ben', lastName: 'Hector'};
      <Hello {...props}/> 与 <Hello firstName={props.firstName} lastName={props.lastName} />等价

    8. 如果你想渲染 false、true、null、undefined 等值,你需要先将它们转换为字符串:
      <div>My JavaScript variable is {String(myVariable)}.</div>

    Portals

    ReactDOM.createPortal(child, container)

    1. Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案;
    2. 第一个参数(child)是任何可渲染的 React 子元素,例如一个元素,字符串或 fragment。第二个参数(container)是一个 DOM 元素。

    Render Props

    1. 在 React 组件之间使用一个值为函数的 prop 共享代码的简单技术;
    2. 具有 render prop 的组件接受一个返回 React 元素的函数,并在组件内部通过调用此函数来实现自己的渲染逻辑:
      <DataProvider render={data => (<h1>{data.target}</h1>)}/>
    3. 本质上是把一个回调函数传入到组件里,通过回调函数的参数data再次渲染指定组件;
    4. 任何被用于告知组件需要渲染什么内容的函数 prop 在技术上都可以被称为 “render prop”,不一定非要起 render 名称;
    5. 实例代码如下:
      // 以下组件跟踪 Web 应用程序中的鼠标位置
      class Man extends React.Component {
      constructor(props) {
      super(props);
      }
      render() {
      const mouse = this.props.mouse;
      return <p>人散步:当前的人的位置是 ({mouse.x}, {mouse.y})</p>
      }
      }
      class Cat extends React.Component {
      constructor(props) {
      super(props);
      }
      render() {
      const mouse = this.props.mouse;
      return <p>猫追老鼠:当前的猫的位置是 ({mouse.x}, {mouse.y})</p>
      }
      }
      class Mouse extends React.Component {
      constructor (props) {
      super(props);
      this.state = {
      x: 0,
      y: 0
      };
      this.handleMouseMove = this.handleMouseMove.bind(this);
      }
      handleMouseMove(event) {
      this.setState({
      x: event.clientX,
      y: event.clientY
      });
      }
      render() {
      return (
      <div style={{height: '10vh'}} onMouseMove={this.handleMouseMove}>
      { /<Cat mouse={this.state}/>/ }
      {
      /*
      使用 renderprop 动态决定要渲染的内容,
      而不是给出一个 <Mouse> 渲染结果的静态表示
      b
      */
      }
      {
      this.props.render(this.state,this.props.type)
      }
      </div>
      )
      }
      }
      class MouseTracker extends React.Component {
      constructor(props) {
      super(props);
      this.renderMouse = this.renderMouse.bind(this);
      }
      renderMouse(mouse,Type) {
      return <Type mouse={mouse}/>
      }
      render() {
      return (
      <div>
      <h1>移动鼠标!</h1>
      <Mouse type={Cat} render={this.renderMouse}/>
      <Mouse type={Man} render={this.renderMouse}/>
      </div>
      )
      }
      }
      const id = document.getElementById('example');
      const ele = <React.Fragment>
      <MouseTracker />
      </React.Fragment>;
      ReactDOM.render(ele, id);

    相关文章

      网友评论

          本文标题:React深入(一)

          本文链接:https://www.haomeiwen.com/subject/lzbxzktx.html