Fragment
占位符
方法中this指向
this.handleChange.bind(this)
list中key的问题
index.js:1375 Warning: Each child in a list should have a unique “key” prop.
immutable
state 不允许改变
添加class=‘xx’ className报错问题
<input className='input'
如何使标签中的tag不被转义
this.state.list.map((v, i) => {
return <li key={i}
onClick={this.handleItemDelete.bind(this, i)} dangerouslySetInnerHTML={{__html: v}}></li>})
htmlFor的作用
<label htmlFor='input-area'>输入内容</label>
<input id='input-area'
...
父组件如何向子组件传递数据
// 标签赋值
<TodoItem content={item}>
<div>{this.props.content}</div>
一般的方法绑定,会不会损耗性能,怎么优化?
// 好的写法
class xx {
constructor(props) {
super(props)
this.handleClick = this.handleClick.bind(this)
}
render() {return div onClick={this.handleClick}}
handleClick() {console.log(this.props.index)}
}
// 不好的写法
render() {
return div onClick={this.handleClick.bind(this)}
}
子组件怎么修改父组件的数据
子组件怎么调用父组件的方法改变父组件的数据?
和变量传递一样,将父组件的方法通过props赋值传给子组件,注意要bind tihs
todo 优化
- 父组件传值,善于用结构赋值
- setState里面传函数,不直接传对象
// const list = [...this.state.list, this.state.inputValues]
// this.setState(() => ({
// list: list,
// inputValues: ''
// }))
// 更靠谱的写法
this.setState((prevState) => ({
list: [...prevState.list, prevState.inputValues],
inputValues: '',
}))
this.setState((prevState) => {
const list = [...prevState.list]
list.splice(index, 1)
return {list}
})
命令式vs申明式
2019-05-21 14:34:57 总结
- 声明式开发
- 可以其他框架bingcun
- 组件化
- 单项数据流
- 父组件可向子组件传值,但子组件不能改变父组件的值
- 视图层框架
- 函数式编程
PropTypes 与 DefaultProps
- PropTypes 属性接收的强校验
// 检查属性的类型
TodoItem.propTypes = {
// 要求有这个字段
test: PropTypes.string.isRequired,
content: PropTypes.string,
deleteItem: PropTypes.func,
index: PropTypes.number,
}
// 定义属性的默认值
TodoItem.defaultProps = {
test: 'hello world',
}
props, state, render
数据绑定原理
当state或props发生改变,render会重新执行
父组件发生变化,子组件的render都将执行
虚拟dom
原始方案
- state 数据
- 模板jsx
- 数据 + 模板,生成真实dom
- state发生改变
- 数据 + 模板,生成正dom,替换原始dom(有问题,寻找替换方案↓)
- (方案2)
- 数据 + 模板,生成正dom,不直接替换原始dom
- 新dom和原始dom对比
- 找出发生了变化的dom
- 只用新dom中的元素替换老相同元素
虚拟dom方案(草案)
- state 数据
- 模板jsx
3, 数据 + 模板,生成真实dom,显示
<div id='abc'><span>hello</span></div>
- 生成虚拟dom (js对象) (损耗新能)
['div', {id: 'abc'}, ['span', {}, 'hello world']]
- state发生变化
- 数据 + 模板,生成新的虚拟dom (提升了性能)
['div', {id: 'abc'}, ['span', {}, 'bye bye']]
- 比较原始dom和新dom的区别,定位到变化的span (提升了性能)
- 直接操作dom,改变span中的内容
虚拟dom方案(实际)
- state 数据
- 模板jsx
- 生成虚拟dom (js对象) ,显示,(损耗新能)
- jsx -> createElement -> js对象(虚拟dom) -> 真实dom
['div', {id: 'abc'}, ['span', {}, 'hello world']]
// render 对比
render() {
const { content, test } = this.props // 结构赋值
return <div><li>node node</li></div>
// return React.createElement('div', {}, React.createElement('li', {}, 'node node'))
}
4, 数据 + 模板,生成真实dom,显示
<div id='abc'><span>hello</span></div>
- state发生变化
- 数据 + 模板,生成新的虚拟dom (提升了性能)
['div', {id: 'abc'}, ['span', {}, 'bye bye']]
- 比较原始dom和新dom的区别,定位到变化的span (提升了性能)
- 直接操作dom,改变span中的内容
虚拟dom好处
- 性能提升。dom对比->js对比
- 使得跨端应用得以实现: React Native
虚拟dom diff算法
- setState设计成异步的原因
为了提高性能。多次set可以合并成一次,再渲染dom
1 | 2 | 3 |
---|---|---|
setState | dirty | re-rendered |
-
diff
-
同级比较,如果同层不一样,那么下面就不再比较了
-
用index做key值的弊端
key值不稳定
例子:
不稳定:
a 0 b 1 c 2
删除a标签
b 0 c 1稳定:
a a b b c c
删除a标签
b b c c
ref
ref直接操作dom
<input id='insertArea' className='input'
ref={(xx) => this.xx = xx}
setState 异步完成后回调
setState 第二个函数
使用场景:例如在页面更新后再去获取dom
生命周期
// - constructor
-
initialization
- set state and props
-
mounting
- componetWillMount
- render
- componetDidMount
-
updating
-
(props
-
componentWillReceiveProps
没有props参数(没有父组件)的话,不会被执行
- 一个组件要从父组件接受参数
- 该组件第一次存在于父组件中,不会执行
- 已存在,才会执行
-
-
(state
-
(props, state公共生命周期:)
- shouldComponentUpdate
(bool, 组件被更新之前)
- componentWillUpdate
(组件被更新之前,should之后)
- render
- componentDidUpdate
-
-
unmounting
-
componentWillUnmont
被从页面上移除时
-
生命周期使用场景
react怎么做性能优化?
- constructor中做函数的绑定
- setState中采用异步函数
- 虚拟dom,list中key值
- 由于父组件有变化,会导致子组件不断render
shouldComponentUpdate(nextProps, nextState) {
return nextProps.content === this.props.content
}