React framework

1. Introduction to React framework


  1. introduce

    CS combined with BS: ReactThis Vuetype of framework transfers some of the server's functions to the client. Combine CSand BS. The client only needs to request the server once, and the server will return all js codes to the client, and all interactive operations no longer depend on the server. The client only uses jsoncommunication when it needs data from the server. At other times, the client uses jsoperations and temporarily stores data, which greatly reduces the pressure on the server.

  2. React features

    ○ Virtual DOM tree

    ReactBy simulating DOM, the interaction with is minimized DOM. Completely copy the tree of the web page and put DOMa virtual DOM tree into the memory.

    ○ Data driven

    Maintain the virtual DOMtree. When it is found that some nodes have changed, the original DOMtree (every area seen on the web page) does not necessarily need to be modified. For example, when certain branches may change, the virtual tree will first be modified. These nodes are then compared with the original nodes. Only the nodes that actually change will be modified.
    Insert image description here
    ○ JSX file

    To build interactive user interfaces, JSX. JSXThe full version of is a JavaScriptsyntax extension that greatly simplifies component creation. It supports HTMLreferences and makes rendering of child components easier. It's essentially a set of Reactwriting shortcuts. Using with some rules createElementcan make the source code more readable and straightforward. First, write a jsx file. When running, the written jsxfile will be compiled into jsx jsfile. After compilation, jsthe file will be run in the browser.

  3. React function

    Generalize and optimize the language framework, Reactmainly for construction UI. You can Reactpass various types of parameters here, such as declaration codes to help you render UI, static HTML DOMelements, dynamic variables, and even interactive application components. It has outstanding performance and simple code logic.

2. Configuration environment


  1. Install Git Bash
    Git bash Download link
    Git Bash installation tutorial
  2. Install Node.js
    Nodejs Download Link
    Nodejs Installation Tutorial
  3. Open create-react-app
    the installation Git Bashand directly enter the following command to execute
    npm i -g create-react-app
    
  4. Create a React project named React App.
    Right-click in the target directory (the directory where you store the project) to open Git Bash and execute the following command.
    create-react-app react-app  # react-app可以替换为其它名称
    
  5. Start the project
    . Enter the directory. Enter the react-app layer. Open Git Bash and enter the following command.
    npm start  # 启动应用
    

3. Component


A component is similar to a class. It combines some HTML, data, and event functions into a component.

  1. Define components: After defining the components, you need to render the components. index.js is the entry point for all js, and introduce React and Component components.

    // box.js 文件
    import React, {
          
           Component } from 'react';  		// 快捷键:imrc 
    
    // 引入React原因:将jsx编译为js
    // 通过React.createElement()
    
    class Box extends Component {
          
          					// 快捷键:CC
        state = {
          
            } 								//局部变量
    
        // component类的函数,用来返回当前组件最后的渲染html结构
        // render方法只能返回一个标签及所包含内容
        render() {
          
           
            return (
                <h1> Hello world</h1>
            );
        }
    }
     
    export default Box;
    
    // index.js 文件
    import React from 'react';
    import ReactDOM from 'react-dom/client';
    import './index.css';
    import 'bootstrap/dist/css/bootstrap.css';   		// 引入bootstrap库
    import Box from './components/box';        			// 引入box
    
    const root = ReactDOM.createRoot(document.getElementById('root'));
    root.render(
      <React.StrictMode>
        <Box /> 										// Box组件,见box.js
      </React.StrictMode>
    );
    
  2. Introduction and use of React Fragment:

    (1) render()The method can only return one label and its content. If you want to return multiple parallel labels, they need to be included in one label.
    (2) Components can allow methods to return multiple elements React.Fragmentwithout creating additional elements. Allows sublists to be grouped without adding extra tags to them.DOM render()Fragments DOM

    The understanding is that when we define components, returnthe outermost package divoften does not want to be rendered to the page, so Fragmentcomponents must be used.

    class Box extends Component {
          
           
    state = {
          
            } 
    render() {
          
           
        return (
            <React.Fragment>
                <h1> Hello world</h1>
                <button>left</button>
                <button>right</button>
            </React.Fragment>
        );
    }
    }
    
  3. When writing js and html tags in jsx, tags
    jsxcan be defined anywhere html , but please note that when writing code in tags, jsxyou need to enclose them, and only expressions can be written in.html js{}{}

    render() {
          
           
        return (
            <React.Fragment>
                <h1>{
          
          this.toString()}</h1>  		// html 标签内写js
                <button className="btn btn-primary">left</button>
                <button>right</button>
            </React.Fragment>
        );
    }
    
    toString(){
          
          
        return `x: ${
            
            this.state.x}`;
        // 或者
        // const {x} = this.state; //ES6写法相当于const xxx = this.state.xxx
        // return `x:${x}`;
    }
    
  4. Set style

    When setting the class name in the html tag under the jsx file for css style, you need to class =" "write it as className. Since html tags and js statements are mixed under jsx, writing a class may conflict with the class of the same name in the actual js.

    className

    return (
            <React.Fragment>
                <h1>{
          
          this.toString()}</h1>     
                <button className="btn btn-primary m-2">left</button>
                <button className="btn btn-success m-2">right</button>
            </React.Fragment>
            // m-2 为 bootstrap 中 margin=2 的简写方式
    );
    

    style

    render() {
          
           
        return (
            <React.Fragment>
            	// style样式:第一层{}代表里面是表达式,第二层{}代表里面是对象,即样式变量的内容
                <div style={
          
          {
          
          
                    width: "50px",
                    height: "50px",
                    backgroundColor: "pink", 
                    color: "white",
                    textAlign: "center",
                    lineHeight: "50px",
                    borderRadius: "5px",
                }}>{
          
          this.toString()}</div>     
                <button className="btn btn-primary m-2">left</button>
                <button className="btn btn-success m-2">right</button>
            </React.Fragment>
        );
    }
    

    Equivalent to:

    styles = {
          
          
        width: "50px",
        height: "50px",
        backgroundColor: "pink", 					// css中所有 - 命名均改为驼峰命名法
    }
    
    render() {
          
           
        return (    								// 标签内 style={this.styele} 即可
            <React.Fragment>
                <div style={
          
          this.styles}>{
          
          this.toString()}</div>     
                <button className="btn btn-primary m-2">left</button>
                <button className="btn btn-success m-2">right</button>
            </React.Fragment>
        );
    }
    
  5. Data driven style change

    Will be associated stylewith a (local variable) value and will be changed by changing the value in it . When a local variable changes, all components affected by this value through the interface implementation change.statestate style

    state = {
          
           
        x: 1,
     } 
     
    getStyles() {
          
          
        let styles = {
          
          
            width: "50px",
            height: "50px",
            backgroundColor: "pink", 
            color: "white",
            textAlign: "center",
            lineHeight: "50px",
            borderRadius: "5px",
            margin: '5px',
        };
    
        if (this.state.x === 0){
          
          
            styles.backgroundColor = 'orange'; // 数据驱动改变style
        }
        return styles;
    }
    
     render() {
          
           
        return (
            // 直接调用 getStyles()函数
            <React.Fragment>
                <div style={
          
          this.getStyles()}>{
          
          this.toString()}</div>     
                <button className="btn btn-primary m-2">left</button>
                <button className="btn btn-success m-2">right</button>
            </React.Fragment>
        );
    }
    
  6. render list

    Use mapfunction

    The traversal class writing method requires defining a unique attribute for each tag element keyto help Reactquickly find the modified DOMelement .

    class Box extends Component {
          
           
        state = {
          
           
            x: 1,
            colors: ['red','green','blue'],   		// 定义渲染列表,这里用来修改div元素内容
         } 
    
        render() {
          
           
    	        return (
    	            <React.Fragment>
    	                {
          
          this.state.colors.map(color => (
    	                    <div key={
          
          color}>{
          
          color}</div> // 这里建立div并将内容赋值为上述列表
    	                ))}             
    	            </React.Fragment>
       	        );
        }
    	}
    
  7. Conditional Rendering
    A && B && C ...: From front to back, return the first falseexpression of . (If all are true, return the last true expression)
    A || B || C ...: From front to back, return the first trueexpression that is . (If all are false, the last false expression is returned.)

    逻辑表达式That is, the principle of utilization 短路:

     render() {
          
                 
        return (     
         	<React.Fragment>   
                {
          
          this.state.colors.length === 0 && <p> No colors</p>}   
                // 即当 colors 有元素时无操作, 即当 colors 无元素时显示 No color
                {
          
          this.state.colors.map(color => (
                    <div key={
          
          color}>{
          
          color}</div>
                ))}             
            </React.Fragment>           
        );
    }
    
  8. Binding events

    eq buttonbinds events to the button:

    class Box extends Component {
          
          
    
        handleClickLeft(){
          
          
            console.log("click left",this); 
        }
    
        handleClickRight(){
          
          
            console.log("click right",this);
        }
        
        render() {
          
           
            //仅仅是绑定函数,而不是在渲染时就将返回值传过来,因此handleClickleft不加()    
            return (
                <React.Fragment>
                    <div style={
          
          this.getStyles()}>{
          
          this.toString()}</div> 
                    <button onClick={
          
          this.handleClickLeft} className="btn btn-primary m-2">left</button>
                    <button onClick={
          
          this.handleClickRight} className="btn btn-success m-2">right</button>          
                </React.Fragment>
        }
    }
    

    At this time, the output thisis not Boxthe class, but the undifind.

    How to make this in the method still belong to the Box class:
    // Method 1: Arrow function (recommended)
    // Method 2: bind function

    code show as below:

    handleClickLeft=()=>{
          
          						 // 法一:箭头函数
        console.log("click left",this); 
    }
    
    handleClickRight(){
          
          
        console.log("click right",this);
    }
    
    render() {
          
           
         return (
            <React.Fragment>
                <div style={
          
          this.getStyles()}>{
          
          this.toString()}</div> 
                <button onClick={
          
          this.handleClickLeft} className="btn btn-primary m-2">left</button>
                <button onClick={
          
          this.handleClickRight.bind(this)} className="btn btn-success m-2">right</button>          
            </React.Fragment>					// 法二:bind函数
        );
    }
    
  9. Modify the value in state

    Direct this.state.x-- will not affect the displayed x value of the page div.
    If you want the modification of x in the state to affect the render function, you must use the setState() function (modify the div by re-calling render x value)

    class Box extends Component {
          
          
        state = {
          
           
            x: 1,
        } 
        
        handleClickLeft = () => {
          
           
               this.setState({
          
          				// setState() 函数
                x: this.state.x - 1
            });
        }
    
        handleClickRight = () => {
          
          
            this.setState({
          
          					// setState() 函数
                x: this.state.x + 1
            });
        }
        
        render() {
          
              
            return (
                <React.Fragment>
                    <div style={
          
          this.getStyles()}>{
          
          this.toString()}</div> 
                    <button onClick={
          
          this.handleClickLeft} className="btn btn-primary m-2">left</button>
                    <button onClick={
          
          this.handleClickRight} className="btn btn-success m-2">right</button>          
                </React.Fragment>
            );
        }
    }
    
  10. Modify css properties through buttons:

    Assign statethe value in to the attribute of a certain style, and modify statethe value through the button to modify cssthe style.

    class Box extends Component {
          
          
        state = {
          
           
            x: 10, 							// state值
        } 
    
        handleClickLeft = () => {
          
           
        this.setState({
          
          
            x: this.state.x - 10			// setState() 修改 state值, 重新调用 render() 函数
        });
    	}
    
        handleClickRight = () => {
          
          
            this.setState({
          
          
                x: this.state.x + 10		// setState() 修改 state值,重新调用 render() 函数
            });
        }
        
        render() {
          
           
            return (
                <React.Fragment>
                    <div style={
          
          this.getStyles()}>{
          
          this.toString()}</div> 
                    <button onClick={
          
          this.handleClickLeft} className="btn btn-primary m-2">left</button>
                    <button onClick={
          
          this.handleClickRight} className="btn btn-success m-2">right</button>          
                </React.Fragment>
            );
        }
    
        getStyles() {
          
          
            let styles = {
          
          
                width: "50px",
                height: "50px",
                backgroundColor: "pink", 
                color: "white",
                textAlign: "center",
                lineHeight: "50px",
                borderRadius: "5px",
                margin: '5px',
                marginLeft: this.state.x,              //  state值赋值给 css 属性值
            };
    
            if (this.state.x === 0){
          
          
                styles.backgroundColor = 'orange';
            }
            return styles;
        }		
    }
    
  11. Add parameters to event function

    handleClickRight = (step) => {
          
          
        this.setState({
          
          
            x: this.state.x + step
        });
    }
    
    handleClickRightTmp = () => {
          
          
        return this.handleClickRight(50);
    }
    
     render() {
          
           
        return (
            <React.Fragment>
                <div style={
          
          this.getStyles()}>{
          
          this.toString()}</div> 
                <button onClick={
          
          this.handleClickLeft} className="btn btn-primary m-2">left</button>
                <button onClick={
          
          this.handleClickRightTmp} className="btn btn-success m-2">right</button>          
            </React.Fragment>
        );
    }
    

    Writing handleClickRight()the function as an arrow anonymous function is equivalent to:

    render() {
          
           
        	//    绑定了一个调用含参 函数 handleClickLeft =(step)=>{ }  的匿名函数  
            return (
                <React.Fragment>
                    <div style={
          
          this.getStyles()}>{
          
          this.toString()}</div> 
                    <button onClick={
          
          ()=>this.handleClickLeft(10)} className="btn btn-primary m-2">left</button>
                    <button onClick={
          
          ()=>this.handleClickRight(10)} className="btn btn-success m-2">right</button>          
                </React.Fragment>
            );
        }
    

In summary, the steps to build the Box component are:

  1. Define statevariables and make them data-driven style;
  2. Construct handleClickLeft =(step)=>{ } function with parameters, and use setState()the function to change statethe value;
    调用setState()能够重新加载 render 函数,才可以对里面的 div 显示进行修改
  3. Bind the written function to the button's click event onClick.
    这里绑定了一个调用含参函数 handleClickLeft =(step)=>{ } 的匿名函数,()=>this.handleClickRight(10)
    class Box extends Component {
          
          
    	
    	// 1. 定义 state,并使得数据驱动style
        state = {
          
           
            x: 10,
        } 
    	
    	// 2. 通过 handleClickLeft =(step)=>{ } 带参函数 与 setState()  改变state值
    	//    并能够重新加载 render 函数来对里面的 div 显示进行操作
        handleClickLeft = (step) => {
          
           
            this.setState({
          
          
                x: this.state.x - step
            });
        }
    
        handleClickRight = (step) => {
          
          
            this.setState({
          
          
                x: this.state.x + step
            });
        }
        
        render() {
          
           
        	// 3. 给事件绑定函数:通过 render 函数里,按钮事件绑定函数。
        	//    绑定了一个调用含参函数 handleClickLeft =(step)=>{ }  的匿名函数  
            return (
                <React.Fragment>
                    <div style={
          
          this.getStyles()}>{
          
          this.toString()}</div> 
                    <button onClick={
          
          ()=>this.handleClickLeft(10)} className="btn btn-primary m-2">left</button>
                    <button onClick={
          
          ()=>this.handleClickRight(10)} className="btn btn-success m-2">right</button>          
                </React.Fragment>
            );
        }
    
        getStyles() {
          
          
            let styles = {
          
          
                width: "50px",
                height: "50px",
                backgroundColor: "pink", 
                color: "white",
                textAlign: "center",
                lineHeight: "50px",
                borderRadius: "5px",
                margin: '5px',
                marginLeft: this.state.x,	// 数据驱动 style
            };
    
            if (this.state.x === 0){
          
          
                styles.backgroundColor = 'orange';
            }
            return styles;
        }
    }
    

4. Combination and interaction of Component components


  1. 【Combined Component】Construction of components

    BoxCombine multiple components defined above to form Boxescomponents and complete 属性the transfer of values.
    < 注:多个相同子组件时,每个子组件需要有唯一 key 值>

    ○ Create Boxesa class component containing multiple Boxcomponents

    import React, {
          
           Component } from 'react';
    import Box from './box';
    
    class Boxes extends Component {
          
          
    	// 1. 设置 state 变量,包括 Box 组件的唯一 key 值与 x 坐标值。
        state = {
          
            
            boxes:[
                {
          
          id: 1, x: 10},
                {
          
          id: 2, x: 10},
                {
          
          id: 3, x: 100},
                {
          
          id: 4, x: 10},
                {
          
          id: 5, x: 10},
            ]
        } 
        // 2. render 函数返回多个 box 组件,通过 map 列表,逐一建立并赋值多个 Box 组件
       	//    将 box.id 赋值给组件唯一 key,将 box.x 赋值给 Box 组件的 x
        render() {
          
           
            return (
                <React.Fragment>
                   {
          
          this.state.boxes.map((box)=>(
                        <Box
                            key = {
          
          box.id} // id
                            x = {
          
          box.x}    // 这里会自动找到 Box 组件里的 x 赋值并存储在 props 中
                            			   // 但仅仅是修改了x,并不会改变前端的显示
                        />
                   ))}
                </React.Fragment>
            );
        }
    }
    
    export default Boxes;
    

    [Note] Communication between react components is propsdone through attributes. For example, if a parent component needs to pass data to a child component, then when the component renders the child component, it will directly pass the data as a property parameter of the child component.

    ○ state value passing: propsReturn Boxesthe defined attribute value passed Boxtostate

    class Box extends Component {
          
          
        state = {
          
           
            // props类似于state,存储除key以外属于 box 的所有属性
            // Boxes 建立的 Box 赋值的 x 存到了 props 里
            // 通过 props 传递给了每个 Box
            x: this.props.x,
        } 
    
        handleClickLeft = (step) => {
          
           
            this.setState({
          
          
                x: this.state.x - step
            });
        }
    
        handleClickRight = (step) => {
          
          
            this.setState({
          
          
                x: this.state.x + step
            });
        }
        
        render() {
          
           
            return (
                <React.Fragment>
                    <div style={
          
          this.getStyles()}>{
          
          this.toString()}</div> 
                    <button onClick={
          
          ()=>this.handleClickLeft(10)} className="btn btn-primary m-2">left</button>
                    <button onClick={
          
          ()=>this.handleClickRight(10)} className="btn btn-success m-2">right</button>          
                </React.Fragment>
            );
        }
    
        getStyles() {
          
          
            let styles = {
          
          
                width: "50px",
                height: "50px",
                backgroundColor: "pink", 
                color: "white",
                textAlign: "center",
                lineHeight: "50px",
                borderRadius: "5px",
                margin: '5px',
                marginLeft: this.state.x,
            };
    
            if (this.state.x === 0){
          
          
                styles.backgroundColor = 'orange';
            }
            return styles;
        }
    
        toString(){
          
          
            return `x: ${
            
            this.state.x}`;	        
        }
    }
     
    export default Box;
    

    ○ Label transfer: propspass the Boxesadded Box.childrensub-label toBox

     // Boxes.jsx文件
     render() {
          
           
        return (
            <React.Fragment>
               {
          
          this.state.boxes.map((box)=>(
                    <Box key = {
          
          box.id} x = {
          
          box.x}> 
                        <p>Box :</p>				// 将 Box 的闭合标签写为双标签
                        <div>{
          
          box.id}</div>			// 可在 Box 标签内增加其它标签,属性名为 Box.children
                    </Box>							// 并存储到了 props 中																
               ))}
            </React.Fragment>
        );
    }
    
    // Box.jsx 文件
    render() {
          
           
        console.log(this.props); 
        return (
            <React.Fragment>
                {
          
          this.props.children[0]}			// 通过 props 所存储的 children 将增加的标签传递给Box
                <div style={
          
          this.getStyles()}>{
          
          this.toString()}</div> 
                <button onClick={
          
          ()=>this.handleClickLeft(10)} className="btn btn-primary m-2">left</button>
                <button onClick={
          
          ()=>this.handleClickRight(10)} className="btn btn-success m-2">right</button>          
            </React.Fragment>
        );
    }
    

    ○ Method passing 1: React child component calls the method of parent component.

    BoxWhen the child component calls Boxesthe method in the parent component, it still passes props. After the event is triggered in Boxthe component onClick, the corresponding value is Boxesdeleted in the component , that is, the method of calling the label within the labelkeyBoxBoxBoxes

     // Boxes.jsx 文件
     // 1. Boxes.jsx 文件中写删除的方法
     handleDelete = (id) => {
          
          
        // filter: boxes列表的元素依次判断,若表达式为true则留下,否则删掉
        // 即若id不等留下来,相等删除
        const newboxes = this.state.boxes.filter(
            (x)=>(x.id !== id)
        );
        this.setState({
          
          
            boxes: newboxes
        })
     }
    
     render() {
          
           
        if(this.state.boxes.length === 0){
          
          
            return <div className='alert alert-dark'>没有元素可以删除了!!!</div>
        }
        return (
        	// 2. 将所写删除方法定义为标签的 onDelete 属性传递给 Box(会存储在 props中)
            <React.Fragment>
               {
          
          this.state.boxes.map((box)=>(
                    <Box key = {
          
          box.id} id={
          
          box.id} x = {
          
          box.x} onDelete = {
          
          this.handleDelete}> 
                        <p>Box :</p>
                        <div>{
          
          box.id}</div>   
                    </Box>
               ))}
            </React.Fragment>
        );
    }
    
    // Box.jsx 文件
     render() {
          
              
        return (
            <React.Fragment>
                {
          
          this.props.children[0]}
                <div style={
          
          this.getStyles()}>{
          
          this.toString()}</div> 
                <button onClick={
          
          ()=>this.handleClickLeft(10)} className="btn btn-primary m-2">left</button>
                <button onClick={
          
          ()=>this.handleClickRight(10)} className="btn btn-success m-2">right</button>
                // 3. Box 调用 Boxes 的删除方法 :
                //    Box 中的 Button 的 onClick 事件,绑定匿名函数来调用含参的删除方法        
                <button onClick={
          
          ()=>this.props.onDelete(this.props.id)} className='btn btn-danger m-2'> Delete </button>
            </React.Fragment>
        );
    }
    

    ○ Method passing 2: The React parent component calls the method of the child component.

    (Only one subcomponent method can be called, and list subcomponents cannot be called)

    // 父组件
    class Boxes extends Component {
          
          
    
    	// 1. Boxes 父组件中写入
    	setChildRef = (ref) => {
          
          
            this.ChildRef = ref;
        }
        
    	// 3. Boxes 父组件中写调用 Box 子组件的方法
        handleReset = () =>{
          
          
            this.ChildRef.handleRE()
        }
    	
    	render() {
          
               
            return (
                <React.Fragment>
       // 4. 将父组件方法绑定onClick单击事件中,即可实现单击调用子组件的方法
                    <button onClick={
          
          this.handleReset} className='btn btn-primary'> Clear </button>
                   {
          
          this.state.boxes.map((box)=>( 
       // 2. Boxes 父组件的 Box 子组件标签内增加 ref 属性,并将 setChildRef 传递过来
                        <Box key = {
          
          box.id} ref={
          
          this.setChildRef} id={
          
          box.id} x = {
          
          box.x} onDelete = {
          
          this.handleDelete}> 
                            <p>Box :</p>
                            <div>{
          
          box.id}</div>   
                        </Box>
                   ))}
                </React.Fragment>
            );
        }
     }
    
    // 子组件
    class Box extends Component {
          
          
        
        state = {
          
           
            x: this.props.x,
        } 
    	
    	//  子组件中被调用的方法
        handleRE = () =>{
          
          
            this.setState({
          
          
                x: 0
            });
        }
    
    
        render() {
          
           
            return (
                <React.Fragment>
                    ......
                </React.Fragment>
            );
        }
    }
    
    

Guess you like

Origin blog.csdn.net/qq_46201146/article/details/125547585