Functional programming is the essence of React

They were prepared early last year, after the last draft

2.JSX

React officially developed a compiler for JSX parsing early on, JSTransform, which is no longer maintained and is now fully implemented using Babel’s JSX compiler. Because the two are functionally identical, Babel, as a specialized JavaScript syntax compiler, provides more powerful functions, achieving the purpose of “one configuration, one operation”.

In addition to using JSX syntax, we can also build React elements using React.createElement() and React.cloneElement().

  • 2.1 Virtual elements can be understood as the corresponding to real elements. The construction and update of virtual elements are completed in memory, and they are not really rendered into DOM. Virtual elements created in React can be divided into two categories: DOM element and Component element, corresponding to native DOM element and custom element respectively

    Element types: DOM element and component element. The corresponding rule is whether the HTML tag starts with a lowercase letter. The lowercase letter corresponds to the DOM element, and the component element naturally corresponds to the uppercase letter. JSX can also use component elements in namespaces to resolve conflicts between components with the same names or to categorize groups of components

    • 2.1.1 DOM elements

    • 2.1.2 Component elements

  • 2.2 Basic JSX syntax

    • When you define a label, only one label is allowed
    • 2.2.2 The label must be closed
    • 2.2.3 Element type: DOM element and component element, whether the HTML tag starts with a lowercase letter. The lowercase letter corresponds to the DOM element, while the component element naturally corresponds to the uppercase letter
    • 2.2.4 Use comments wrapped in {}
    • 2.2.5 Element attributes
      • Change the class attribute to className;

      • Let’s change the for attribute to htmlFor; Custom attributes are written in small hump instead of standard;

      • Boolean property: To pass false, a property expression must be used.

        For example, <Checkbox checked={true} /> <Checkbox checked={false} /> can omit the checked property.Copy the code
      • Expand properties: You can use the ES6 REST /spread features to improve efficiency:

        const data = { name: 'foo', value: 'bar'}; const component = <Component name={data.name} value={data.value} />; Const data = {name:'foo', value: 'bar'}; const component = <Component {... data} />;Copy the code
      • Custom HTML attributes

        React will not render if you pass custom attributes to a DOM element in JSX: <div d="xxx"If you want to use HTML custom attributes, use the data- prefix, which is also consistent with the HTML standard: <div data-attr="xxx"Word-wrap: break-word! Important; "> < span style =" box-sizing: border-box; color: RGB (74, 74, 74)"foo"/> Web accessibility properties starting with aria- can also be used properly: <div aria-hidden={true< div style = "box-sizing: border-box; color: RGB (74, 74, 74); line-height: 22px; white-space: inherit;" Its core rendering method, or component output method, is the Render methodCopy the code
    • 2.2.6 JavaScript attribute expressions

      To use expressions for property values, simply replace “” with {};

       <Person name={window.isLoggedIn ? window.name : ' '} / >;Copy the code
    • 2.2.7 HTML escaping
      React will escape all strings to be displayed to the DOM, preventing XSS. So, if JSX contains escaped entity characters, such as &copy; (©), the final DOM will not display correctly because React automatically converts &copy; The special characters in. There are several solutions: - Use the UTF-8 character © directly; - Use the Unicode encoding of the corresponding character to query the encoding; - Use array assembly '<div>{['cc ', <span>&copy; </span>,'2015']} < / div > `; - Insert the original HTML directly. In addition, React provides dangerouslySetInnerHTML attributes. <div dangerouslySetInnerHTML={{__html: <div dangerouslySetInnerHTML={{__html:'cc © 2015 '}} / >Copy the code

3. The React components

  • 3.1 Construction of the React component
    • React.createClass
        const Button = React.createClass({
            getDefaultProps() {
                return {
                color: 'blue',
                text: 'Confirm'}; },render() {
                const { color, text } = this.props;
                return (
                    <button className={`btn btn-${color}`}> <em>{text}</em> </button> ); }});Copy the code
  • ES6 classes
        import React, { Component } from 'react';
        class Button extends Component {
            constructor(props) {
                super(props);
            }
            static defaultProps = {
                color: 'blue',
                text: 'Confirm'};render() {
                const { color, text } = this.props;
                return (
                    <button className={`btn btn-${color}`}> <em>{text}</em> </button> ); }}Copy the code
  • Stateless function
    Components built using stateless functions are called stateless components, and this is a new addition since version 0.14, and is officially favored. The example code is as follows:function Button({ color = 'blue', text = 'Confirm'{})return (
        <button className={`btn btn-${color}`}> <em>{text}</em> </button> ); } The stateless component only passes props and context; That is, it has no state, no lifecycle method, and the component itself is the render method of the two React component build methods above. When it is created, it always keeps an instance, avoids unnecessary checks and memory allocation, and achieves internal optimization;Copy the code

6.ReactDOM

There are very few apis in ReactDOM, just findDOMNode, unmountComponentAtNode, and Render.

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
class App extends Component {
  componentDidMount() {// myComp is an instance of Comp, so we need to convert findDOMNode to the corresponding DOM const myComp = this.refs.mycomp; const dom = findDOMNode(myComp); }render() {
    return (
      <div>
        <Comp ref="myComp"/> </div> ); }}Copy the code

7. Event system

7.1 Binding Modes of Synthetic Events

The event types of React composite events are a subset of JavaScript’s native event types.

<button onClick={this.handleclick}>Test</button> For HTML events, use all lowercase property names (such as onclick). React does not bind event handlers directly to HTML elements as dom0-level events do. React just borrows from thatCopy the code

7.2 Implementation mechanism of synthetic events

At the React level, there are two main things you do with synthesized events: event delegation and automatic binding.

  1. Event delegate

Before using React events, be sure to familiarize yourself with its event proxy mechanism. Instead of binding event handlers directly to a real node, it binds all events to the outermost layer of the structure, using a single event listener that maintains a map to all event listeners and handlers inside the component. When a component is mounted or unmounted, only objects are inserted or deleted from the uniform event listener; When an event occurs, it is first processed by the uniform event listener, and then the actual event handler is found in the map and called. This simplifies the event handling and recovery mechanism, and also greatly improves the efficiency;

  1. Automatic binding

In the React component, the context of each method points to an instance of that component, which automatically binds this to the current component. React also caches such references to optimize CPU and memory. When using ES6 classes or pure functions, this automatic binding no longer exists, and we need to manually implement this binding.

  • The bind method. This method helps us bind this to the event handler and pass parameters to the event handler, such as:

    import React, { Component } from 'react';
    class App extends Component {
      handleClick(e, arg) {
        console.log(e, arg);
      }
      render() {// PassbindMethod implementation, you can pass parametersreturn <button onClick={this.handleClick.bind(this, 'test')}>Test</button>; }}Copy the code

    If methods bind only and pass no arguments, the Stage 0 draft provides a convenient solution ① — a double colon syntax that works the same as this.handleclick.bind (this), and Babel already implements this proposal. Such as:

    — — — — — — — — — — — — — — — — — — — — —

    ① ECMAScrip This-Binding Syntanx, see github.com/zenparsing/…

    import React, { Component } from 'react';
    class App extends Component {
      handleClick(e) {
        console.log(e);
      }
      render() {
        return<button onClick={::this.handleClick}>Test</button>; }}Copy the code
  • Constructor.

    This is bound in the constructor of the component. The advantage of this binding is that it only needs to be bound once, rather than every time the event listener is called:

    import React, { Component } from 'react';
    class App extends Component {
      constructor(props) {
        super(props);
        this.handleClick = this.handleClick.bind(this);
      }
      handleClick(e) {
        console.log(e);
      }
      render() {
        return<button onClick={this.handleClick}>Test</button>; }}Copy the code
  • Arrow function.

    Not only is the arrow function syntax sugar, it also automatically binds to this, which defines the scope of the function, so we don’t need to use bind on it. For example, the following works:

    import React, { Component } from 'react';
    class App extends Component {
      const handleClick = (e) => {
        console.log(e);
      };
      render() {
        return<button onClick={this.handleClick}>Test</button>; }} or import React, {Component} from'react';
    class App extends Component {
      handleClick(e) {
        console.log(e);
      }
      render() { 
        return<button onClick={() => this.handleclick ()}>Test</button>}}Copy the code
    • Use native events in React

      React provides a nice synthetic event system, but that doesn’t mean native events can’t be used under the React architecture. React provides full lifecycle methods, where componentDidMount is called after the component has been installed and a real DOM exists in the browser, at which point we can complete the binding of native events;

      import React, { Component } from 'react';
      class NativeEventDemo extends Component {
        componentDidMount() {
        this.refs.button.addEventListener('click', e => {
          this.handleClick(e);
        });
        }
        handleClick(e) {
          console.log(e);
        }
        componentWillUnmount() {
          this.refs.button.removeEventListener('click');
        }
        render() {
          return <button ref="button">Test</button>; It is important to note that when using DOM native events in React, you must manually remove them during component uninstallation. Otherwise, memory leaks may occur. You don't need to use the synthetic event system because React already handles it for you.Copy the code

      Try to avoid in the React to mix in the synthesis and native DOM events, in addition, with reactEvent. NativeEvent. StopPropagation () to prevent a bubble is not enough. – Blocking React event bubbles can only be used in the React composite event system, and there is no way to prevent native event bubbles. Conversely, blocking bubbling behavior in native events prevents React composite events from spreading;

      In fact, React’s synthetic event system is only a subset of the native DOM event system. It implements only the DOM Level 3 event interface and unifies interoperability between browsers. There are some events that React does not implement, or cannot implement due to certain limitations, such as the Window resize event. For scenarios where events cannot be synthesized using React, we also need to use native events to do so

      The propagation of browser native DOM events can be divided into three stages: event capture, event handler invocation of the target object itself, and event bubbling. React’s synthesized events do not capture events, but only support event bubbling. Blocking native event propagation requires the use of E.preventDefault (), but for browsers that do not support this method (IE9 below), only e.ancelbubble = true can be used to prevent this. For React composite events, just use e.preventDefault().

    • 8. Controlled and uncontrolled components

      Every time the state of the form changes, it is written to the state of the component, known in React as a controlled Component. In a controlled component, the rendered state of the component corresponds to its value or checked Prop; A form component can be called an uncontrolled component if it does not have a value prop (the radio button and check box correspond to a Checked Prop). The use of uncontrolled components in React is not recommended

    • 9. Styling

      const style = {
        color: 'white',
        backgroundImage: `url(${imgUrl}) ', // Notice the capital W, which will be converted to -webkit-transition WebkitTransition:'all'// ms is the only lower-case browser prefix msTransition:'all'}; const component = <Component style={style} />;Copy the code
      • Pixel values in 9.1 styles

      When setting sizing styles such as Width and height, most of them are in pixels, and it can be cumbersome to enter px repeatedly. For efficiency, React automatically adds px to attributes like this. // render to height: 10px const style = {height: 10};

      • 9.2 Using the ClassNames Library

        Dynamically set the className for the component

          render() {
            const btnClass = classNames({
              'btn': true.'btn-pressed': this.state.isPressed,
              'btn-over': !this.state.isPressed && this.state.isHovered,
            });
            return <button className={btnClass}>{this.props.label}</button>;
          } 
        Copy the code
      • 9.3 CSS Modules
        // webpack.config.js CSS? modules&localIdentName=[name]__[local] - [hash:base64:5] is enabled by adding modules, wherelocalIdentName is the naming rule that sets the generation styleCopy the code

        CSS Modules implements the following:

        • All styles are local, resolving name conflicts and global contamination;
        • The class name generation rules are flexible, which can be used to compress the class name.
        • All of the JavaScript and CSS of the component can be done simply by referring to the JavaScript of the component;
        • It’s still CSS, and the learning cost is almost zero.
        Using CSS Modules is equivalent to adding:localTo implement style localization. If we want to switch to global mode, we can use :global package. The example code is as follows:.normal {color: green; } /* This is equivalent to the following */ :local(.normal) { color: green; } /* Define global style */ :global(.btn) {color: red; } /* define multiple global styles */ :global {.link {color: green; } .box { color: yellow; }}Copy the code

        Here is the configuration code for the WebPack section used in the specific project:

          module: {
           loaders: [{
             test: /\.jsx? $/, loader:'babel'}, {test: /\.scss$/,
             exclude: path.resolve(__dirname, 'src/styles'),
             loader: 'style! css? modules&localIdentName=[name]__[local]! sass? sourceMap=true'}, {test: /\.scss$/,
             include: path.resolve(__dirname, 'src/styles'),
             loader: 'style! css! sass? sourceMap=true',
           }]
          }
          
          /* src/app.js */
          import './styles/app.scss';
          import Component from './view/Component'
          /* src/views/Component.js */
          import './Component.scss'; The directory structure is as follows: SRC ├── app.js ├── styles │ ├── app.scss │ ├── normalize. SCSS │ ├─ views ├─ component.js ├─ component.scss All global styles are imported in SRC /styles/app.scss, and all other directories (including SRC /views) are local. CSS Modules is a good solution to the modularity problem of CSSCopy the code
    • 10. Communication between components

      • 10.1 Parent Component Communicates with child component
      • 10.2 The child component communicates with the parent component
      • 10.3 Cross-level Communication
      • 10.4 Communication between Components without nested relationships
    • 11. Inter-component abstraction

      During the React component building process, there are often scenarios where a class of functionality needs to be shared by different components, and this is where abstraction comes in. There are many abstract approaches under different design concepts, but with React we focus on two: mixins and higher-order components;

      • 11.1 Mixin

        React provides mixin properties when building components using createClass, such as the official package PureRenderMixin: Import React from'react';
          import PureRenderMixin from 'react-addons-pure-render-mixin';
          React.createClass({
              mixins: [PureRenderMixin],
              render() {
                  return<div>foo</div>; }}); In the createClass object parameter, we pass an array of mixins that encapsulate the modules we needCopy the code
        • Some of mixins’ biggest problems
        Encapsulation name conflicts that break the original component add complexityCopy the code

        In response to these concerns, the React community has come up with a new way to replace mixins: higher-order components

        • High order component

          A higher-order component, similar to a higher-order function, takes the React component as input and outputs a new React component. There are two ways to implement higher-order components.

          • Props Proxy. High-level components operate props through the wrapped React component.
              import React, { Component } from 'React';
              const MyContainer = (WrappedComponent) =>
              class extends Component {
                  render() {
                      return <WrappedComponent {...this.props} />;
                  }
              } 
            Copy the code
          • Inheritance Inversion. Higher-order components inherit from the wrapped React component.
              const MyContainer = (WrappedComponent) =>
                class extends WrappedComponent {
                  render() {
                    returnsuper.render(); }}Copy the code
    • 12. Optimize component performance

      We all know that one of the biggest factors affecting web performance is browser reflow and repaint. The Virtual DOM behind React is designed to minimize browser redrawing and reformatting. On the topic of performance optimization, we tend to base it on the “untrusting” premise that we need to make the React Virtual DOM more efficient. Judging from React’s rendering process, how to prevent unavoidable rendering is probably the biggest problem to solve. However, React officials offer a convenient solution to this problem: PureRender.

    • 12.1 pure functions

    • 12.2 PureRender

    • 12.3 Immutable

    • 12.4 the key

    • 12.5 the react – addons – perf

    Automated testing

    • Reference: React front-end automated tests: JEST + enzyme

    React has perfect support for testing. The current mature React testing frameworks include Jest and Enzyme

    Enzyme is an open-source React component testing framework created by Airbnb. Compared to Jest, Enzyme provides syntax similar to jQuery for manipulating the DOM, making it more flexible and easy to use when making test assertions

    reference

    • Dive into the React technology stack