非受控组件
数据随用随取, 输入类的数据没有被state维护
受控组件
输入类的数据被state维护, 能省略掉ref
高阶函数
符合下面任意一条就能被称为高阶函数
1. 若函数A, 接收的是一个函数, 那么这个函数A就可以称为高阶函数
2. 若函数A, 调用的返回值依然是一个函数, 那么A也可以被称为高阶函数
常见的高阶函数:
promise, setTimeout, array很多的操作
函数的柯理化
通过函数调用继续返回函数的方式, 实现多次接受参数最终统一处理的函数编码形式
save = (data) => {
// 这么写的时候, 当使用 this.save('userName')调用 只会输出 字符串 userName
console.log(data)
}
// 这么写的意思是 将save函数交给onChange回调
<input onChange={this.save} />
// 这么写的意思是将save()函数的返回值交给 onChange 进行回调
<input onChange={this.save('userName')} />
// 将save这么改造之后, 内部返回的是一个函数, event 是event, data 则是字符串userName
save = (data) => {
// 这个data 是函数传递的字符串
console.log(data)
// 这个函数是被 onChanged调用
return (event) => {
console.log(event.target.value)
}
}
save = (dataType) => {
return (event) => {
// 这里注意 不能直接写dataType:event.target.value
// 加[] 意思是读取 dataType这个变量, 而不是把他当做字符串
this.setState({[dataType]:event.target.value})
}
}
当到真正使用的时候, 直接去state里取就可以了
const { uname, pwd } = this.state
组件的生命周期
<script type="text/babel">
// 1. 创建class组件
class Dom extends React.Component {
state = {opacity:1}
componentDidMount() {
// 组件挂载的时候 开启计时器
this.timer = setInterval(() => {
let {opacity} = this.state
opacity -= 0.1
if(opacity <= 0) opacity = 1
this.setState({opacity})
}, 200)
}
componentWillUnmount() {
// 组件卸载的时候清除计时器, 也叫生命周期钩子函数
clearInterval(this.timer)
}
removeH1 = () => {
// 卸载组件
ReactDOM.unmountComponentAtNode(document.getElementById('app1'))
}
render() {
return (
<div>
<h1 style={{opacity:this.state.opacity}}>test react 声明周期</h1>
<button onClick={this.removeH1}>点击</button>
</div>
)
}
}
ReactDOM.render(<Dom />, document.getElementById('app1'))
</script>
完整的生命周期(旧版本)
上图中父组件有三条线
从上到下
setState() 触发 shouldComponentUpdate 的更新 这个函数默认返回true
forceUpdate() 触发 componentWillUpdate, 不会收到上面shouldComponentUpdate影响
1. 初始化阶段: 由ReactDOM.render()触发 --- 初次
constructor()
componentWillMount()
render()
componentDidMount()
2. 更新阶段: 由组件内部的setState或者父组件render触发
shouldComponentUpdate()
componentWillUpdate()
render()
componentDidUpdate()
3. 卸载组件: 由ReactDOM.unmountComponentAtNode()触发
componentWillUnmount()
新版本的生命周期
1. 初始阶段
constructor()
// state的值, 任何时候都取决于props 可以重写这个函数
static getDerivedStateFromProps(props, state) -- 几乎不怎么用, 必须返回state对象或者null
render()
componentDidMount()
2. 更新阶段
static getDerivedStateFromProps()
souldComponentUpdate()
redner()
getSnapshotBeforeUpdate(preProps, preState) -- 几乎不怎么用, 相当于是更新前的状态
componentDidUpdate(preProps, preState, snapShot) -- snapShot 就是 上面那个方法 return出来的
3. 卸载组件
componentWillUnmount()
diffing算法
react 中的key有什么作用?
首先, key是虚拟DOM对象的标识, 在更新显示时起着重要的作用
其次, 当状态中的数据发生变化时, react会根据新数据生成新的虚拟DOM, 随后会拿新旧进行比较
1. 旧虚拟DOM中找到了与新虚拟DOM相同的key
. 若虚拟DOM中的内容没有改变, 直接使用之前的真实DOM
. 若虚拟DOM中的内容改变了, 则生成新的真实DOM, 随后替换掉页面中之前的真实DOM
2. 旧虚拟DOM中未找到与新虚拟DOM相同的key
根据数据创建新的真实DOM, 随后渲染到页面上
为什么遍历的时候不要用index作为key?
1. 若对数据进行: 逆序添加, 删除, 等破坏顺序操作, 会产生没有必要的真实DOM更新(界面没问题但效率低)
2. 如果结构中还包含输入类的DOM, 会产生错误DOM更新
3. 如果不存在对数据的逆序添加, 删除等破坏顺序的操作, 只用于渲染列表展示, 这个时候是没问题的
那开发中如果选择key?
1. 最好使用每条数据的唯一标识作为key
2. 如果确定只是简单的展示数据, 用index也是可以的
一旦含有input输入框的, 有输入内容, 就容易出现内容混乱
<li key=index> {obj.name} <input type="text"></li>