写在前面:
1.本文是个人课上学习内容的总结和梳理,主要知识点来自于“开课吧”线上直播课程,以及 React 官方文档。
2.目前尚处于 React 乃至前端入门阶段,因此很多内容理解的不是很透彻,文章更多是用来学习记录而非干货分享。
因此,建议如果需要解决项目问题,还是去看一下其他大佬的文档以及 React 官方文档(一手资料)
key
key在列表渲染当中是必要的,用来表示每一条元素的唯一身份标识。
如果我们在遍历数组渲染列表的时候,没有添加key,那么在这段js代码运行在浏览器的时候,会抛出一个警告a key should be provided for list items,告诉我们必须要添加一个key。那么这个key为什么如此必要呢?
- 给虚拟DOM添加一个标识符,方便视图更新时匹配到每一个节点。
- 说白了,就是给每一个节点一个ID,并告诉react记录下来,在每次更新时,比对每一个虚拟DOM节点更新前后的ID,如果前后ID一致,这个节点就不进行更新;如果不一致,那么这个节点就进行对应的更新
- 这个ID一定要是数据提供的,不能是我们自己写死的ID
const data = [{ id:1, todo:"我要学前端" },{ id:2, todo:"我要学后端" },{ id:3, todo:"我要学全栈" }] function TodoList(props){ const data = props.data const todoItems = data.map(item => { <li key={item.id}> {item.todo} </li> }) return <ul>{todoItems}</ul> } ReactDOM.render( <TodoList data={data} />, document.getElementById('root') );复制代码
- 还需要注意的一点是,key值的唯一性指的是在同一级兄弟节点之间需要保持唯一:上述的<TodoItems />标签里面的每个li标签的key需要保持唯一。但是不必要求全局唯一:如果这是又冒出来一个<FinishList />标签,这里面的li标签的key值没必要和上面这个<TodoItems />里面的区分开来。
PureComponent
首先,react.PureComponent组件和react.Component类似,都是用来生成类组件的。不同的一点是,react.PureComponent利用类组件的生命周期函数shouldComponentUpdate()来进行浅对比:如果当前的props和state与更新后的props和state一致,就不更新视图。如果不一致,就会更新视图。
- shouldComponentUpdate()生命周期函数
该函数接收两个参数:nextProps和nextState这两个参数是更新后的props和state,这个生命周期函数如字面意思,是在组件视图更新前执行的。如果前后不一致,则会返回true,组件视图就会进行下一步的视图更新。
shouldComponentUpdate(nextProps,nextState){ // 获取更新前的 props|state 和 更新后的 props|state判断组件是否需要进行更新 // 这时挂载在this上面的state和props仍是更新前的state和props if(nextProps.data !== this.props.data)return true; return false; }复制代码
因为直接通过生命周期函数控制视图是否更新有风险,容易出现各类意想不到的bug,所以,react并不推荐用这种方式,而是给我们封装好了一个可以实现浅对比的类react.PureComponent,通过react.PureComponent创建的类组件实例,就会在每一次更新前全对比props和state以决定是否进行视图更新。
ref
ref表示一个响应式对象,在react中用来获取组件实例或者真实的 DOM 节点。react给我们提供了createRef方法来创建一个ref对象,然后在想要绑定的标签内,通过 ref={声明好的ref对象}将该标签绑定成响应式对象。
class Todo extends PureComponent { todoEl = createRef(); render() { return <span ref={this.todoEl} > this is ref object </span> }复制代码
child
一般我们在app组件中调用各种类组件是,都是使用单标签的,那么有没有想过,如果我们使用双标签,并且在标签内写入内容呢,那么在调用这个组件的同时,会发生什么事情呢?
// App.js组件 class App extends Component { render() { // 调用组件时,如果在标签对中间写内容,该内容会传递给子组件的props.children 属性 return <Child> <div>明天周末了,要约一块做练习吗</div> <button>约</button> <button>不约,练习太少已经做完了</button> {()=>{ alert("你想干啥") }} </Child> } } //Child.js class Child extends Component { render(){ return <div> <h1>children</h1> {this.props.children.slice(0,3)} </div> } }复制代码
答案是这样的,如果我们在标签对中间写入内容时,不管这些内容时元素标签还是函数方法,都会传递给子组件的
props.children属性,该属性是一个数组,依次记录着每一条写入的内容。