zoukankan      html  css  js  c++  java
  • React 简介

    React 是一个用于构建用户界面的 JavaScript 库

    创建DOM节点 React.createRef();

    class CustomTextInput extends React.Component {
      constructor(props) {
        super(props);
        // 创造一个 textInput DOM 元素的 ref
        this.textInput = React.createRef();
      }
      render() {
      // 使用 `ref` 回调函数以在实例的一个变量中存储文本输入 DOM 元素
      //(比如,this.textInput)。
        return (
          <input
            type="text"
            ref={this.textInput}
          />
        );
      }
    }
    

    代码分割 import() 语法, 这样写webpack也会单独打包一个chunk

    import("./math").then(math => {
      console.log(math.add(16, 26));
    });
    

    React.lazy 函数能让你像渲染常规组件一样处理动态引入(的组件)。

    const OtherComponent = React.lazy(() => import('./OtherComponent'));
    

    React.lazy 接受一个函数,这个函数需要动态调用 import()。它必须返回一个 Promise,该 Promise 需要 resolve 一个 defalut exportReact 组件。

    然后应在 Suspense 组件中渲染 lazy 组件,如此使得我们可以使用在等待加载 lazy 组件时做优雅降级(如 loading 指示器等)。

    import React, { Suspense } from 'react';
    
    const OtherComponent = React.lazy(() => import('./OtherComponent'));
    
    function MyComponent() {
      return (
        <div>
          <Suspense fallback={<div>Loading...</div>}>
            <OtherComponent />
          </Suspense>
        </div>
      );
    }
    

    fallback 属性接受任何在组件加载过程中你想展示的 React 元素。你可以将 Suspense 组件置于懒加载组件之上的任何位置。你甚至可以用一个 Suspense 组件包裹多个懒加载组件。

    import React, { Suspense } from 'react';
    
    const OtherComponent = React.lazy(() => import('./OtherComponent'));
    const AnotherComponent = React.lazy(() => import('./AnotherComponent'));
    
    function MyComponent() {
      return (
        <div>
          <Suspense fallback={<div>Loading...</div>}>
            <section>
              <OtherComponent />
              <AnotherComponent />
            </section>
          </Suspense>
        </div>
      );
    }
    

    基于路由的代码分割

    import React, { Suspense, lazy } from 'react';
    import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
    
    const Home = lazy(() => import('./routes/Home'));
    const About = lazy(() => import('./routes/About'));
    
    const App = () => (
      <Router>
        <Suspense fallback={<div>Loading...</div>}>
          <Switch>
            <Route exact path="/" component={Home}/>
            <Route path="/about" component={About}/>
          </Switch>
        </Suspense>
      </Router>
    );
    

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

    React.createContext

    创建一个 Context 对象。当 React 渲染一个订阅了这个 Context 对象的组件,这个组件会从组件树中离自身最近的那个匹配的 Provider 中读取到当前的 context 值。

    const MyContext = React.createContext(defaultValue);
    

    Context.Provider

    每个 Context 对象都会返回一个 Provider React 组件,它允许消费组件订阅 context 的变化。

    const ThemeContext = React.createContext('light');
    class App extends React.Component {
      render() {
        return (
          <ThemeContext.Provider value="dark">
            <Toolbar />
          </ThemeContext.Provider>
        );
      }
    }
    

    Class.contextType

    挂载在 class 上的 contextType 属性会被重赋值为一个由 React.createContext() 创建的 Context 对象。这能让你使用 this.context 来消费最近 Context 上的那个值。你可以在任何生命周期中访问到它,包括 render 函数中。

    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;
      }
    }
    MyClass.contextType = MyContext;
    

    Context.Consumer

    这需要函数作为子元素(function as a child)这种做法。这个函数接收当前的 context 值,返回一个 React 节点。传递给函数的 value 值等同于往上组件树离这个 context 最近的 Provider 提供的 value 值。如果没有对应的 Provider,value 参数等同于传递给 createContext() 的 defaultValue。

    <MyContext.Consumer>
      {value => /* 基于 context 值进行渲染*/}
    </MyContext.Consumer>
    

    Context综合使用实列

    创建 context 对象

    export const ThemeContext = React.createContext({
      theme: themes.dark,
      toggleTheme: () => {},
    });
    

    使用context服务

    import {ThemeContext} from './theme-context';
    
    function ThemeTogglerButton() {
      // Theme Toggler 按钮不仅仅只获取 theme 值,它也从 context 中获取到一个 toggleTheme 函数
      return (
        <ThemeContext.Consumer>
          {({theme, toggleTheme}) => (
            <button          onClick={toggleTheme}
              style={{backgroundColor: theme.background}}>
    
              Toggle Theme
            </button>
          )}
        </ThemeContext.Consumer>
      );
    }
    
    export default ThemeTogglerButton;
    

    消费多个 Context

    为了确保 context 快速进行重渲染,React 需要使每一个 consumers 组件的 context 在组件树中成为一个单独的节点。

    // Theme context,默认的 theme 是 “light” 值
    const ThemeContext = React.createContext('light');
    
    // 用户登录 context
    const UserContext = React.createContext({
      name: 'Guest',
    });
    
    class App extends React.Component {
      render() {
        const {signedInUser, theme} = this.props;
    
        // 提供初始 context 值的 App 组件
        return (
          <ThemeContext.Provider value={theme}>
            <UserContext.Provider value={signedInUser}>
              <Layout />
            </UserContext.Provider>
          </ThemeContext.Provider>
        );
      }
    }
    
    function Layout() {
      return (
        <div>
          <Sidebar />
          <Content />
        </div>
      );
    }
    
    // 一个组件可能会消费多个 context
    function Content() {
      return (
        <ThemeContext.Consumer>
          {theme => (
            <UserContext.Consumer>
              {user => (
                <ProfilePage user={user} theme={theme} />
              )}
            </UserContext.Consumer>
          )}
        </ThemeContext.Consumer>
      );
    }
    

    Refs 转发

    1、Ref 转发是一项将 ref 自动地通过组件传递到其一子组件的技巧。对于大多数应用中的组件来说,这通常不是必需的。但其对某些组件,尤其是可重用的组件库是很有用的 。
    2、我们通过调用 React.createRef 创建了一个 React ref 并将其赋值给 ref 变量。
    3、我们通过指定 ref 为 JSX 属性,将其向下传递给 <FancyButton ref={ref}>
    4、React 传递 refforwardRef 内函数 (props, ref) => ...,作为其第二个参数。
    5、我们向下转发该 ref 参数到 <button ref={ref}>,将其指定为 JSX 属性。
    6、当 ref 挂载完成,ref.current 将指向 <button> DOM 节点。

    const ref = React.createRef();
    <FancyButton label="Click Me" handleClick={handleClick}  ref={ref} />;
    

    创建 Refs

    Refs 是使用 React.createRef() 创建的,并通过 ref 属性附加到 React 元素。在构造组件时,通常将 Refs 分配给实例属性,以便可以在整个组件中引用它们。

    class MyComponent extends React.Component {
      constructor(props) {
        super(props);
        this.myRef = React.createRef();
      }
      render() {
        return <div ref={this.myRef} />;
      }
    }
    

    访问 Refs

    当 ref 被传递给 render 中的元素时,对该节点的引用可以在 ref 的 current 属性中被访问

    const node = this.myRef.current;
    

    1、当 ref 属性用于 HTML 元素时,构造函数中使用 React.createRef() 创建的 ref 接收底层 DOM 元素作为其 current 属性。
    2、当 ref 属性用于自定义 class 组件时,ref 对象接收组件的挂载实例作为其 current 属性。
    3、你不能在函数组件上使用 ref 属性,因为他们没有实例

    为 class 组件添加 Ref

    如果我们想包装上面的 CustomTextInput,来模拟它挂载之后立即被点击的操作,我们可以使用 ref 来获取这个自定义的 input 组件并手动调用它的 focusTextInput 方法:

    class AutoFocusTextInput extends React.Component {
      constructor(props) {
        super(props);
        this.textInput = React.createRef();
      }
    
      componentDidMount() {
        this.textInput.current.focusTextInput();
      }
    
      render() {
        return (
          <CustomTextInput ref={this.textInput} />
        );
      }
    }
    

    请注意,这仅在 CustomTextInput 声明为 class 时才有效:

    class CustomTextInput extends React.Component {
      // ...
    }
    
    

    Refs 与函数组件

    默认情况下,你不能在函数组件上使用 ref 属性,因为它们没有实例:

    function CustomTextInput(props) {
      // 这里必须声明 textInput,这样 ref 才可以引用它
      const textInput = useRef(null);
    
      function handleClick() {
        textInput.current.focus();
      }
    
      return (
        <div>
          <input
            type="text"
            ref={textInput} />
          <input
            type="button"
            value="Focus the text input"
            onClick={handleClick}
          />
        </div>
      );
    }
    
    

    高阶组件

    高阶组件(HOC)是 React 中用于复用组件逻辑的一种高级技巧。HOC 自身不是 React API 的一部分,它是一种基于 React 的组合特性而形成的设计模式

  • 相关阅读:
    超赞!不容错过的5款实用网页开发和设计工具
    如何从平面设计转行到UI设计?
    线段树
    RMQ
    Splay
    Treap
    *模板--矩阵
    最小生成树
    hash
    ac自动机
  • 原文地址:https://www.cnblogs.com/boyGdm/p/14144743.html
Copyright © 2011-2022 走看看