React基本使用
React
简介
是什么
用于构建用户界面的JavaScript
库
以前编写页面的流程
- 发送请求获取数据
- 处理数据(过滤、整理格式等)
- 操作
DOM
呈现页面
React
核心:将数据渲染成HTML
视图
谁开发的
由Facebook
开发,且开源
- 起初由
Facebook
的软件工程师Jordan Walke
创建 - 于2011年部署于
Facebook
的newsfeed
- 随后在2012年部署于
Instagram
- 2013年5月宣布开源
- …
为什么要学
- 原生
JS
操作DOM
繁琐、效率低(DOM-API
操作UI
) - 使用原生
JS
直接操作DOM,浏览器会进行大量的重绘重排 - 原生
JS
没有组件化编码方案,代码复用率低
React
特点
- 采用组件化模式、声明式编码,提高开发效率及组件复用率
- 在
React Native
中可以使用React
语法进行移动端开发 - 使用虚拟
DOM
+优秀的Diffing
算法,尽量减少与真实DOM
的交互
前置知识
- 判断
this
指向 class
ESNext
npm
- 原型与原型链
- 数组常用API
- 模块化
React
入门
官网
英文官网:https://reactjs.org/
中文官网:https://zh-hans.reactjs.org/
React
基本使用
相关js
库
react.js
:React
核心库react-dom.js
:提供操作DOM
的react
扩展库babel.min.js
:解析JSX
语法代码,转为js
代码的库- 使用在线
JS
文件:https://reactjs.org/docs/add-react-to-a-website.html
版本变更:
https://github.com/facebook/react/blob/main/CHANGELOG.md
目前最新版本为18.2.0 (June 14, 2022)
本教程版本为16.8
,有点旧了,但学个基础语法是够用的
HelloReact
案例
https://reactjs.org/docs/add-react-to-a-website.html
1 | <body> |
虚拟DOM
的两种创建方式
方式一:JSX
1 | const VDOM = <h1>Hello, React</h1>; |
方式二:JS
1 | const VDOM = React.createElement('h1', {id: 'title'}, 'Hello, React2') |
需求:h1
里包一个span
,内容不变
JSX
1 | const VDOM = <h1><span>Hello, React</span></h1>; |
JS
1 | const VDOM = React.createElement('h1', {id: 'title'}, React.createElement('span', {}, 'Hello, React2')) |
四层标签嵌套,JS
写法就很痛苦了
JSX
作用:更流畅的创建虚拟DOM
,就是原始JS
创建虚拟DOM
的语法糖
1 | const VDOM = ( |
babel
其实就是讲jsx
语法转化成了createElement
语法了
虚拟DOM
与真实DOM
虚拟DOM
就是一般对象
虚拟
DOM
比较轻,真实DOM
比较重。因为虚拟DOM
是React
内部在用,无需那么多的属性虚拟
DOM
最终会被React
转化为真实DOM
,呈现在页面上
真实DOM
console.dir
看下真实DOM
身上的属性,有很多很多
JSX
语法
- 全称:
JavaScript XML
React
定义的一种类似于XML
的JS
扩展语法:JS XML
- 本质是
React.createElement(co)
- 语法规则
- 定义虚拟
DOM
时,无需引号 - 标签中混入
JS
表达式时,要用{}
- 样式的类名指定,用
className
,不能用class
class
是ES6
中的关键字
- 内联样式,要用
style={{key: value}}
的形式- 外层的
{}
表示要写js
表达式 - 内层的
{}
表示一个对象 key
如果是多个单词,采用小驼峰value
是字符串,要加引号
- 外层的
- 只能有一个根标签
- 标签必须闭合
- 标签首字母
- 小写开头:将标签转为
HTML
中的同名元素,若无同名元素,则报错 - 大写开头:则认为是组件
- 小写开头:将标签转为
- 定义虚拟
React
面向组件编程
前置准备
安装React
开发插件,edge浏览器插件市场搜索并安装:
React Developer Tools - Microsoft Edge Addons
安装成功后,打开https://www.meituan.com/,美团PC官网就是用React写的
审查元素,有两个额外的标签页:
基本理解和使用
函数式组件
1 | <script type="text/babel"> |
Demo
组件中,如果打印this
,值是undefined
,因为babel
转化开启了严格模式
[Babel 中文网 · Babel - 下一代 JavaScript 语法的编译器 (babeljs.cn)](https://www.babeljs.cn/repl#?browsers=defaults%2C not ie 11%2C not ie_mob 11&build=&builtIns=false&corejs=3.21&spec=false&loose=false&code_lz=GYVwdgxgLglg9mABAEQKYFs4AoCUiDeiA9EYoGmZg6tqCz1oKP6g3hmDkmoJmKAUIogE6pQgdIA8ACwBMAPkCIRoHozQBSugX8VADqaAs7UCScoBC3QCN-gN7lAEP-AgBOmA4uUAB3oFVlLapWBIf_5ERogNzFSgFfjAe2qAAc0Bf6oAEPVYAA5QCo5QGW_QBDzFgBfIA&debug=false&forceAllTransforms=false&shippedProposals=false&circleciRepo=&evaluate=false&fileSize=false&timeTravel=false&sourceType=module&lineWrap=true&presets=env%2Creact%2Cstage-2&prettier=false&targets=&version=7.20.12&externalPlugins=&assumptions={})
执行root.render(<Demo/>)
,发生了什么
React
解析组件标签,找到组件- 发现组件是函数定义,调用该函数,将返回的虚拟
DOM
转为真实DOM
,呈现在页面中
类语法
类式组件
1 | <script type="text/babel"> |
render
函数是在Demo
的原型对象上
render
函数要被调用,肯定要new
一个实例的,React
默认创建了组件实例
还是回到
执行root.render(<Demo/>)
,发生了什么
这个问题:
React
解析组件标签,找到组件发现组件是类定义,
new
出来类的实例,并通过该实例调用原型的render
方法render
中的this
,指向该实例,通常称之为组件实例对象或组件对象
将
render
返回的虚拟DOM
转为真实DOM
,呈现在页面中
组件实例三大核心属性
state
state
是组件对象最重要的属性,值是对象(可以包含多个key-value
的组合)- 组件被称为“状态机”,通过更新组件的
state
来更新对应的页面显示(重新渲染组件)
注意点:
- 组件中的
render
方法中的this
为组件实例对象 - 组件自定义的方法中,
this
为undefined
如何解决?- 强制绑定
this
:通过函数对象的bind()
- 箭头函数
- 强制绑定
- 状态数据,不能直接修改或更新
定义state
在类组件的构造器里初始化state
1 | class Demo extends React.Component { |
事件绑定
React
重新封装了各种事件,onclick
对应onClick
,其它类似
1 | return <h2 onClick={demo}>今天天气很{isHot ? '炎热' : '凉爽'}</h2> // 不要加括号 |
如果将方法定义在外层,获取不到state,可以将方法写在类里面
1 | class Demo extends React.Component { |
但是:
class
类中定义的方法, 都在局部开启了严格模式
由于点击事件,不是通过实例调用,而是作为回调,直接调用,所以内部this
为undefined
解决类中this
指向问题:
1 | constructor(props) { |
修改state
状态不可直接更改,类似于原生小程序的setData
,React
中使用组件实例原型的原型上的setState
方法,是一个合并的操作
1 | demo() { |
state
的每次变化:
构造器只调用一次
render
函数初始化会被调用一次,state
变化时也会重新调用(1+N次)demo
回调,点几次调用几次
state
的简写方式
标准写法
1 | class Demo extends React.Component { |
简写
回调函数的简写
- 箭头函数,没有
this
,如果写了this
则向外层作用域寻找
- 箭头函数,没有
初始化状态的简写
类中可以直接写赋值语句
1
2
3class Demo {
a = 1 // 往实例上追加a,值为1
}
简写
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17class Demo extends React.Component {
state = {
isHot: false
}
demo = () => {
const { isHot } = this.state
this.setState({
isHot: !isHot
})
}
render() {
const { isHot } = this.state
return <h2 onClick={this.demo}>今天天气很{isHot ? '炎热' : '凉爽'}</h2>
}
}
props
- 每个组件对象,都会有
props
(properties
)的简写 - 组件标签的所有属性都保存在
props
中