Directorio de artículos
1. Introducción al marco React
-
introducir
CS combinado con BS:
React
esteVue
tipo de marco transfiere algunas de las funciones del servidor al cliente. CombinaCS
yBS
. El cliente solo necesita solicitar al servidor una vez, y el servidor devolverá todos los códigos js al cliente y todas las operaciones interactivas ya no dependen del servidor. El cliente solo utilizajson
la comunicación cuando necesita datos del servidor, en otras ocasiones utilizajs
operaciones y almacena datos temporalmente, lo que reduce en gran medida la presión sobre el servidor. -
Funciones de reacción
○ Árbol DOM virtual
React
Al simularDOM
, se minimiza la interacción conDOM
. Copie completamente el árbol de la página web y guardeDOM
un árbol virtualDOM
en la memoria.○ Basado en datos
Mantenga el
DOM
árbol virtual. Cuando se descubre que algunos nodos han cambiado,DOM
no es necesario modificar el árbol original (cada área vista en la página web). Por ejemplo, cuando ciertas ramas pueden cambiar, el árbol virtual primero será modificado Estos nodos luego se comparan con los nodos originales. Sólo se modificarán los nodos que realmente cambien.
○ archivo JSXPara crear interfaces de usuario interactivas,
JSX
.JSX
La versión completa es unaJavaScript
extensión de sintaxis que simplifica enormemente la creación de componentes. AdmiteHTML
referencias y facilita la representación de componentes secundarios. Es esencialmente un conjunto deReact
atajos de escritura. Usar algunas reglascreateElement
puede hacer que el código fuente sea más legible y sencillo. Primero, escriba un archivo jsx. Cuando se ejecute, eljsx
archivo escrito se compilará enjs
un archivo jsx. Después de la compilación,js
el archivo se ejecutará en el navegador. -
Función de reacción
Generalizar y optimizar el marco del lenguaje,
React
principalmente para la construcciónUI
. PuedeReact
pasar varios tipos de parámetros aquí, como códigos de declaración para ayudarlo a representarUI
,HTML DOM
elementos estáticos, variables dinámicas e incluso componentes de aplicaciones interactivas. Tiene un rendimiento excepcional y una lógica de código simple.
2. Entorno de configuración
- Instalar
Git Bash
Git bash Enlace de descarga
Tutorial de instalación de Git Bash - Instalar
Node.js
Nodejs Enlace de descarga
Tutorial de instalación de Nodejs - Abra
create-react-app
la instalaciónGit Bash
e ingrese directamente el siguiente comando para ejecutarnpm i -g create-react-app
- Cree un proyecto de React llamado React App.
Haga clic derecho en el directorio de destino (el directorio donde almacena el proyecto) para abrir Git Bash y ejecutar el siguiente comando.create-react-app react-app # react-app可以替换为其它名称
- Inicie el proyecto
. Ingrese al directorio. Ingrese a la capa de aplicación de reacción. Abra Git Bash e ingrese el siguiente comando.npm start # 启动应用
3. Componente
Un componente es similar a una clase: combina algunas funciones HTML, datos y eventos en un componente.
-
Definir componentes: después de definir los componentes, debe representar los componentes. index.js es el punto de entrada para todos los js e introducir los componentes React y Component.
// 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> );
-
Introducción y uso de React Fragment:
(1)
render()
El método solo puede devolver una etiqueta y su contenido. Si desea devolver varias etiquetas paralelas, deben incluirse en una etiqueta.
(2) Los componentes pueden permitir que los métodos devuelvan múltiples elementosReact.Fragment
sin crear elementos adicionales . Permite agrupar sublistas sin agregarles etiquetas adicionales.DOM
render()
Fragments
DOM
Lo que se entiende es que cuando definimos componentes,
return
el paquete más externodiv
a menudo no quiere ser representado en la página, por lo queFragment
se deben usar componentes.class Box extends Component { state = { } render() { return ( <React.Fragment> <h1> Hello world</h1> <button>left</button> <button>right</button> </React.Fragment> ); } }
-
Al escribir etiquetas js y html en jsx, las etiquetas
jsx
se pueden definir en cualquier lugarhtml
, pero tenga en cuenta que al escribir código en etiquetas,jsx
debe encerrarlas y solo se pueden escribir expresiones.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}`; }
-
Establecer estilo
Al configurar el nombre de la clase en la etiqueta html debajo del archivo jsx para el estilo css, debe
class =" "
escribirlo comoclassName
. Dado que las etiquetas html y las declaraciones js se mezclan en jsx, escribir una clase puede entrar en conflicto con la clase del mismo nombre en el js real.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> ); }
Equivalente a:
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> ); }
-
Cambio de estilo basado en datos
Se asociará
style
con un valor (variable local) y se cambiará cambiando el valor que contiene . Cuando una variable local cambia, todos los componentes afectados por este valor a través de la implementación de la interfaz cambian.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> ); }
-
lista de renderizado
map
Función de usoEl método de escritura de clase transversal requiere definir un atributo único para cada elemento de etiqueta
key
para ayudar a encontrar rápidamente el elementoReact
modificado .DOM
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> ); } }
-
Representación condicional
A && B && C ...
: de adelante hacia atrás, devuelve la primerafalse
expresión de. (Si todas son verdaderas, devuelve la última expresión verdadera)
A || B || C ...
: de adelante hacia atrás, devuelve la primeratrue
expresión que sea. (Si todos son falsos, se devuelve la última expresión falsa).逻辑表达式
Es decir, el principio de utilización短路
: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> ); }
-
Eventos vinculantes
eq
button
vincula eventos al botón: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> } }
En este momento, la salida
this
no esBox
la clase, sino el archivoundifind
.Cómo hacer que esto en el método siga perteneciendo a la clase Box:
// Método 1: función de flecha (recomendado)
// Método 2: función de enlaceEl código se muestra a continuación:
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函数 ); }
-
Modificar el valor en estado
Dirigir this.state.x-- no afectará el valor x mostrado del div de la página.
Si desea que la modificación de x en el estado afecte la función de renderizado, debe usar la función setState() (modifique el div re -llamando a render x valor)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> ); } }
-
Modificar propiedades css mediante botones:
Asigne
state
el valor al atributo de un determinado estilo y modifiquestate
el valor mediante el botón para modificarcss
el estilo.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; } }
-
Agregar parámetros a la función de evento
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> ); }
Escribir
handleClickRight()
la función como una función anónima de flecha equivale a: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> ); }
En resumen, los pasos para construir el componente Box son:
- Definir
state
variables y convertirlas en basadas en datosstyle
; - Construya la función handleClickLeft =(step)=>{ } con parámetros y use
setState()
la función para cambiarstate
el valor;
调用setState()能够重新加载 render 函数,才可以对里面的 div 显示进行修改
- Vincula la función escrita al evento de clic del botón
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. Combinación e interacción de los componentes.
-
【Componente combinado】Construcción de componentes
Box
Combine múltiples componentes definidos anteriormente para formarBoxes
componentes y completar属性
la transferencia de valores.
<注:多个相同子组件时,每个子组件需要有唯一 key 值
>○ Cree
Boxes
un componente de clase que contenga variosBox
componentesimport 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;
[Nota] La comunicación entre los componentes de reacción se
props
realiza a través de atributos. Por ejemplo, si un componente principal necesita pasar datos a un componente secundario, cuando el componente represente el componente secundario, pasará directamente los datos como un parámetro de propiedad del secundario. componente.○ paso del valor de estado:
props
devuelveBoxes
el valor del atributo definido pasadoBox
astate
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;
○ Transferencia de etiqueta:
props
pase la subetiquetaBoxes
agregada aBox.children
Box
// 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> ); }
○ Paso del método 1: el componente secundario de React llama al método del componente principal.
Box
Cuando el componente secundario llamaBoxes
al método en el componente principal, aún pasaprops
. Después de que se activa el evento enBox
el componenteonClick
, el valor correspondiente seBoxes
elimina en el componente , es decir, el método de llamar a la etiqueta dentro de la etiqueta.key
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> ); }
○ Paso del método 2: el componente principal de React llama al método del componente secundario.
(Solo se puede llamar a un método de subcomponente y no se puede llamar a una lista de subcomponentes)
// 父组件 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> ); } }