第一章 React 新的前端思维方式
1.creat-react-app 脚手架的使用方法
安装脚手架:
npm i -g create-react-app
创建项目:
create-react-app
运行项目:
npm start
2.import React, {Component} from ‘react’
问:在组件中并没有使用到React,为什么要引用React?
答:“在使用JSX的范围内必须要有React”,即使代码中并没有直接使用React,也一定要导入这个React,这是因为JSX最终会被编译成依赖于React的表达式。
3.JSX是进步还是退步
问:与传统的html,css,js三种语言分开在不同文件来比较,React将html、js,甚至是css都放在了一个文件里,是不是不符合原则?
答:三种语言分在三种不同的文件里面,实际上是把不同技术分开管理了,而不是逻辑上的“分而治之”。根据做同一件事的代码应该有高耦合性的设计原则,那为什么不把实现这个功能的所有代码集中在一个文件里?
4.JSX的onClick与html的onclick
Html中直接使用onclick很不专业,原因如下:
1.onclick添加的事件处理函数是在全局下执行的,污染了全局环境。
2.给很多DOM元素添加onclick事件,可能会影响页面的性能。
3.对于使用onclick的DOM元素,如果要动态地从DOM树中删除掉的话,需要把对应的时间处理器注销,要不然可能会造成内存泄露。
JSX的onClick事件:
上述问题都不存在
1.onClick挂载的每个函数,都可以控制在组件范围之内,不会污染全局空间。
2.JSX中使用onClick,并不会直接产生使用onclick的HTML,而是使用了事件委托的方式处理点击事件,无论多少的onClick出现,最后都只在DOM树上添加了一个事件处理函数。
3.react控制组件的生命周期,在unmount的时候自然能够清除相关的所有事件处理函数,内存泄露也不再是问题
5.jQuery和React的比较
jQuery:选中一些DOM元素,然后对这些元素做一些操作。
React:
UI=render(data)
用户看到的界面,应该是一个函数的执行结果。只接受数据(data)作为参数。这个函数是一个纯函数,两次函数调用如果输入相同,得到的结果也绝对相同。
React利用声明式的语法,让开发者专注于描述用户界面“显示成什么样子”,而不是重复思考“如何去显示”。
第二章 设计高质量的REACT组件
1.易于维护组件的设计要素
1.“分而治之”的策略,把问题分解为多个小问题,组件化。
2.高内聚,低耦合。React天生具有高内聚的特点。
2.prop与state
Prop是组件的对外接口
state是组件的内部状态
3.prop
赋值方式:
prop支持任何一种javascript语言的数据类型;
prop的类型不是字符串类型时,JSX中必须用花括号{}把prop值包住;
class ControlPanel extends Component {
render() {
return (
)
}
}
读取方式:
class Counter extends Component {
constructor(props) {
super(props);
//ES6方法创造的react组件类并不自动给我们绑定this到当前实例对象,所以要在构造函数中绑定当前this的执行环境
this.onClickIncrementButton = this.onClickIncrementButton.bind(this);
this.onClickDecrementButton = this.onClickDecrementButton.bind(this);
this.state = {
count: props.initValue
}
}
}
…
render() {
const {caption} =this.props;
return (
{caption} count:{this.state.count}
)
}
4.PropTypes检查
在15.5.0版本中,这一API被独立成了一个新的包prop-types
// 15.4 以前
import React from 'react';
class Component extends React.Component {
render() {
return {this.props.text};
}
}
Component.propTypes = {
text: React.PropTypes.string.isRequired,
}
// 15.5 以后
import React from ‘react';
import PropTypes from 'prop-types';
class Component extends React.Component {
render() {
return {this.props.text};
}
}
Component.propTypes = {
text: PropTypes.string.isRequired,
};
5.state
组件的state必须是一个javascript对象;
this.state = {
count: props.initValue;
}
读取:this.state.count
更新:
onClickIncrementButton() {
this.setState({count: this.state.count + 1});
}
必须使用this.setState()
去更新,不能直接改变state,例:
onClickIncrementButton() {
this.setState.count = this.setState.count + 1;
} // 错 ❌
原因:直接修改this.state的值,虽然事实上改变了组件的内部状态,却没有驱动组件进行重新渲染;
而this.setState()函数所做的事情,首先是改变this.state的值,然后驱动组件经理更新过程,这样才有机会让this.state里的新值出现在界面上
6.prop和state的对比
1.prop用于定义外部接口,state用于记录内部状态;
2.prop的赋值在外部世界使用组件时,state的赋值在组件内部;
3.组件不应该改变prop值,而state存在的目的就是让组件来改变的。
修改prop的值,是一个副作用,组件应该避免。
7.组件的生命周期
生命周期可能会经历如下三个过程:
1.装载过程(Mount),也就是吧组件第一次在DOM树上渲染的过程;
2.更新过程(Update),当组件被重新渲染的过程;
3.卸载过程(Unmount),组件从DOM中删除的过程。
三种不同的过程,React库会依次调用组件的一些成员函数,这些函数成为生命周期函数。所以,要定制一个React组件,实际上就是定制这些生命周期函数。
8.装载过程(Mount)
执行函数
1.constructor
es6中每个类的构造函数,做两件事,初始化state,绑定成员函数的this环境。
2.getInitialState
在使用React.createClass定义组件时候使用,现在React.createClass被废弃,因此也不会执行了
3.getDefaultProps //同上
4.componetWillMount
“将要装载”,存在的目的就是和component对称,componentWillMount中要做的事情,都可以提前到comstructor中去做。可以在服务器端调用,也可以在浏览器端调用。
5.render
render函数并不做实际的渲染动作,它只是返回一个JSX描述的结构,最终由React来操作渲染过程。
6.componentDidMount
“装载后”,只能在浏览器端被调用。
在此处通过AJAX获取数据来填充组件的内容。
componentDidMount不是紧跟着render函数被调用,当所有子组件的render函数都被调用之后,componentDidMount才连在一起被调用。
9.更新过程(Mount)
执行函数
1.componentWillReceiveProps(nextProps)
父组件的render函数被调用,在render函数里面被渲染的子组件就会经历更新过程,不管父组件传给子组件的props有没有变化,都会触发子组件的componentWillReceiveProps函数。
这个函数有必要把传入参数nextProps和this.props做比较,只有两者有变化的时候才有必要调用this.setState更新内部状态
2.shouldComponentUpdate(nextProps, nextState)
“是否允许更新”,render,shouldComponentUpdate,是生命周期函数中唯二要求有返回结果的函数。与this.props和this.state对比,看是否变化,决定是否重新渲染。
3.componentWillUpdate
“组件将要更新”
4.render
5.componentDidUpdate
“组件更新后”
10. 卸载过程(Unmount)
componentWillUnmount
React组件要从DOM树上删除掉之前执行。
11. 组件向外传递数据
给子组件传个函数,子组件数据改变时,调用函数。
12. React组件state和prop的局限
1.设想在一个应用中,包含三级或者三级以上的组件结构,顶层的祖父组件想要传递一个数据给最底层的子组件,用prop的方式,就只能通过父组件中转。也许中间那层用不上这个prop,但依然要支持这个prop,扮演着搬运工的角色,这明显违反了低耦合的设计要求。
2.使用react的state来存储状态的一个缺点,那就是数据的冗余和重复。