React类组件基础03-其他API

157 阅读4分钟

写在前面:

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()生命周期函数

该函数接收两个参数:nextPropsnextState这两个参数是更新后的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属性,该属性是一个数组,依次记录着每一条写入的内容。