前言

react的核心是数据与页面双向绑定,虚拟DOM,JSX,而react与vue差别在于react没有那么多的钩子函数,无指令,class方式编程,当然也可以函数式编程,如hooks,但主流还是class,在主观上react的操作需要构思一下数据结构与父子组件间的渲染优化,因为父组件渲染会触发子组件的钩子函数,并执行render,虽然虚拟DOM的diff算法,已经很大优化了渲染,但还是会出现父组件渲染导致子组件无必要渲染而导致页面卡顿现象,这就需要自己对不必要的数据控制不要渲染,如使用shouldComponentUpdate优化。

安装

脚手架的安装运行

1
2
create-react-app my-app
npm run eject //弹出webpack

一定要弹出webpack,不是没法进行一些配置,且安装babel-plugin-import那么就可以进行babel的配置,而且不需要建立babel配置文件,在package.json里就可以进行,否则会报错,plugins的import配置多个时需要在数组的第三个标明名称如:

1
2
3
4
5
6
7
8
9
10
"plugins": [
["import", {
"libraryName": "antd",
"libraryDirectory": "es",
"style": "css"
},
"antd"],
["import",
{ "libraryName": "antd-mobile", "style": "css" },"antd-mobile"]
]

第三个参数没有会报错,如表明为antd或antd-mobile等。
而style设置为css,若设置true,那么加载的antd就要是less文件,否则无法正常加载css文件。

react组件间使用的生命周期

在不使用路由router的情况下,组件在当前路由一开始就constructor->componentWillMount->render->componentDidMount,而当页面没有被卸载情况下componentWillReceiveProps->shouldComponentUpdate->componentWillUpdate->render->componentDidUpdate,当组件被卸载componentWillUnmount。

由于子组件没有卸载,所以constructor、componentWillMount、componentDidMount不会再触发,而是触发更新操作流程,而想每次更新都重新加载组件,那么就是卸载组件如:

1
2
3
4
5
6
7
8
9
10
11
12
import {ChildCom} from './ChildCom';
class App extends Component {
render() {
const aaa = show?<ChildCom />:null;
return (
<div className="App">
{aaa}
</div>
);
}
}
// 当shou为false时卸载组件,为true加载组件,这样就可以实现卸载与加载

由于父组件的更新会触发子组件也触发更新操作,所以子组件的更新的钩子函数会去执行,而子组件自己的更新不会触发componentWillReceiveProps钩子函数。

antd与antdDesign的表单校验

antd里有自己的一套完善的表单校验规则,根据API使用,而使用时需要Form与Form.Item包着,这样就可以使用getFieldDecorator函数给需要校验的组件进行双向绑定,然后进行表单的校验,而组件必须有value(或 valuePropName 指定的其他属性) onChange(或 trigger 指定的其他属性),而且传入的组件不需要声明value与onChange,它内部就实现好了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { setItem, setItemContent } from '../../redux/itemReduce';
import { List, InputItem } from 'antd-mobile';
import {Form} from 'antd';

class ItemTwo extends Component {
constructor(props) {
super(props);
this.state={name:"zhang"};
}
componentDidMount() {
// 全部进行校验,回调校验结果并触发页面的校验规则
this.props.form.validateFields((err, values) => {
if (!err) {
console.log('Received values of form: ', values);
}
});
}
componentDidUpdate(){
// isFieldTouched判断一个输入控件是否经历过 getFieldDecorator 的值收集时机 options.trigger
// getFieldError获取某个输入控件的 Error
const { isFieldTouched,getFieldError,getFieldsValue, validateFields } = this.props.form;
const childPhoneError = isFieldTouched('childPhone') && getFieldError('childPhone');
}
render() {
const { getFieldDecorator } = this.props.form;
return (
<div className='itemOne'>
<Form>
<Form.Item>
{getFieldDecorator('childPhone',{
rules: [{ required: true, message: '手机号必填!' }]
})(
<InputItem >子手机号</InputItem>
)}
</Form.Item>
</Form>
</div>
)
}
}

const mapStateToProps = state=>{
return state.itemRedux;
}

const mapDispatchToProps = {setItem, setItemContent};

export default connect(mapStateToProps, mapDispatchToProps)(Form.create({
name:"itemTwo",
// 具体表单进行与父组件或redux,的props属性关联起来
mapPropsToFields(props){
return {
childPhone:Form.createFormField({
value: props.phone
})
}
},
// 当 Form.Item 子节点的值发生改变时触发,可以把对应的值转存到 Redux store
onFieldsChange(props, fields){
console.log(props);
},
// 任一表单域的值发生改变时的回调
onValuesChange(props, changedValues, allValues){
console.log(props.form.getFieldError)
//console.log(changedValues);
}
})(ItemTwo));

这里只是一部分,还有很多校验方法,如自定义校验,自定义校验方法等等。