初始化
getDefaultProps()
getIniterStates()
componentwillmount()
render()
componentdidmount()
运行中
componentWillReceiveProps()
shouldComponentUpdate()
componentwillUpdate()
render()
componentdidUpdate()
卸载
compoentwillUnmount()
声明式
虚拟DOM
支持服务端渲染
单向数据绑定 flux
状态机组件
接受参数后,生成新的虚拟Dom对象树,使用Diff算法比较新旧对象树,找出有差异的节点,以打补丁的形式更新到真实Dom上
真实Dom树有231个元素属性,大部分与渲染无关,渲染真实Dom非常耗性能
虚拟Dom以对象树的形式模拟真实Dom,只添加与渲染有关的属性,利用Diff算法
找出更新的部分,然后更新到真是Dom上,提升了渲染效率
jsx最终都会被转换成createClass()的形式,每个元素及组件都是一个对象,最终形成一个虚拟Dom对象树的结构。
Diff算法是从外而内开始比较,会比较节点的类型、属性、子元素等,如果根节点类型不一致,会重新渲染整个对象树。
Diff会借助列表元素的key值进行比较,key最好不是循环的index,有助于提升Diff算法的效率
元素渲染:所有组件最终编译为 React.createElement(type, {props}, …children)
组件命名:首字母大写
组件嵌套:只能有一个根节点,并用()包含
props:只读,父组件传递 constructor(props){ … },至上而下数据流
state:不能直接修改this.state,通过this.setState() 修改
setState不会立刻改变React组件中state的值;
setState通过引发一次组件的更新过程来引发重新绘制;
- shouldComponentUpdate
- componentWillUpdate
- render
- componentDidUpdate
多次setState函数调用产生的效果会合并
this.setState({name: 'newName'})
this.setState((preState,props)=>{
return preState + newState
})
事件处理:
class Demo extends React.component {
constructor(props){
this.state.name = props.name
this.handEvent = this.handEvent.bind(this)
}
handEvent (e) {
console.log(e.target.name)
}
render () {
return {
}
}
}
条件渲染:
class Demo extends React.component {
constructor(props){
super(props)
this.state.flag = true
this.state.name = props.name
this.handEvent = this.handEvent.bind(this)
this.handCommit = this.handCommit.bind(this)
}
handEvent (e) {
console.log(e.target.name)
}
handCommit (e) {
console.log(e.target.name)
}
render () {
return {
if (this.state.flag) {
}
else {
}
// or
{this.state.flag ?
: }
}
}
}
列表&keys:
class Demo extends React.component {
constructor(props){
super(props)
this.state.items = props.array
}
render () {
const items =
this.state.items.map((item) => - {item.name}
)
return {
{items}
}
}
}
表单:
import React form 'react'
class Demo extends React.component {
constructor (props) {
super(props)
this.state = {name: ''}
this.handInput = this.handInput.bind(this)
this.handCommit = this.handCommit.bind(this)
}
handInput (e) {
this.setState({name: e.target.value})
/*
this.setState((preState,props) => {
name:preState.name + e.targer.value
})
*/
}
handCommit (e) {
e.preventDefault()
console.log({this.state.name})
}
render () {
return {
}
}
}
状态提升:兄弟之间共享状态的情况,将状态提升至最近父组件进行管理(至上而下)
组合:
// 组合
function Dialog(props) {
return (
{props.title}
{props.message}
{props.children}
);
}
class SignUpDialog extends React.Component {
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
this.handleSignUp = this.handleSignUp.bind(this);
this.state = {login: ''};
}
handleChange(e) {
this.setState({login: e.target.value});
}
handleSignUp() {
alert(`Welcome aboard, ${this.state.login}!`);
}
render() {
return (
);
}
}
深入JSX:
React 与 引用组件类型必须在当前作用域
组件编译后:React.createElement(component,props, ...children)
运行时选择类型
class Demo extends React.component {
constructor (props) {
super(props)
this.state.types = ['Button','Input']
}
render () {
const componentType = this.state.types[0]
return {
}
}
}
JSX中的子代:可以为任何对象(常量,变量,表达式,函数,引入组件),最终返回为JSX标签即可
使用PropTypes检查类型:
import 'PropTypes' from 'prop-types'
class Demo extends React.component {
constructor (props) {
super(props)
this.state.name = props.name
this.state.number = props.number
}
render () {
return {
{this.state.name}
{this.state.number}
}
}
}
Demo.PropTypes = {
name: PropTypes.string,
number: ProTypes.number
}
受控组件&木偶组件:
受控组件:React负责渲染表单的组件仍然控制用户后续输入时所发生的变化。相应的,其值由React控制的输入表单元素称为“受控组件”
木偶组件:只用作渲染数据,没有状态管理的组件
由于该标签的
value
属性是只读的, 所以它是 React 中的一个非受控组件
// 受控
import React form 'react'
class Demo extends React.component {
constructor (props) {
super(props)
this.state = {name: '默认值'}
this.handInput = this.handInput.bind(this)
this.handCommit = this.handCommit.bind(this)
}
handInput (e) {
this.setState({name: e.target.value})
}
handCommit (e) {
e.preventDefault()
console.log({this.state.name})
}
render () {
return {
}
}
}
Refs&dom:
// Refs
class Demo extends React.component {
constructor (props) {
super(props)
this.inputText = React.createRef()
}
handInputFocus () {
this.inputText.current.focus()
}
componentDidMount () {
this.handInputFocus()
}
render () {
return {
}
}
}
// dom
class Demo extends React.component {
constructor (props) {
super(props)
this.inputText = null
}
handInputFocus () {
this.inputText.curent.focus()
}
componentDidMount () {
this.handInputFocus()
}
render () {
return {
this.inpuText = input)} type="text"/>
}
}
}
// Refs回调
class Demo extends React.component {
constructor (props) {
super(props)
this.inputText = null
this.setInputTextRef = element => {
this.inputText = element
}
}
handInputFocus () {
if (this.inputText) {
this.inputText.focus()
}
}
componentDidMount () {
this.handInputFocus()
}
render () {
return {
}
}
}
Fragments<>>:根节点占位符
render() {
return (
<>
>
)
}
// or
class Columns extends React.Component {
render() {
return (
Hello
World
)
}
}
Portals:提供了一种很好的将子节点渲染到父组件以外的 DOM 节点的方式
第一个参数(
child
)是任何可渲染的 React 子元素,例如一个元素,字符串或碎片第二个参数(
container
)则是一个 DOM 元素
ReactDOM.createPortal(child, container)
react-redux
提供provider组件和connect方法操控store
provider
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import store from "./store";
import App from "./App";
const rootElement = document.getElementById("root");
ReactDOM.render(
,
rootElement
);
connect
import { connect } from "react-redux";
import { increment, decrement, reset } from "./actionCreators";
// const Counter = ...
const mapStateToProps = (state /*, ownProps*/) => {
return {
counter: state.counter
};
};
const mapDispatchToProps = { increment, decrement, reset };
export default connect(
mapStateToProps, // 订阅store
mapDispatchToProps // 封装dispatch
)(Counter);
redux-thunk
连接action 和 store 的中间件,升级dispatch能够返回一个函数
redux-sage 代替 redux-thunk