1. Pre-knowledge

  1. Vue template syntax is vue-loader
  2. React JSX syntax uses the jsX-loader that is built into babel-loader, which is built into WebPack
  3. JSX Precautions
  • The class attribute is className
    <div className ="red">n</div>
Copy the code

CreateElement (‘div’,{className:’red’},’n’)

  • Variables and objects are enclosed in curly braces {}

  • Return followed by parentheses ()

  1. Introduced the React
yarn add react react-dom
import React from 'react'
import ReactDom from 'react-dom'
Copy the code

Class component

1. Creation mode
    class Welcome extends React.Component{
        constructor(props){
           super(props) 
           this.state={
                n:0.m:1.user: {name:"xiaohong".age: 18}}}render(){
            return (<h1>hello,{this.props.name}</h1>)}}// How to use it
    <Welcome name = "xiaoming">
Copy the code
2. Read the props
  • Do not write props, notify the parent component to modify
{name:"xiaohong",onClick:()=>{},children:"hi"}
class Parent extends React.component{
    constructor(props){
        super(props) 
        this.state ={name:"xiaohong"}
    }
    onClick =() = >{}
    render(){
        return <B name = {this.state.name} onClick={this.onClick}>hi</B>}}/ / read
 class B extends React.component{
    constructor(props){
        super(props) // With this done,this. Props is the address of the external data object
    }

    render(){
        return <div onClick = {this.props.onClick}>
        {this.props.name}
        <div>
            {this.props.children}
        </div>
        </div>}}Copy the code
3. The state of reading and writing

Matters needing attention:

  • SetState automatically merges the first layer attributes, using object.assign () or… when there are multiple layers. The operator
  • This.state. n+=1 is invalid and setState() must be called to trigger the UI update
  • SetState will update the UI asynchronously, and reading state immediately will fail, so setState(function) is more recommended.
  • This.setstate (this.state) not recommended, do not modify old state(immutable data, functional programming philosophy)
  • This.setstate ((state,props)=>newState,fn) Fn executes after a write is successful
/ / read
this.state.n 
/ / write
this.setState({n:1}) 
// Multi-layer attributes - method 1... The m and n operators are automatically merged
this.setState({
    user: {... this.state.username:jack
    }
})
// For multiple attributes - methods 2-object. assign,m and n are automatically merged
const user =Object.assign({},this.state.user)
user.name ="xiaofang"
this.setState({
    user:user
})
// function
this.setState((state) = >({n:state.n+1}))Copy the code
4. Event binding
//addN is on the object
class Son extends React.Component{
    constructor(props){
        super(props)
        this.state={
            n:0
        }
        this.addN=() = >{
            this.setState({n:this.state.n+1}}})render(){
        return <button onclick ={this.addN}>+ 1</button>}}// Use constructor to refer to addN
class Son extends React.Component{
    constructor(props){
        super(props)
        this.state={
            n:0
        }
        
    }
    addN=() = >{
        this.setState({n:this.state.n+1})}render(){
        return <button onclick ={this.addN}>+ 1</button>}}//addN on the prototype, if you do not bind this,this will become window,window has no addN function
class Son extends React.Component{
    constructor(props){
        super(props)
        this.state={
            n:0}}function addN(){
        this.setState({n:this.state.n+1})}render(){
        return <button onclick ={()= >this.addN()}>+1</button>}}/ / another
class Son extends React.Component{
    constructor(props){
        super(props)
        this.state={
            n:0}}function addN(){
        this.setState({n:this.state.n+1})}render(){
        return <button onclick ={this.addN.bind(this)}>+ 1</button>}}Copy the code
5. Lifecycle hook functions
Constructor () // initialize state 2. static getDerivedStateFromProps() 3. shouldComponentUpdate() return false 4. Render () create virtual DOM 5.GetSnapshotBeforeUpdate () 6.ComponnetDidMount () // Component appears on the page to get DOM Ajax request first render execute this hook 7. ComponentDidUpdate () shouldCoponentUpdate () shouldCoponentUpdate returns false when this hook is not executed. 9. Static getDerivedStateFromError() 10. ComponnetDidCatch ()Copy the code
//shouldComponentUpdat() return false to prevent updates
//React.PureComponent has this function built in and will not rerender if the props and state are not changed
class App extends React.component{
    constructor(props){
        super(props)
        this.state = {
            n:1
        }
    }
    onClick = () = >{
        this.setState(state= >({n: state.n + 1}))
        this.setState(state= >({n: state.n - 1}}))shouldComponentUpdate(newProps,newState){
        if(newState.n === this.state.n){
            return false
        }else{
            return true}}render(){
        console.log("Render once")
        return(
            <div>
                {this.state.n}
                <button onClick = {this.onClick}>+ 1 to 1</button>
            </div>)}}Copy the code

Hook execution order:

Function components

1. Creation mode
/ / 1
function Welcome(props){
   return <h1>hello,{props.name}</h1>;
}
   
/ / the second
const Welcome = props= > <div>{props.name}<div/>  
   
 / / 3 kinds
const Welcome = (props) = > {return <div>{props.name}<div/>}
   
// How to use it
<Welcome name = "xiaoming"/>
Copy the code
2. React Hooks

2.1. useState

  • Using a state
const [n,setN] = useState(0)
const [user,setUser] = useState({name:"xiaohong"})
Copy the code
  • SetState (obj) does not automatically merge attributes;
  • SetState (obj) If the OBj address has not changed, reAC assumes that the address has not changed
  • UseState () accepts the function, which returns the initial state and is executed only once
 const[state,setState] = useState(() = >{
     return initialState
 })
Copy the code
  • SetState () accepts functions and uses them in preference
    setN(i= > i+1)
Copy the code
  • SetN (n+1) produces a new n, the original n does not change

    Example: add 1 and log,log returns 1; So log is going to be plus one,log is going to be the original n, which is zero

    If you don’t want doppelganger, you can use useRef or useContext

function App(props){
    const [n,setN] = useState(0)
    const log =() = >{
        setTimeOut(() = >{
            console.log(`n:${n}`)},3000)}return(
        <div className = "app">
           <p>{n}</p> 
           <p>
               <button onClick = {()= > setN(n+1)}>+1</button>
               <button onClick = {log}>log</button>
           </p> 
        </div>)}Copy the code
  • UseState simple principle
// Self-implement -- principle
import React from 'react'
import ReactDom from 'react-dom'
const rootElement = document.getElementById("root")

let _state = []
let index = 0
fucntion myUseState(initialValue){
    const currentIndex = index
    index+=1
    _state[currentIndex] = _state[currentIndex] || initialValue
    const setState= (newState) = >{
        _state[currentIndex] = newState;
        render()
    }
    return[_state[currentIndex],setState]
}

const render=() = >{
    index =0
    ReactDom.render(<App />,rootElement)
}

function APP(props){
    const [n,setN] = myUseState(0)
    const [m,setM] = myUseState(0)
    return(
        <div className = "app">
            <p>{n}</p>
            <p>
                <button onClick = {() => {setN(n+1)}}>+1</button>
            </p>
            <p>{m}</p>
            <p>
                <button onClick = {() => {setN(m+1)}}>+1</button>
            </p>
        <div>
    )
}

ReactDom.render(<App />,rootElement)
Copy the code

2.2 useReducer

  • Create the initial value initialData
  • Reducer (state,action)
  • Pass it to useState to get the read and write apis
  • Write API({type:” XXX “})
import React, { useState, useReducer } from "react";
import ReactDOM from "react-dom";
const initial = {
    n: 0
};

const reducer = (state, action) = > {
    if (action.type === "add") {
        return { n: state.n + action.number };
    } else if (action.type === "multi") {
        return { n: state.n * 2 };
    } else {
        throw new Error("unknown type"); }};function App() {
    const [state, dispatch] = useReducer(reducer, initial);
    const { n } = state;
    const onClick = () = > {
        dispatch({ type: "add".number: 1 });
    };
    const onClick2 = () = > {
        dispatch({ type: "add".number: 2 });
    };
    return (
    <div className="App">
        <h1>n: {n}</h1>
        <button onClick={onClick}>+ 1</button>
        <button onClick={onClick2}>+ 2</button>
    </div>
    );
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Copy the code

2.3. useContext

  • UseContext can be used not only throughout, but also across different components
  • UseContext is not response-style. If you change the themeContext value in one module, the other module will not notice the change
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";

const rootElement = document.getElementById("root");
const themeContext = React.createContext(null);
function App() {
    const [theme, setTheme] = React.useState("red");
    return (
        <themeContext.Provider value={{ theme.setTheme}} >
            <div className={`AppThe ${theme} `} >
                <p>{theme}</p>
                <div>
                    <ChildA />
                </div>
                <div>
                    <ChildB />
                </div>
            </div>
        </themeContext.Provider>
    );
}
function ChildA() {
    const { setTheme } = React.useContext(themeContext);
    return (
        <div>
            <button onClick={()= > setTheme("red")}>red</button>
        </div>
    );
}

function ChildB() {
    const { setTheme } = React.useContext(themeContext);
    return (
        <div>
            <button onClick={()= > setTheme("blue")}>blue</button>
        </div>
    );
}
ReactDOM.render(<App />, rootElement);
Copy the code

2.4. useRef & forwardRef

  • The state of being throughout
  • UseRef can be used not only for divs, but also for arbitrary data
  • Because the props class does not contain the ref, the forwardRef is required
import React from "react";
import ReactDOM from "react-dom";
const rootElement = document.getElementById("root");

function App() {
    const nRef = React.useRef(0);
    const update = React.useState()[1];
    const log = () = > setTimeout(() = > console.log(`n: ${nRef.current}`), 1000);
    return (
        <div className="App">
        <p>{ref.current} there is no real-time update</p>
        <p>
            <button onClick={()= > {nRef.current += 1; update(nRef.current)}}>
                +1
            </button>
            <button onClick={log}>log</button>
        </p>
        </div>
    );
}
ReactDOM.render(<App />, rootElement);
Copy the code
import React, { useRef } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
    const buttonRef = useRef(null);
    return (
        <div className="App">
            <Button3 ref={buttonRef}>button</Button3>
        </div>
    );
}
const Button3 = React.forwardRef((props, ref) = > {
    return <button className="red" ref={ref} {. props} / >;
});
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Copy the code

2.5. memo & useMemo & useCallback

  • React defaults to redundant render
  • If the props are unchanged, there is no need to execute the function component again
  • When there are functions in props, useMemo is needed to support function reuse
  • The first argument to useMemo is ()=>value. The second argument is dependent on [m,n].
  • The new value is computed only when the dependency changes, and the previous value is reused
  • If value is a function, write useMemo(()=>(x)=>{console.log(x)})
  • UseCallback ((x) = > {the console. The log (x)}, [m]) is equivalent to useMemo (() = > (x) = > {the console. The log (x)}, [m])
import React, { useMemo } from "react";
import ReactDOM from "react-dom";
import "./styles.css";

function App() {
    const [n, setN] = React.useState(0);
    const [m, setM] = React.useState(0);
    const onClick = () = > {
        setN(n + 1);
    };
    const onClick2 = () = > {
        setM(m + 1);
    };
    const onClickChild = useMemo(() = > {
        const fn = div= > {
            console.log("on click child, m: " + m);
            console.log(div);
        };
        return fn;
    }, [m]); // If [m] is changed to [n], the old m is printed
    return (
        <div className="App">
            <div>
                <button onClick={onClick}>update n {n}</button>
                <button onClick={onClick2}>update m {m}</button>
            </div>
            <Child2 data={m} onClick={onClickChild} />
        </div>
    );
}

function Child(props) {
    console.log("Child executed");
    console.log("Let's say there's a lot of code here.");
    return <div onClick={e= > props.onClick(e.target)}>child: {props.data}</div>;
}
const Child2 = React.memo(Child);

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
Copy the code

2.6. useEffect & useLayoutEffect

  • UseEffect runs after each render (afterRender is better)
  • UseEffect is executed after the browser renders and useLayoutEffect is executed before the browser renders
  • UseLayoutEffect is always executed before useEffect

2.7. Custom hook

//index.js
import React, { useRef, useState, useEffect } from "react";
import ReactDOM from "react-dom";
import useList from "./hooks/useList";

function App() {
    const { list, deleteIndex } = useList();
    return (
        <div className="App">
            <h1>List</h1>
            {list ? (
                <ol>
                    {list.map((item, index) => (
                        <li key={item.id}>
                        {item.name}
                            <button
                                onClick={()= > {
                                    deleteIndex(index);
                                }}
                            >
                                x
                            </button>
                        </li>
                    ))}
                </ol>) : (" Loading..." )}</div>
    );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

//useList.js
import { useState, useEffect } from "react";

const useList = () = > {
    const [list, setList] = useState(null);
    useEffect(() = > {
        ajax("/list").then(list= >{ setList(list); }); } []);// [] Make sure to run only the first time
        return {
            list: list,
            addItem: name= > {
            setList([...list, { id: Math.random(), name: name }]);
        },
        deleteIndex: index= > {
            setList(list.slice(0, index).concat(list.slice(index + 1))); }}; };export default useList;
function ajax() {
return new Promise((resolve, reject) = > {
    setTimeout(() = > {
            resolve([
            { id: "1".name: "Frank" },
            { id: "2".name: "Jack" },
            { id: "3".name: "Alice" },
            { id: "4".name: "Bob"}]); },2000);
    });
}
Copy the code
5. Simulate the declaration cycle
  • When a function component executes, it is equivalent to performing constructor
  • The return value of the function component is the return value of render
  • React.memo and react. useMemo can emulate shouldComponentUpdate
useEffect(() = >{console.log("First render")}, [])// First render
useEffect(() = >{console.log("Arbitrary property change")})  // Arbitrary attribute changes
useEffect(() = >{console.log(Changed "n")},[n])  / / n
useEffect(() = >{
    console.log("Arbitrary property change")
    return () = >{
        console.log("Components are dying.")}})// The component is dying
Copy the code

3. EventHub

/ / data
var money = {
  amount: 100000
}
var user = {
  id: 123123.nickname: 'local tyrants'
}
var store = {
  money: money,
  user: user
}

// eventHub
var fnLists = {}
var eventHub = {
  trigger(eventName, data){
    let fnList = fnLists[eventName]
    if(! fnList){return}
    for(let i = 0; i<fnList.length; i++){
      fnList[i](data)
    }
  },
  on(eventName, fn){
    if(! fnLists[eventName]){ fnLists[eventName] = [] } fnLists[eventName].push(fn) } }var x = {
  init(){
    eventHub.on('I want to spend money'.function(data){  // subscribe
      store.money.amount -= data  // reducer
      render()
    })
  }
}
x.init()
class App extends React.Component {
  constructor(){
    super(a)this.state = {
      store: store
    }
  }
  
  render(){
    return (
      <div className="root"> 
        <BigPapa money={this.state.store.money} />
        <YoungPapa money={this.state.store.money}/>
      </div>)}}class BigPapa extends React.Component{
  constructor(){
    super()}render(){
    return (
    <div className="papa">Big daddy {this. Props. Money. Amount}<Son1 money={this.props.money}/>
      <Son2 money={this.props.money}/>
    </div>)}}class YoungPapa extends React.Component{
  constructor(){
    super()}render(){
    return (
    <div className="papa">Second dad {this. Props. Money. Amount}<Son3 money={this.props.money}/>
      <Son4 money={this.props.money}/>
    </div>)}}class Son1 extends React.Component{
  constructor(){
    super()}render(){
    return (
    <div className="son">Son 1 {this. Props. Money. Amount}</div>)}}class Son2 extends React.Component{
  constructor(){
    super()}x(){
    // action
    eventHub.trigger('I want to spend money' /*action type*/.100) // payload
  }
  render(){
    return (
    <div className="son">2 son {this. Props. Money. The amount}<button onClick={()= >This. (x)} > consumption</button>
    </div>)}}class Son3 extends React.Component{
  constructor(){
    super()}render(){
    return (
    <div className="son">Son 3 {this. Props. Money. Amount}</div>)}}class Son4 extends React.Component{
  constructor(){
    super()}render(){
    return (
    <div className="son">Son 4 {this. Props. Money. Amount}</div>)}}function render(){
  ReactDOM.render(<App/>.document.querySelector('#app'))}Copy the code

Four story.

5. Dom Diff

6. CSS scheme

Vue vs. React

1. Comparison of programming models