react 学习笔记
[TOC]
ES6 基础
一. 变量的解构赋值
1. 数组的解构赋值
1 |
|
数组的解构,前提是右边一定要是数组(可以是可遍历的结构),不然会报错
2. 对象的解构赋值
1 |
|
- 解构对象的字段都是普通类型,是值拷贝
1 | let object1 = {a: 1, b: 2, c: 3} |
- 解构对象的字段还是一个对象的话,也是赋值的对象引用,不是值拷贝
1 |
|
3. 函数参数的解构
1 |
|
补充说明 ( … 操作符)
…操作符一般用来解构对象和数组,解构的时候,只能放到最后一个参数使用
1
2
3
4
5
6
7
8
9
10
11
12// 正确解构赋值
let {a, ...b} = {a: 123, b: 2, c: 3}
// a = 123 b = {b: 2, c: 3}
let object1 = {a: 123, b: 2, c: 3}
let {...a} = object1
// a = {a: 123, b: 2, c: 3} 这里 a 和 直接赋值 ( let a = object1 ) 还是有区别的
// 解构的话是 object1 值的拷贝; 直接赋值 是 object1 对象引用
// 错误
let {...a, b} = {a: 123, b: 456}
// 程序报错
2. ...操作符也能用于对象的合并和数组的合并
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 对象的合并
let object1 = {username: 123, age: 456}
let object2 = {name: '123', sex: 1}
// 后者的同名字段会覆盖前者的同名字段 相当于php数组的 array_merge
let object3 = {...object1, ...object2, username: 'jinxing'}
// object2 = {username: 'jinxing', age: 456, name: '123', sex: 1}
// 数组的合并
let a = [1, 2, 3, 4, 5]
let b = [1, 2, 3, 4, 5]
// 相当于将 a, b 数组展开追加到新数组中 c = [], c.push(...a), c.push(...b), c.push(7, 8)
let c = [...a, ...b, 7, 8]
// c = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 7, 8]
3. ...操作符用于函数,表示接收不确定参数个数 (和 go 有点相似)
1
2
3
4
5
6
7
8
9
// 求和 params 是传入参数组成的数组
function sum(...params) {
let i = 0
params.forEach(v => i += v)
return i
}
const a = sum(1, 2, 3)
// a = 6
4. ...操作符用于函数传参数,表示将数组各个元素传递给函数参数
1
[1, 2, 3].push(...[4, 5, 6])
二. 箭头函数的使用
1. 定义
1 | // 不要参数 |
2. this 指向
箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this
1 | // 不使用箭头函数 |
三. 其他补充
1. 对象字段的简写
1 |
|
2. 对象字段名为变量
1 |
|
3. export 和 export default 的区别
export 导出的函数或者类 名称是什么,外面引入的时候就要是什么, 但可以引入的时候修改名称; 而且import 引入的时候,需要加上 {}
1 |
|
export default 导出的函数或者类,在其他文件引入,需要为其定义名称;import 不要使用 {}
- 一个 js 文件中 只能有一个 export default 导出
1 |
|
React 基础
创建一个 React 的单页应用
1 | npx create-react-app my-app |
一、JSX语法
JSX,是一个 JavaScript 的语法扩展
1、使用
1 | const element = <h1>测试</h1> |
2、使用表达式和变量
1 | const username = "my-test" |
- 属性 使用
{}
包起来的表示变量或者表达式,如果使用""
包起来表示简单的字符串 - 属性定义了但没有给值 默认为
true
二、定义组件
1. 使用类定义
1 | import React, {Component} from 'react' |
2. 使用函数定义
1 | const MyComponent = props => { |
3. 注意事项
- 组件命名必须组照大驼峰命名法
- 渲染class类名,需要使用className
- 渲染style时候,必须使用对象,并且字段需要使用小驼峰法 例如:font-size: “16px” 需要写为 fontSize: “16px”
1 | const MyComponent = props => { |
- render 函数里面渲染的时候,最外层必须要一个父级标记,不允许同时出现两个同级外层标签
1 | // 正确 |
react 允许外层不适用外层标签、即允许两个同级标签,不过需要使用Fragment 标签标记
1 |
|
出于安全考虑的原因(XSS 攻击),在 React.js 当中所有的表达式插入的内容都会被自动转义,如果需要使用html 标记必须使用dangerouslySetInnerHTML
1 | import React, {Component} from 'react' |
4、state和生命周期
state
相当于 vue
的 data
修改state
必须使用 this.setState()
函数
- constructor() 初始化
- render() 渲染
- componentDidMount() 挂载之后
5、条件渲染&循环
条件渲染
- 可以使用
&&
操作符 可以使用 三元运算符
?:
1
2
3
4
5
6
7
8
9
10const MyComponent = props => {
return <div>
{this.props.title && <h1>{this.props.title}<h1>}
{this.props.content ? <div>{this.props.conent}</div> : ''}
{0 && <div>123</div>}
</div>
}
- 可以使用
注意: 使用 `&&` 操作符的时候,前面表达式最好是一个布尔值
- 列表渲染
- 需要给同级元素一个唯一的
key
- 如果是数组变量可以直接渲染
1
2
3
4
5
6
7
8
9
10
11
12const MyComponent = props => {
const items = [1, 2, 3]
return <div>
{items}
{items.map(v => v)}
<ul>
{item.map(v => <li key={v}>{v}</li>)}
</ul>
</div>
}
- 需要给同级元素一个唯一的
三、组件传参
父组件传参给子组件直接像html标签属性一样
1 | import React, {Component} from 'react' |
子组件接收父组件的参数,使用this.props 接收
1 | import React, {Component} from 'react' |
四、默认传参defaultProps
1 | import React, {Component} from 'react' |
五、PropTypes 和组件参数验证
- 需要引入React 提供的第三方库 prop-types
1 | npm install --save prop-types |
1 | import React, {Component} from 'react' |
六、组件的事件处理
- React 事件的命名采用小驼峰式(camelCase),而不是纯小写。
- 使用 JSX 语法时你需要传入一个函数作为事件处理函数,而不是一个字符串。
1. 绑定事件时候 this 指向问题
文档
1 |
|
- 推荐使用箭头函数
2. 绑定事件的时候,添加传递参数
1 |
|
- 使用函数的 bind 方法, 第一个参数,函数内部 this 指向谁, 后面参数为函数需要接收的参数
如果原有事件就有传递参数,但是处理的时候还想添加参数的话,同样使函数的 bind 方法,自己添加的参数在最前面; 原有的参数,会在自定义参数后面传递
1 | // 子组件 |
使用箭头函数解决传递参数问题
- 通过箭头函数返回函数实现 注意箭头函数的写法 () => () => {}
1 | // 子组件 |
七、… 操作符在 JSX 语法中常用方式
1. 接收剩余传递参数
1 |
|
2. 属性展开
1 |
|
八、高阶组件
定义高阶组件
就是像定义普通函数一样,不过第一个参数是一个组件,而且必须要返回一个组件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20const hocComponent = WrappedComponent => {
class HocComponent extends Component {
render() {
return <WrappedComponent style={{padding: '5px', borderRadius: '3px'}} {...this.props}/>
}
}
// 这个是约定: 需要定义一个displayName属性,方便调试
HocComponent.displayName = `HocComponent(${getDisplayName(WrappedComponent)})`
return HocComponent
}
// 使用
const Button = props => {
return <button {...props}>{props.children}</button>
}
const HocButton = hocComponent(Button)高阶组件静态属性的导出(务必复制静态方法)
- 默认不会导出静态属性,需要手动去导出
- 使用
hoist-non-react-statics
高阶组件ref问题
- refs 提供了一种方式,允许我们访问 DOM 节点或在 render 方法中创建的 React 元素。
- 默认 ref 指向高阶组件自己,如果需要转发到被高阶组件包裹的组件中,要用到refs转发
九、Context
Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法
四个API:
- React.createContext
- Context.Provider
- Class.contextType
- Context.Consumer
我们项目中常用组件
基于 Ant Design Pro
Ant Design of React UI库
一、表格组件CTable
1 | <CTable columns={[....]} api={queryApi} btnClick={this.handleClick} /> |
常用的属性列表
属性名 | 类型 | 说明 |
---|---|---|
columns |
array |
表格字段信息 |
api |
function |
表格数据来源API |
btnClick |
(key, rows) => {} |
表格操作项点击事件处理 |
index |
string or function |
表格每一行唯一的key |
filters |
object |
查询的默认条件 |
其他说明
columns
中,元素配置 _render
表示生成操作项,配置格式 {key: 'update', title: '修改'}
或者 [{key: 'update', title: '修改'}]
, 点击事件交给表格的 btnClick
函数处理
1 | <CTable |
需要后端服务器返回数据格式
1 | { |
如果不需要分页, page
返回 false
二、表单组件CForm
CForm
表单组件
1 | <CForm rules={{name: [{required: true, message: '不能为空'}]}} onSubmit={(values) => { |
常用的属性列表
属性名 | 类型 | 说明 |
---|---|---|
rules |
object |
表单字段验证信息 |
onSubmit |
(values) => {} |
表单提交事件处理 |
initialValue |
object |
表单字段初始值数据 |
CInput
Input 输入框
1 | <CInput name="name" label="名称" /> |
常用的属性列表
属性名 | 类型 | 说明 |
---|---|---|
name |
string |
表单字段名称(html input 元素的name 属性,可以是 :name="user[name]" |
label |
string |
label 名称 |
initialValue |
mixed |
表单字段的初始值 |
show |
(values) => boolean |
显示处理函数,values 表示所有表单的值,需要返回ture 表示渲染 |
JS异步
一、异步示例
1 | for (var i = 0; i < 10; i ++) { |
二、使用Promise
对象
所谓 Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。
Promise对象特点:
- 对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。
- 一旦状态改变,就不会再变,任何时候都可以得到这个结果。
1. 定义Promise
对象
Promise
函数有两个参数 resolve
和 reject
,这两个参数都是函数
- resolve 表示成功返回
- reject 表示错误返回
1 | const handle = () => { |
2. 使用Promise
对象
then
表示resolve
后的回调函数;参数是resolve
返回catch
表示reject
后的回调函数;参数是reject
返回finally
表示不管是resolve
还是reject
都会执行的回调
1 | handle().then(value => { |
三、使用co
包
为什么使用co
- 解决异步回调的嵌套
- 让异步回调,同步的形式执行
例如: 发送一个异步请求,但这个请求依赖于另一个异步请求
1 |
|
四、使用async
函数
async
函数是 ES2017 标准引入的,是生成器函数的语法糖
使用 async
就是将 生成器函数的 *
改为 async
, 将 yield
改为 await
1 |
|
async
返回的还是一个 Promise
所以可以继续调用 then
,catch
,finally
1 | (async () => { |