本章内容
上一节我们讲了如何使用 PropTypes
及 DefaultProps
来进行属性的类型校验及设置属性默认值。本节内容我们来了解一下 state
、props
与render
函数的关系。
一、state 与 render 函数的关系
- 我们知道,
React
是一个有”数据“驱动视图的框架,即:数据发生变化,页面视图就会自动的跟着发生变化。那这背后的原理是怎么样的呢? - 这背后其实是这样运作的:当组件的
state
或者props
发生变化时,render
函数就会重新执行。而界面又是由render
函数渲染出来的,所有数据发生变化,界面自然而然的自动跟着变化。 - 下面我们来打开
TodoList.js
来演示一遍(不断地更改输入框的值,观察render
函数的执行情况)
import React, { Component, Fragment } from "react";
import TodoItem from "./TodoItem";
class TodoList extends Component{
constructor(props) {
super(props)
this.deleteData = this.deleteData.bind(this)
this.addListData = this.addListData.bind(this)
this.changeInputValue = this.changeInputValue.bind(this)
this.state = {
inputValue: '',
list: []
} // 1、一旦 state 中的数据发生变化(可以通过操作输入框的数据来使其数据发生变化)
}
render() { // 2、render 函数会重新执行(重新使用新的数据进行渲染)
console.log('render') // 3、这里使用 console 来巧妙观察render函数是否在数据变化时执行
return (
<Fragment>
<div>
<label>请输入要进行的事项:</label>
<input value={this.state.inputValue} onChange={this.changeInputValue} />
<button onClick={this.addListData}> 提交 </button>
</div>
<ul> {this.getTodoItem()} </ul>
</Fragment>
)
}
getTodoItem() {
return this.state.list.map((item, index) => {
return <TodoItem key={index} content={item} index={index} deleteFn={this.deleteData}></TodoItem>
})
}
deleteData(index) {
this.setState((prevState) => {
const list = [...prevState.list]
list.splice(index, 1)
return {list}
})
}
addListData() {
this.setState((prevState) => ({
list: [...prevState.list, prevState.inputValue],
inputValue: ''
}))
}
changeInputValue(e) {
const value = e.target.value
this.setState(() => ({inputValue: value}))
}
}
export default TodoList
- 运行代码,你会发现,当输入框输入数据在变化时,控制台就相应的输出
render
函数中打印的信息”render“
二、props 与 render函数的关系
- 打开
TodoItem.js
,我们来演示下props
变化,界面跟着变化的情形
import React, { Component } from 'react'
import PropTypes from 'prop-types'
class TodoItem extends Component {
constructor(props) {
super(props)
this.handleClick = this.handleClick.bind(this)
}
render () {
console.log('TodoItem 的 render 函数执行了') // 1、当属性数据发生变化,会重新执行 render 函数,打印此信息
/*
2、通过属性从父组件传来的数据。
2.1 子组件的 content 是从父组件接收的,在父组件 TodoList 里,content的值是列表循环的每一项。
当输入框输入数据并点击提交,列表的数据会发生变化,
子组件收到的属性数据也会发生变化,子组件的 render 函数会根据新值进行渲染
2.2 当父组件的 render 函数运行时,其子组件的 render 函数也会被运行一次。
因为子组件也是被父组件的render函数渲染出来的,所以父组件的render执行,子组件的render也会执行
*/
const { content, title } = this.props
return (
<div onClick={this.handleClick}>
{/* 展示在界面的内容 content2 */}
{title}---{content}
</div>
)
}
handleClick() {
const { deleteFn, index } = this.props
deleteFn(index)
}
}
TodoItem.propTypes = {
title: PropTypes.string.isRequired,
content: PropTypes.string,
index: PropTypes.number,
deleteFn: PropTypes.func
}
TodoItem.defaultProps = {
title: '我是子组件'
}
export default TodoItem
- 本章的
state
及props
跟render
函数的关系介绍到这里。可能小伙伴们存在一些疑惑,可以等介绍完”虚拟DOM“的知识后回过来看,那时可能会对React
的”数据驱动“思想有更深的了解
到此,本章内容结束!