最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • React16后一些重要的API和概念

    正文概述 掘金(Jack_Huang)   2021-01-25   583

    1. 组合和继承

    React 有十分强大的组合模式。React推荐我们使用组合而非继承来实现组件间的代码重用。 通过 JSX 嵌套,实现组件之间的组合。

    // 渲染模板
    function FancyBorder(props) {
      return (
        <div className={'FancyBorder FancyBorder-' + props.color}>
          {props.children}
        </div>
      );
    }
    // 传递数据
    function WelcomeDialog() {
      return (
        <FancyBorder color="blue">
          <h1 className="Dialog-title">
            Welcome
          </h1>
          <p className="Dialog-message">
            Thank you for visiting our spacecraft!
          </p>
        </FancyBorder>
      );
    }
    

    2. Context

    Context 灵魂三拷问?

    Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。

    // App.js
    import React from 'react';
    import Parent from './Parent'
    export const {Provider, Consumer} = React.createContext();
    export function App() {
      return (
          <Provider value={'li'}>
            <Parent/>
          </Provider>
          );
    }
    
    // Parent.js
    import React from 'react';
    import Child from './Child'
    class Parent extends React.Component {
        render() {
            return <Child/>
        }
    }
    export default Parent;
    
    // Child.js
    import React from 'react';
    import {Consumer} from './App'
    class Child extends React.Component {
        render() {
            return (
                <div>
                    <Consumer>
                        {
                            theme => <div>{theme}</div>
                        }
                    </Consumer>
                </div>
            )
        }
    }
    export default Child;
    
    • ContextType

    Context会让组件变得不纯粹,因为依赖了全局变量。所以这决定了Context一般不会大规模的使用。所以一般在一个组件中使用一个Context就好。由于Consumer的特性,里面的代码必须是这个函数的返回值。这样就显得复杂与不优雅了。

    • 挂载在 class 上的 contextType 属性会被重赋值为一个由 React.createContext() 创建的 Context 对象。这能让你使用 this.context 来消费最近 Context 上的那个值。你可以在任何生命周期中访问到它,包括 render 函数中。
    import React from 'react'
    import MyContext from './App.js'
    
    class MyClass extends React.Component {
      componentDidMount() {
        let value = this.context;
        /* 在组件挂载完成后,使用 MyContext 组件的值来执行一些有副作用的操作 */
      }
      componentDidUpdate() {
        let value = this.context;
        /* ... */
      }
      componentWillUnmount() {
        let value = this.context;
        /* ... */
      }
      render() {
        let value = this.context;
        /* 基于 MyContext 组件的值进行渲染 */
      }
    }
    MyClass.contextType = MyContext;
    
    • 如果你正在使用实验性的 public class fields 语法,你可以使用 static 这个类属性来初始化你的 contextType
    import React, { Component, createContext } from 'react';
    
    const BatteryContext = createContext();
    
    //声明一个孙组件 ,使用context.type
    class Leaf extends Component {
        static contextType = BatteryContext;
        render() {
            const battery = this.context;
            return<h1>Battery : {battery}</h1>
        }
    }
    
    //声明一个子组件
    class Middle extends Component {
        render() {
            return <Leaf />
        }
    }
    
    class MyClass extends Component {
        state = {
            battery: 60,
        }
        render() {
            const { battery } = this.state;
            return (
                <BatteryContext.Provider value={battery}>
                    <button
                        type="button"
                        onClick={() => this.setState({ battery: battery - 1 })}
                    >
                        减减
                    </button>
                    <Middle />
                </BatteryContext.Provider>
            );
        }
    
    }
    

    Providervalue 状态提升到父节点的 state 里:防止当 provider 的父组件进行重渲染时,可能会在 consumers 组件中触发意外的渲染。

    3. Suspense

    Suspense 使得组件可以“等待”某些操作结束后,再进行渲染。目前,Suspense 仅支持的使用场景是:通过 React.lazy 动态加载组件。它将在未来支持其它使用场景,如数据获取等。

    • React.lazy
    • React.Suspense

    (3.1)、 Lazy

    React.lazy函数用来加载动态引入的组件。

    React.lazy 函数能让你像渲染常规组件一样处理动态引入(的组件)。
    React.lazy 接受一个函数,这个函数需要动态调用 import()。它必须返回一个 Promise,该 Promise 需要 resolve 一个 defalut export 的 React 组件。

    然后应在 Suspense 组件中渲染 lazy 组件,如此使得我们可以使用在等待加载 lazy 组件时做优雅降级(如 loading 指示器等)。 fallback 属性接受任何在组件加载过程中你想展示的 React 元素。你可以将 Suspense 组件置于懒加载组件之上的任何位置。你甚至可以用一个 Suspense 组件包裹多个懒加载组件。

    // parent
    import React, {Suspense} from "react";
    
    const OtherComponent = React.lazy(() => {return import('./OtherComponent.js')});
    
    export default function LazyDemo() {
        return (
            <div>
                <Suspense fallback={<div>Loading...</div>}>
                    <OtherComponent/>
                </Suspense>
            </div>
        );
    }
    
    // child
    import React from "react";
    
    export default function OtherComponent() {
        return (
            <div>777</div>
        )
    }
    

    (3.2)、 Suspense

    React 16.6添加了一个组件,允许您“等待”一些代码加载,

    suspense是React 16.6添加了一个组件,此组件使得加载其他代码成为同步,并在等待时声明性地指定加载状态(例如spinner)。

    4. memo

    React.memo 为高阶组件,主要用于性能优化。它与 React.PureComponent 非常相似,但它适用于函数组件,但不适用于 class 组件。默认情况下其只会对复杂对象做浅层对比。

    // 1. 现在有一个显示时间的组件,每一秒都会重新渲染一次
    import React  from 'react';
    export default class extends React.Component {
        constructor(props){
            super(props);
            this.state = {
                date : new Date()
            }
        }
    
        componentDidMount(){
            setInterval(()=>{
                this.setState({
                    date:new Date()
                })
            },1000)
        }
    
        render(){
            return (
                <div>
                    <Child seconds={1}/>
                    <div>{this.state.date.toString()}</div>
                </div>
            )
        }
        
    // 2. 对于Child组件我们肯定不希望也跟着渲染,所有需要用到 PureComponent
    class Child extends React.PureComponent {
        render(){
            console.log('I am rendering');
            return (
                <div>I am update every {this.props.seconds} seconds</div>
            )
        }
    }
    
    // 3. 现在新出了一个 React.memo() 可以满足创建纯函数 而不是一个类的需求
    // 3.1 React.memo()
    import React, { useState, useMemo, memo } from 'react'
    
    export default function MemoCallback() {
        const [count, setCount] = useState(0);
        const double = useMemo(() => {
            return count * 2;
        }, [count === 5])
    
        const Counter = memo(function Child(props) {
            return (
                <span>子组件:{props.count}</span>
            )
        });
    
        return (
            <div>
                <button onClick={() => {setCount(count + 1)}}>click: {count}</button>
                {/*<span>double: {double}</span>*/}
                <Counter count={double}/>
            </div>
        )
    }
    
    // 3.2 React.memo()可接受2个参数,
    // 第一个参数为纯函数的组件,第二个参数用于对比props控制是否刷新,与shouldComponentUpdate()功能类似。
    import React from "react";
    function Child({seconds}){
        console.log('I am rendering');
        return (
            <div>I am update every {seconds} seconds</div>
        )
    };
    
    function areEqual(prevProps, nextProps) {
        if(prevProps.seconds===nextProps.seconds){
            return true
        }else {
            return false
        }
    
    }
    export default React.memo(Child,areEqual)
    
    // 3.3 React.memo() 与Redux
    import React from "react";
    function Child({seconds,state}){
        console.log('I am rendering');
        return (
          <div>
            <div>I am update every {seconds} seconds</div>
            <p>{state}</p>
          </div>
        )
    };
    const mapStateToProps = state => ({
        state: 'React.memo()用在connect()(内)'
    });
    export default connect(mapStateToProps)(React.memo(Child))
    

    5. 在 React 中有两种流行的方式来共享组件之间的状态逻辑

    • 高阶组件
    • render props

    6. React.PureComponent

    React.PureComponentReact.Component 很相似。两者的区别在于 React.Component 并未实现 shouldComponentUpdate(),而 React.PureComponent 中以浅层对比 prop 和 state 的方式来实现了该函数。

    // 1. shouldComponentUpdate 的 demo
    class CounterButton extends React.Component {
        constructor(props) {
            super(props);
            this.state = {count: 1};
        }
        shouldComponentUpdate(nextProps, nextState) {
            if (this.props.color !== nextProps.color) {
                return true;
            }
            if (this.state.count !== nextState.count) {
                return true;
            }
            return false;
        }
        render() {
            return (
                <button
                    color={this.props.color}
                    onClick={() => this.setState(state => ({count: state.count + 1}))}
                >
                    Count: {this.state.count}
                </button>
            );
        }
    }
    
    // 2. React.PureComponent 的 demo
    class ListOfWords extends React.PureComponent {
     render() {
         return <div>{this.props.words.join(',')}</div>;
     }
    }
    class WordAdder extends React.Component {
     constructor(props) {
         super(props);
         this.state = {
             words: ['marklar']
         };
         this.handleClick = this.handleClick.bind(this);
     }
     handleClick() {
         // This section is bad style and causes a bug
         const words = this.state.words;
         words.push('marklar');
         this.setState({words: words});
     }
     render() {
         return (
             <div>
                 <button onClick={this.handleClick}>click</button>
                 <ListOfWords words={this.state.words} />
             </div>
         );
     }
    }
    

    7. ref

    ref的3中用法:

    • 字符串

    dom节点上使用,通过this.refs[refName]来引用真实的dom节点

    <input ref="inputRef" /> //this.refs['inputRef']来访问
    
    • 回调函数

    React 支持给任意组件添加特殊属性。ref 属性接受一个回调函数,它在组件被加载或卸载时会立即执行。

    当给 HTML 元素添加 ref 属性时,ref 回调接收了底层的 DOM 元素作为参数。 当给组件添加 ref 属性时,ref 回调接收当前组件实例作为参数。 当组件卸载的时候,会传入null ref 回调会在componentDidMount 或 componentDidUpdate 这些生命周期回调之前执行。

    <input ref={(input) => {this.textInput = input;}} type="text" />   //HTML 元素添加 ref 属性时
    <CustomInput ref={(input) => {this.textInput = input;}} />   //组件添加 ref 属性
    
    • React.createRef()

    在React 16.3版本后,使用此方法来创建ref。将其赋值给一个变量,通过ref挂载在dom节点或组件上,该ref的current属性 将能拿到dom节点或组件的实例

    class Child extends React.Component{
        constructor(props){
            super(props);
            this.myRef=React.createRef();
        }
        componentDidMount(){
            console.log(this.myRef.current);
        }
        render(){
            return <input ref={this.myRef}/>
        }
    }
    

    起源地下载网 » React16后一些重要的API和概念

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元