01- react脚手架、jsx语法、组件、遍历、条件渲染、组件内外传值
笔记批注:易错 参考文献 重点 面试题
01 脚手架的使用
01.01 cra(create-react-app)使用;
- vue的脚手架:vite -- 给vue3主要使用。
- react的脚手架:create-react-app;
- 创建一个react应用;create react app
- 创建项目:npx create-react-app myappname
- 初始化,启动项目:yarn install,yarn start
参考文献:https://zh-hans.react.dev/learn/creating-a-react-app
cnpm、yarn、npx、pnpm命令都可以使用;
cra脚手架强制最新的版本,
node版本: 18.x+
01.02 项目目录 以及eject 解析
-
文件:package.json项目配置 与package-lock.json 锁定:有新的版本或者依赖有问题,就锁定在固定的版本,项目如果跑不起来,可以尝试删除;
- react-script 脚手架集成,包较大,基于webPack;
-
public文件夹:
-
静态目录,项目入口页面 -- SPA单页应用入口页面;
-
index.html, icon偏好图标。(其他可以删除)
-
禁止强制缩放代码添加,删除多余的代码
<!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF-8"> <link rel="icon" href="/favicon.ico"> <title>欢迎</title> <meta name="viewport" content="width=device-width, initial-scale=1, user-scalabel=no"> </head> <body> <div id="root"></div> </body> </html>
-
-
src文件夹:全部清空
-
添加index.js
// 主框架 import React from "react" // 导入创建根节点方法,管理虚拟dom,真实dom挂载方法; import ReactDom from "react-dom/client" // const root = ReactDom.createRoot(document.querySelector('#root')); // 调用render方法把虚拟节点渲染到容器上;(vue h函数) const VNode2 = <h1>好好学习</h1> const VNode = React.createElement( 'h1', { style: { color: 'red' }, }, "标题", React.createElement( 'span', { style: { fontSize: '20px', color: 'green' } }, "内容" ) ) // react 没有vue的template,script,style进行模块化管理; // 开发jsx语法 root.render( VNode ) -
项目源码;
-
可不用脚手架,把脚手架的依赖底层源码全部释放, 不可逆 -- npm run eject;
02 react 基础知识
02.01 react开发特性;
- 每个react组件首行引入react框架;
- react所有数据流皆单向,区别于vue双向绑定;
- 一些皆组件,一个组件一个元素;
- jsx (javaScript xml)--使用js和xml格式来编写页面;
-
jsx 中每一个html 片段都是js对象;
-
jsx语法片段被编译成createElement方法,类似vue的template;
-
定义变量,方法( 函数组件)
// 01. 全局变量; const userName = '张三'; const VNode = <h1>好好学习</h1> // 02. 闭包构成局部变量; function VNode() { const userName2 = "张三" return ( <h1>好好学习</h1> ) } // 03,调用VNode方法(实际上就是一个组件),调用render方法把虚拟节点渲染到容器上; root.render( // VNode() // 03.01 首字母必须大写:错误:vNode, v-Node, vnode; <VNode/> ) -
类组件
// 1.类组件定义: 定义普通类,继承Component类; // 2.继承:继承Component类,就必须实现Component类的固定方法 -- render class VNode extends React.Component{ render() { return ( <h2>好好学习</h2> ) } } -
类组件-抽取组件
// 1. 抽取组件; // 1.1 .js或.jsx 作为后缀(没区别) import React from "react"; class VNode extends React.Component { render() { return { <h2>好好学习,天天向上 </h2> } } } export default VNode; // 2. 引入类组件;(导入组件位置一律置顶) import VNode from "./VNode"
-
- vue的组合式抄袭react的函数组件;
- react 16.8之前没有函数式编程,只有类组件
- 遵守es6模块华规则,导出定义组件;
03 条件渲染
03.01 元素条件渲染\样式绑定;
-
条件渲染:
- 元素各条件渲染
- 动态类名;
- 动态样式 classnames;
-
遍历渲染
- map方法;
- key的作用;
-
index.js--代码
import React from "react" import {createRoot} from "react-dom/client" import Todos from "./Todos" createRoot('root').render(<Todos/>) -
Todos.jsx--代码
import React, {Component} from "react"; // 05 - 样式的引用; import './index.css' class Todos extends Component { render() { let data = Array(8).fill("").map((_,i) => ({id:'id-'+i, title:"今日任务开发", state:Math.random()> .5? '完成':"新建" })); let tr = ( <tr key="1"> <td></td><td></td><td></td> </tr> ) let trs =[tr]; let finish = <button>完成</button> let active = <button>激活</button> // 04. map返回的是对象,因此可以直接返回 let trs2 = data.map(item => { return ( <tr key={item.id}> <td>{item.title}</td><td>{item.id}</td><td className="state-cls red">{item.state === '完成' ? finish : active}</td> // 06 - 样式的绑定数据,react 的className只接受一个字符串; <td className={"state-cls red"}>{it.state === "完成"? <button>完成</button> : <button>激活</button>}</td> <td className={it.state === "完成"? "state-cls":"state-cls new"}>it.state</td> // 07 - 样式的绑定,react安装第三方库代替三目运算; <td className={classNames({"state-cls":true, "new":it.state === '新建'})}> </td> </tr> ) }) return { // 01. class 在react中是一个关键字,jsx也是js对象,所以样式名class不能写class,替换为className; <table className="table"> <thead> <tr> <td></td><td></td> </tr> </thead> <tbody> <tr> <td></td><td></td> </tr> // 02. jsx中绑定任何属性数据,语法:{} {tr} // 03. 如果绑定的是一个数组,那么数组中的jsx对象,必须有一个key属性。 {trs} </tbody> </table> } } }
// 1- 安装命令;
// yarn add classnames;
// 2- index.css样式
.state-cls {
font-size: 14px;
color: green;
};
.red {
color: red;
};
.new {
color: orange;
};
- class 在react中是一个关键字,jsx也是js对象,所以样式名class不能写class,替换为className;
- 绑定数组时,必须有一个key属性,key属性在diff算法中的唯一标识;没有key时,数据发生变化时,虚拟dom需要将对象逐个对比查找更新的属性;有key时,可以快速定位到哪个虚拟dom发生变化
- className库-参考文献:npmjs.com/package/classnames
03.02 事件、表单、state数据(组件内部数据)
- 表单绑定事件;
- 事件绑定和this指向;
- 表单功能实现value和onChange;
- state数据;
- state及特点;
- state定义和使用方法;
- setState方法及特性
-
MyForm.jsx
import React from "react" class MyForm extends React.Component { count = 10 // 04 - this 丢失; inputEvt(evt){ console.log(arguments, evt.target.value) console.log(this); } // 04.1 - this获取,通过箭头函数找回; inputEvt = () => { console.log(evt.target.value); console.log(this) this.count = evt.target.value; // 将输入的值回显给表单变量; } // 04.2 - this获取2,使用call,apply,bind方法; getData(evt){ console.log("结果",this.state.count) } render(){ return ( // 01 - react 和vue2一样,顶层元素只能有一个; <div> <input type="text" placeholder="请输入数据"> </div> <hr/> <button>获取数据</button> // 01.2 - 修改后; <> <div> // 03 - 给表单提供一个value属性,没有onChange事件handler,它会被渲染成一个只读属性; <input type="text" placeholder="请输入数据" value={this.count} onChange={this.inputEvt}> </div> <hr /> // 02 - react中绑定事件,{},所有的react的事件都是组合事件 -- react框架把原生事件进行了一个二次封装; <button onChange={this.getData}>获取数据</button> // 04.2.1 this获取2,使用call,apply,bind方法 <button onChange={this.getData.bind(this)}>获取数据</button> <> ) } } export default MyForm -
MyForm.jsx定义数据修改版
import React from "react" class MyForm extends React.Component { // 05 - state名称固定不能变,类似vue的data,并且这个state数据为只读; state = { count : 10, } getData(){ console.log(arguments) } // 04 - this 丢失; inputEvt(evt){ console.log(arguments, evt.target.value) console.log(this); } // 04.1 - this获取,通过箭头函数找回; inputEvt = () => { console.log(evt.target.value); console.log(this) this.count = evt.target.value; // 将输入的值回显给表单变量; // 05 -1 错误赋值方法; this.state.count = evt.target.count; console.log("修改后的数据",this.state.count)//由于Object.freez,因此无法修改; // 05 -2;setState方法正确赋值方法; this.setState({ count: count: evt.target.value }) } render(){ return ( // 01 - react 和vue2一样,顶层元素只能有一个; <div> <input type="text" placeholder="请输入数据"> </div> <hr/> <button>获取数据</button> // 01.2 - 修改后; <> <div> // 03 - 给表单提供一个value属性,没有onChange事件handler,它会被渲染成一个只读属性; <input type="text" placeholder="请输入数据" value={this.state.count} onChange={this.inputEvt}> </div> <hr /> // 02 - react中绑定事件,{},所有的react的事件都是组合事件 -- react框架把原生事件进行了一个二次封装; <button onChange={this.getData}>获取数据</button> <> ) } } export default MyForm
- react 和vue2一样,顶层元素只能有一个;
- react中绑定事件,{},所有的react的事件都是组合事件 -- react框架把原生事件进行了一个二次封装,所有的事件名字和原生事件一样,区别在于原生事件名全部时小写,react组合事件是驼峰书写;
1. onchange ==> onChange; onmouseover ==>onMouseOver;
2. arguments 拿到的是合成事件:SyntheticBaseEvent- 合成事件与组合事件
1. 参考文献:https://juejin.cn/post/7525039240528461839;
2. 合成事件对象e,原生事件对象e.nativeEvent。打印结果:SytheticEvent, MouseEvent;
3. 合成事件,非原生单兼容,统一浏览器事件接口,实现框架级性能优化;
4.
- 给表单提供一个value属性,没有onChange事件handler,它会被渲染成一个只读属性;
- react 中的视图、数据、事件:事件不能直接改变视图,只能先改变数据,数据再改变视图;
1. change事件修改数据时,需要主动调用setState方法;
2. this当心丢失,使用箭头函数或者.bind解决;
3. react 中内部数据中都是state
03.03 props数据(组件外传值)
- props 及特点;
- react中外部数据都是props;
- 父子组件通信;
- 解构获取值
- this.props获取值
-
Cart.jsx代码块
import React ,{Component} from "react" import Item from "./item.jsx"//名称定义合理可以不需要引用; export default Class Cart extends Component { // 1. 放在contructor构造器中没有区别; constructor() { // 1.1 constructor构造器中调用this时,一定先调用super方法; this.state = { list: Array.form(Array(6).fill("").map((item,i) => { id: "cart-" + i, name: "华为手机" + i, price: 3000, count: 1 })) } } render(){ return( <div> <table className="table"> <thead> <tr> <th>商品名称</th> <th>单价</th> <th>数量</th> </tr> </thead> <tbody> { this.state.list.map((it) => { return( // 2.1 循环一定记得加key属性 // 2.2 类似vue传值: <Item key={it.id} key={it.id} name={it.name} price={it.price} count={it.count}/> ) }) } </tbody> </table> </div> ) } }
-
item.jsx
import React, {Component} from "react" export default class Item extends Component { render(){ // 01.1-react绑定数据,类似给实例绑定数据;实例=this console.log(this) // 01.2- react绑定数据,解构; const {name, price, count} = this.props return{ <tr> <td>{this.props.name}化为手机{name}</td> <td>{this.props.price}4000元{price}</td> <td>{this.props.count}数量{count}</td> </tr> } } }
- vscode插件库:es7+React; react的模板生成,输入rcc即可;
04 BUG整理;
04.01 使用cra脚手架页面报错;
- 问题
ctrl+s src下面的文件下时,随机在报错和正常的页面之间切换;
- 错因:
- react 和eslint 冲突;
- 解决:
法1. package.json文件删除eslint-config (项目明确不需要使用eslint-config-react)
法2. node_modules 中的文件版本冲突,删了重装; - 参考文献:
回顾
1.0 脚手架
-
脚手架;
- VUE => Vite;
- React => create-react-app;(cra);
-
安装命令:
- npx create-react-app projectName;
- pnpm install;
- pnpm start;
-
Node版本控制在18.X以上;
-
项目目录;
- public文件夹下index.html代码的简化;(scanable="no",icon图标的路径);
- 初始搭建项目前删除git(提交到react版本管理库),公司的项目不删(项目提交记录)
- src 项目源码:依赖,WEBPACK,沙盒(可以释放但不推荐,且不可撤回)
-
开发特性:
- react引入;
- 组件式开发;
- 单元素;
- 单向数据流;
2.0 React基础知识
-
知识点汇总;
-
模块的基础引用;
-
创建root的组件
import ReactDom from 'react-dom/client' -
创建类的组件;
import React from "react"; -
组件内部使用的函数;
React.createRoot(document.querySelector("#root")).render()ReactDom.createElement('h1',{style:{}},'你好')
-
react创建组件的几种方式;
createElement- 创建对象;
<> <h1>this is a title! </h2> <div>这是表体的基本内容!</div> </> - 继承对象
Component; class Child1 extends Component{render(){return()}}
1. 导入模块
// 1. 导入React.createElement创建挂载组件 // - 格式: ("div",{},...Child) // 2. 导入ReactDom.createRoot 创建根元素的组件; import React from "react"; import ReactDom from "react-dom/client"; const VNode = React.createElement( "div", // 易错为:{type:"div",} { style:{ fontSize:"24px", color: "red" } }, "你好朋友", React.createElement( "button", { style: { width: "100px", height: "80px", } }, "打招呼" ) ) const root = ReactDom.createRoot(document.querySelector("#root")); root.render(VNode);2. 创建react组件
// 1. createElement; const VNode1 = React.createElement( "h1", { style: { color: "red" }, "hello world !", React.createElemtn() } ) -
react 变量的函数的定义;



浙公网安备 33010602011771号