一、React的介绍和特点
React的介绍(技术角度)
- React是什么?
- React:用于构建用户界面的JavaScript库
- React的官网文档:react.docschina.org/learn
React的特点 - 声明式编程
- 声明式编程
- 声明式编程是目前整个大前端开发的模式:Vue、React、Flutter、SwiftUI
- 只需要维护自己的状态,当状态改变时,React可以根据最新的状态去渲染UI界面
React特点 - 组件化开发
- 组件化开发
- 组件化开发页面目前前端的流行趋势,将复杂的界面拆分成一个个小小的组件
- 合理的进行组件的划分和设计
React的特点 - 多平台适配
- 多平台适配
- 2013年,React发布之初主要是开发Web页面
- 2015年,Facebook推出了ReactNative,用于开发移动端跨平台;(目前Flutter非常火爆,但仍有很多公司在使用ReactNative)
- 2017年,FaceBook推出ReactVR,用于开发虚拟现实Web应用程序;(VR也会是一个火爆的应用场景)
二、Hello React案例
Hello React案例说明
- 需求
- 在界面显示文本:Hello World
- 点击下方的按钮,文本改变为 Hello React
Hello World
- 第一步:在界面上通过React显示一个Hello World
- 注意:编写React的script代码中,必须添加 type="text/babel",作用是可以让babel解析jsx的语法
<div id="root"></div>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
const root = ReactDOM.createRoot(document.querySelector('#root'))
// 1.将文本定义为变量
let msg = 'Hello World'
// 2.监听按钮的点击
function btnClick() {
// 2.1 修改文本
msg = 'Hello React'
// 2.2 重新渲染界面
rootRender()
}
// 3.渲染函数
function rootRender() {
root.render((
<div>
<h2>{msg}</h2>
<button onClick={btnClick}>修改文本</button>
</div>
))
}
rootRender()
</script>
- ReactDOM.createRoot 函数:用于创建一个React根,之后渲染的内容会包含在这个根中
- 参数:将渲染的内容,挂载到那个HTML元素上
- 定义一个 id 为 root 的 div
- 参数:将渲染的内容,挂载到那个HTML元素上
- root.render 函数
- 参数:要渲染的根组件
- 可以通过 {} 语法来引入外部的变量或者表达式
三、React开发依赖分析
React的开发依赖
-
开发React必须依赖三个库
- react:包含react所必须的核心代码
- react-dom:react渲染在不同平台所需要的核心代码
- babel:将jsx转换成React代码的工具
-
react依赖繁琐
- 三个库各司其职,目的让每一个库只单纯做自己的事情
- React0.14版本之前是没有 react-dom 概念的,所有的功能都包含在 react 里
-
为何拆分?因为 react-native
- react包中包含了react web 和 react-native 所共同拥有的核心代码
- react-dom针对 web 和 native 所完成的事情不同
- web端:react-dom 会将jsx最终渲染成真实的DOM,显示在浏览器中
- native端:react-dom会将jsx最终渲染成原生的控件(如:Android中的Button,IOS中的UIButton)
Babel 和 React 之间的关系
-
babel是什么
- babel.js
- 目前前端使用广泛的编译器、转移器
- 很多浏览器不支持ES6语法,但我们希望在开发中使用它
- 编写源码时可以使用ES6来编写,之后通过Babel工具,将ES6转成大多数浏览器都支持的ES5语法
-
React 和 Babel 关系
- 默认情况下,开发React可以不使用Babel
- 前提是得自己使用 React.createElement 来编写源代码,它编写的代码非常的繁琐和可读性差
- 可以直接编写jsx(JavaScript XML)的语法,并让babel转换成 React.createElement
React 的依赖引入
-
添加依赖的方式
- CDN引入
- 下载后,添加本地依赖
- 通过npm管理(脚手架使用)
-
暂时使用 CDN引入
- crossorigin 的属性目的是为了拿到跨域脚本的错误信息
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
四、React组件化的封装
Hello React - 组件化开发
- 封装成一个组件
- root.render参数是一个HTML元素或者一个组件
- 将之前的业务逻辑封装到一个组件中,然后传入到 ReactDOM.render 函数中的第一个参数
- React中如何封装一个组件呢?类/函数
- 定义一个类(类名大写,组件的名称必须大写,小写会被认为是HTML元素),继承自 React.Component
- 实现当前组件的render函数
- render 当中返回的jsx内容,就是之后React会帮助我们渲染的内容
组件化 - 数据依赖
- 数据在哪里?
- 组件中的数据分为两类
- 参与界面更新的数据:当数据变化时,需要更新组件渲染的内容
- 不参与界面更新的数据:当数据变化时,不需要更新将组件渲染的内容
- 参与界面更新的数据称之为参与数据流,这个数据定义在当前对象的 state 中
- 通过在构造函数中 this.state = {定义的数据}
- 当数据发生变化时,可以调用 this.setState 来更新数据,并通知React进行update操作
- 在进行update操作时,就会重新调用render函数,并且使用最新的数据渲染界面
五、React数据事件处理
组件化 - 事件绑定
- 组件化问题二:事件绑定中的this
- 在类中直接定义一个函数,将这个函数绑定到元素的 onClick 事件上,当前这个函数的 this 指向谁?
- 默认情况下是 undefined
- 在正常的DOM操作中,监听点击,监听函数中的this其实是节点对象(如button对象)
- 因为React并不是直接渲染成真实的DOM,我们编写的button只是一个语法糖,本质是 React Element 对象
- 在这里发生监听的时候,react在执行函数时并没有绑定this,默认情况下就是一个 undefined
- 在绑定的函数中,可能想要使用当前对象,比如执行 this.setState 函数,必须拿到当前对象的 this
- 需要在传入函数时,给这个函数直接绑定 this
- 类似:<button onClick={this.btnClick.bind(this)}>改变文本</button>
<div id="root"></div>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
// 使用组件进行重构代码
// 类组件和函数式编程
class App extends React.Component {
// 组件数据
constructor() {
super()
this.state = {
msg: 'Hello World'
}
// 对需要绑定的方法,提前显式绑定好this
this.btnClick = this.btnClick.bind(this)
}
// 组件方法(实例方法)
btnClick = () => {
// 内部完成了两件事情:1.将state中的msg值修改 2.自动重新执行render函数渲染界面
this.setState({
msg: 'Hello React'
})
}
// 渲染内容 render 方法
render() {
return (
<div>
<h2>{this.state.msg}</h2>
<button onClick={this.btnClick}>修改文本</button>
</div>
)
}
}
// 将组件渲染到界面上
const root = ReactDOM.createRoot(document.querySelector('#root'))
root.render(<App />)
</script>
六、React其他案例实现
电影列表案例
<div id="root"></div>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
// 1.创建root
const root = ReactDOM.createRoot(document.querySelector('#root'))
// 封装App组件
class App extends React.Component {
constructor() {
super()
this.state = {
movies: ['流浪地球', '独行月球', '大话西游', '星际穿越']
}
}
render() {
return (
<div>
<h2>电影列表</h2>
<ul>
{this.state.movies.map(i => {
return (
<li key={i}>{i}</li>
)
})}
</ul>
</div>
)
}
}
// 2.渲染组件
// jsx -> React.createElement
root.render(<App />)
</script>
计数器案例
<div id="root"></div>
<script src="https://unpkg.com/react@18/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@18/umd/react-dom.development.js" crossorigin></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<script type="text/babel">
const root = ReactDOM.createRoot(document.querySelector('#root'))
class App extends React.Component {
constructor() {
super()
this.state = {
count: 10
}
this.increment = this.increment.bind(this)
this.decrement = this.decrement.bind(this)
}
render() {
const { count } = this.state
return (
<div>
<h2>当前计数:{count}</h2>
<button onClick={this.increment}>+1</button>
<button onClick={this.decrement}>1</button>
</div>
)
}
// 组件方法
increment() {
this.setState({
count: this.state.count + 1
})
}
decrement() {
this.setState({
count: this.state.count - 1
})
}
}
root.render(<App />)
</script>