当前位置: 首页 > news >正文

react实例与总结(一)

目录

一、简单认识

1.1、特点

1.2、JSX语法规则

1.3、函数组件和类式组件

1.4、类组件三大属性state、props、refs

1.4.1、state

1.4.2、props

1.4.3、refs

1.5、事件处理

1.6、收集表单数据—非受控组件和受控组件

1.7、高阶函数—函数柯里化

1.8、生命周期—新旧对比

1.8.1、旧16+

1.8.2、新17+

1.8.3、对比

1.9、DOM的Diffing算法

二、脚手架搭建

2.1、创建项目

  因为真实DOM频繁操作节点会导致页面重绘和重排,影响性能,所以会用虚拟DOM【应用于前端框架】进行跨平台开发

一、简单认识

英文:Getting Started – React

中文:快速入门 – React 中文文档

1.1、特点

(1)采用组件化模式、声明式编码,提高开发效率及组件复用率

(2)在React Native中使用它进行移动端开发

(3)使用虚拟DOM+Diffing算法,减少与真实DOM的交互

1.2、JSX语法规则

(1)、定义虚拟DOM时,不要写引号

(2)、标签中混入js表达式时要用{}

(3)、样式的类名指定不要用class,要用className

(4)、内联样式:要用style={{key:value}}形式

(5)、只有一个根标签,所有标签必须闭合

(6)、标签首字母

若小写字母开头,则将该标签转为html中同名元素;若html中没有该标签对应的同名元素,则报错

若大写字母开头,则react去找对应的组件,若找不到,则报错

在Microsoft Edge安装React Developer Tools扩展进行开发辅助,以下语法基于16+版本。

1.3、函数组件和类式组件

前者适用于简单组件(只能使用props属性,除非使用Hooks里的useRef 和 useState ),后者适用于复杂组件

    <div id="root"></div><script type="text/babel">// 1.创建函数式组件function MyComponent() {return <h1>我是函数式组件</h1>;}// 2.渲染组件到页面ReactDOM.render(<MyComponent />, document.getElementById("root"));</script>
      // 1.创建类式组件class MyComponent extends React.Component {render() {//  render()中的this 指向当前组件实例return <h1>我是类式组件</h1>;}}// 2.渲染组件到页面ReactDOM.render(<MyComponent />, document.getElementById("root"));

1.4、类组件三大属性state、props、refs

注意:类组件里的render()会调用1+N次(只要state更新就变)

1.4.1、state

      class MyMood extends React.Component {state = {isGood: false,number: 0,};render() {const { isGood, number } = this.state;return (<div><h1 onClick={this.changeMyMood}>今天心情很{isGood ? "好" : "糟糕"}</h1><h1 onClick={() => this.setState({ number: 10 })}>打个{number}分</h1></div>);}changeMyMood = () => {this.setState({isGood: !this.state.isGood,});};}ReactDOM.render(<MyMood />, document.getElementById("root"));

总结:

(1)、状态必须通过setState进行更新,且更新是一种合并,不是替换;

(2)、组件中render()方法中的this为组件实例对象,当this为undefined,如何解决?

a.通过函数对象的bind()强制绑定this;b.箭头函数

1.4.2、props

<div id="root1"></div>
<div id="root2"></div>
<div id="root3"></div><script type="text/babel">class Person extends React.Component {// 使用 PropTypes 进行类型检查static propTypes = {name: PropTypes.string.isRequired,//必传项sex: PropTypes.string,age: PropTypes.number,onSuccess: PropTypes.func};// 设置默认属性static defaultProps = {age: 18,sex: "男"};render() {const { name, age, sex } = this.props;return (<ul><li>姓名:{name}</li><li>性别:{sex}</li><li>年龄:{age + 1}</li></ul>);}}
ReactDOM.render(<Person name="tom" age={18} sex="男" onSuccess={onSuccess}/>, document.getElementById("root1"));// 批量传递 props 【{...x}】const backData = { name: '后端返回数据', age: 19, sex: "女" }; 
ReactDOM.render(<Person {...backData} />, document.getElementById("root2"));
ReactDOM.render(<Person name="jack" age={20}/>, document.getElementById("root3"));function onSuccess() {console.log('执行事件');}</script>

函数组件Props

      function Person(props) {const { name, age, sex } = props;return (<ul><li>姓名:{name}</li><li>性别:{sex}</li><li>年龄:{age + 1}</li></ul>);}Person.propTypes = {name: PropTypes.string.isRequired, sex: PropTypes.string,age: PropTypes.number,};
ReactDOM.render(<Person name='tom' age={18} sex="男" />, document.getElementById("root"));

总结:

(1)、组件标签的所有属性都保存在props中,但是组件内部不要修改props数据;

(2)、批量传递:{...item}、类型检查:PropTypes、默认属性:defaultProps

1.4.3、refs

class MyComponent extends React.Component {showData = () => {const { input1 } = this.refs;alert(input1.value);};showData2 = () => {const { input2 } = this;alert(input2.value);};myRef=React.createRef();showData3 = () => {alert(this.myRef.current.value);};
render() {return (<div>{/* 1、字符串形式 */}<input ref="input1" type="text" placeholder="点击按钮提示数据" />&nbsp;<button onClick={this.showData}>点击提示左侧数据</button>&nbsp;{/* 2、回调函数形式 */}<inputref={(c) => (this.input2 = c)}onBlur={this.showData2}type="text"placeholder="失去焦点提示数据"/>&nbsp;{/* 3、createRef API:存储被ref标识的节点,“专人专用” */}<inputref={this.myRef}onBlur={this.showData3}type="text"placeholder="createRef的使用"/></div>);}
}
ReactDOM.render(<MyComponent />, document.getElementById("root"));

总结:

(1)、直接访问和操作DOM元素或React组件实例;

(2)、使用React.createRef()或者回调函数形式(类组件);使用useRef(函数组件)

1.5、事件处理

总结:

(1)、通过onXxx属性指定事件处理函数,事件通过事件委托【委托给组件最外层的元素】处理的;

(2)、通过event.target得到发生事件的DOM元素对象【高效】;

(3)、原生Js事件使用onclick,而React事件使用onClick【为了更好的兼容性】。

1.6、收集表单数据—非受控组件和受控组件

特性受控组件 (Controlled)非受控组件 (Uncontrolled)
值存储位置存储在React组件的state存储在DOM中(使用ref访问)
表单元素控制React通过state控制表单的值浏览器控制,React不干涉
更新方式用户输入时通过onChange更新state使用ref获取值,无需触发事件
适用场景需要表单验证、交互或复杂逻辑时简单表单,且无需与React状态紧密交互
代码复杂度稍微复杂,需要维护状态和事件处理简单,直接使用ref访问DOM

1.7、高阶函数—函数柯里化

总结:

高阶函数:如果函数的参数或者返回值是函数,那么这个函数就是高阶函数。

      常见有:Promise、setTimeout、arr.map()、call、apply、bind、...

函数柯里化:通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的一种函数编码形式。·

或者:直接在视图上使用箭头函数,同时传入属性值和对应的event。

1.8、生命周期—新旧对比

1.8.1、旧16+

  <script type="text/babel">class MyComponent extends React.Component {constructor(props) {console.log("构造器---constructor");super(props);this.state = { count: 0 };}componentWillMount() {console.log("组件将要挂载---componentWillMount");}componentDidMount() {console.log("组件挂载完毕---componentDidMount");}shouldComponentUpdate(nextProps, nextState) {console.log("组件是否需要更新---shouldComponentUpdate");return true;}componentWillUpdate() {console.log("组件将要更新---componentWillUpdate");}componentDidUpdate() {console.log("组件更新完毕---componentDidUpdate");}componentWillUnmount() {console.log("组件即将卸载---componentWillUnmount");}moveIt = () => {ReactDOM.unmountComponentAtNode(document.getElementById("root")); //卸载};addIt = () => {const { count } = this.state;this.setState({ count: count + 1 });};forceIt = () => {this.forceUpdate();};render() {console.log("挂载页面---render");const { count } = this.state;return (<div><h2>当前求和为:{count}</h2><button onClick={this.addIt}>点击+1</button><button onClick={this.moveIt}>销毁</button><button onClick={this.forceIt}>强制更新</button></div>);}}// A和B是父子关系class A extends React.Component {state = { carName: '奔驰' };changeCar = () => {this.setState({ carName: '宝马' });};render() {return (<div><div>A页面</div><button onClick={this.changeCar}>换车</button><B carName={this.state.carName} /></div>);}}class B extends React.Component {componentWillReceiveProps(nextProps) {console.log('B组件接收到新的属性(第一次不调)', nextProps);}render() {return <div>B组件接收的车是:{this.props.carName}</div>;}}// ReactDOM.render(<MyComponent />, document.getElementById("root"));ReactDOM.render(<A />, document.getElementById("root"));</script>

1.8.2、新17+

    static getDerivedStateFromProps(props,state) {console.log("获取新的属性---getDerivedStateFromProps",props,state);return null;//返回null或者props}ReactDOM.render(<MyComponent count={199} />, document.getElementById("root"));
<style>.list {width: 200px;height: 150px;background-color: skyblue;overflow: auto;}.news {height: 30px;
</style>
class MyComponent extends React.Component {state = { newArr: [] }componentDidMount() {setInterval(() => {const { newArr } = this.stateconst news = '新闻' + (newArr.length + 1)this.setState({ newArr: [news, ...newArr] })}, 1000);}getSnapshotBeforeUpdate(prevProps, prevState) {return this.refs.list.scrollHeight;// 获取更新前的DOM节点}componentDidUpdate(prevProps, prevState, snapshot) {this.refs.list.scrollTop += this.refs.list.scrollHeight - snapshot;}render() {return <div className="list" ref="list">{this.state.newArr.map((item, index) => {return <div className="news" key={index}>{item}</div>})}</div>;}
}

1.8.3、对比

17+在16+的基础上新增了getDerivedStateFromPropsgetSnapshotBeforeUpdate

即将废弃 componentWillMount、componentWillReceiveProps、componentWillUpdate三个钩子。

1.9、DOM的Diffing算法

经典面试题:为啥key不能使用index,而是取id(唯一标识)

总结:
1、使用 index 作为 key
        在列表项的顺序发生变化、增加或删除时,可能会导致错误渲染或状态丢失
        适用于列表项不变,且不涉及删除、增加或排序操作的简单情况。
2、使用 id 作为 key
        更稳定,能够确保元素在更新时保持一致,特别是在列表顺序发生变化时。
       尤其是在动态数据列表(增、删、改、排序等操作)中使用。

二、脚手架搭建

2.1、创建项目

1、全局安装:npm i -g create-react-app【查看是否下载create-react-app --version

2、切换到想创建项目的目录下:create-react-app react_app【Node版本在14+及以上】

3、进入项目文件夹:cd react_app

4、启动项目:npm start【修改package.json,重新下载node_modules、 package-lock.json来修改版本

或者直接用:React--Umi和Dva_react dva-CSDN博客

http://www.lryc.cn/news/534635.html

相关文章:

  • 电路研究9.3——合宙Air780EP中的AT开发指南(含TCP 示例)
  • Qt 数据库SQLite 使用【01】基本功能
  • stm32小白成长为高手的学习步骤和方法
  • 大模型产品Deepseek(五)、本地安装部署(Docker方式)
  • Kafka 的消费offset原来是使用ZK管理,现在新版本是怎么管理的?
  • 基于改进型灰狼优化算法(GWO)的无人机路径规划
  • JS中|=是什么意思?
  • 快速上手Vim的使用
  • RPA与深度学习结合
  • 在阿里云ECS上一键部署DeepSeek-R1
  • 长安汽车发布“北斗天枢2.0”计划,深蓝汽车普及全民智驾
  • Aitken 逐次线性插值
  • docker 安装 Prometheus、Node Exporter 和 Grafana
  • 【LeetCode 热题100】74:搜索二维矩阵(二分、线性两种方式 详细解析)(Go 语言实现)
  • 元数据、数据元、数据元素、数据项 和 主数据的概念
  • 阿里云cdn怎样设置图片压缩
  • 白话文实战Nacos(保姆级教程)
  • 7. 基于DeepSeek和智谱清言实现RAG问答
  • 【数据结构】双向链表(真正的零基础)
  • 【生产变更】- Oracle RAC添加配置ipv6地址
  • Ai无限免费生成高质量ppt教程(deepseek+kimi)
  • python全栈-python基础
  • Python 鼠标轨迹 - 防止游戏检测
  • 力扣 零钱兑换
  • C# OpenCV机器视觉:OSTU算法实现背景差分的自适应分割
  • 快速搭建 Elasticsearch 8 集群:零基础实战与升级注意事项
  • 基于扑克牌分发效果制作时的问题总结
  • 老榕树的Java专题:Redis 从入门到实践
  • 【玩转 Postman 接口测试与开发2_019】第15章:利用 Postman 初探 API 性能测试(含实战截图)
  • 在 Qt 开发中,可以将 QML 封装成库