Article directory
1. Introduction to React framework
-
introduce
CS combined with BS:
React
ThisVue
type of framework transfers some of the server's functions to the client. CombineCS
andBS
. 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 usesjson
communication when it needs data from the server. At other times, the client usesjs
operations and temporarily stores data, which greatly reduces the pressure on the server. -
React features
○ Virtual DOM tree
React
By simulatingDOM
, the interaction with is minimizedDOM
. Completely copy the tree of the web page and putDOM
a virtualDOM
tree into the memory.○ Data driven
Maintain the virtual
DOM
tree. When it is found that some nodes have changed, the originalDOM
tree (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.
○ JSX fileTo build interactive user interfaces,
JSX
.JSX
The full version of is aJavaScript
syntax extension that greatly simplifies component creation. It supportsHTML
references and makes rendering of child components easier. It's essentially a set ofReact
writing shortcuts. Using with some rulescreateElement
can make the source code more readable and straightforward. First, write a jsx file. When running, the writtenjsx
file will be compiled into jsxjs
file. After compilation,js
the file will be run in the browser. -
React function
Generalize and optimize the language framework,
React
mainly for constructionUI
. You canReact
pass various types of parameters here, such as declaration codes to help you renderUI
, staticHTML DOM
elements, dynamic variables, and even interactive application components. It has outstanding performance and simple code logic.
2. Configuration environment
- Install
Git Bash
Git bash Download link
Git Bash installation tutorial - Install
Node.js
Nodejs Download Link
Nodejs Installation Tutorial - Open
create-react-app
the installationGit Bash
and directly enter the following command to executenpm i -g create-react-app
- 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可以替换为其它名称
- 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.
-
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> );
-
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 elementsReact.Fragment
without 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,
return
the outermost packagediv
often does not want to be rendered to the page, soFragment
components must be used.class Box extends Component { state = { } render() { return ( <React.Fragment> <h1> Hello world</h1> <button>left</button> <button>right</button> </React.Fragment> ); } }
-
When writing js and html tags in jsx, tags
jsx
can be defined anywherehtml
, but please note that when writing code in tags,jsx
you 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}`; }
-
Set style
When setting the class name in the html tag under the jsx file for css style, you need to
class =" "
write it asclassName
. 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> ); }
-
Data driven style change
Will be associated
style
with 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.state
state
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> ); }
-
render list
Use
map
functionThe traversal class writing method requires defining a unique attribute for each tag element
key
to helpReact
quickly find the modifiedDOM
element .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> ); } }
-
Conditional Rendering
A && B && C ...
: From front to back, return the firstfalse
expression of . (If all are true, return the last true expression)
A || B || C ...
: From front to back, return the firsttrue
expression 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> ); }
-
Binding events
eq
button
binds 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
this
is notBox
the class, but theundifind
.How to make this in the method still belong to the Box class:
// Method 1: Arrow function (recommended)
// Method 2: bind functioncode 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函数 ); }
-
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> ); } }
-
Modify css properties through buttons:
Assign
state
the value in to the attribute of a certain style, and modifystate
the value through the button to modifycss
the 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; } }
-
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:
- Define
state
variables and make them data-drivenstyle
; - Construct handleClickLeft =(step)=>{ } function with parameters, and use
setState()
the function to changestate
the value;
调用setState()能够重新加载 render 函数,才可以对里面的 div 显示进行修改
- 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
-
【Combined Component】Construction of components
Box
Combine multiple components defined above to formBoxes
components and complete属性
the transfer of values.
<注:多个相同子组件时,每个子组件需要有唯一 key 值
>○ Create
Boxes
a class component containing multipleBox
componentsimport 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
props
done 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:
props
ReturnBoxes
the defined attribute value passedBox
tostate
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:
props
pass theBoxes
addedBox.children
sub-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.
Box
When the child component callsBoxes
the method in the parent component, it still passesprops
. After the event is triggered inBox
the componentonClick
, the corresponding value isBoxes
deleted in the component , that is, the method of calling the label within the labelkey
Box
Box
Boxes
// 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> ); } }