文章目录
react 中的数据承载— state/props
任意的视图变化都应该是由数据来控制的
React也是基于数据驱动(声明式)的框架,组件中必然要承载一些数据,在react助攻起到这个作用的是属性(props)和状态(state)
- 属性(props):在组件外部传入,或者内部设置,组件内部通过this.props获取
- 状态(state):在组件内部设置或者更改,组件内部通过this.state获取
props 属性
属性一般是由外部传入的,组件内部也可以通过一些方式来进行初始化的设置
属性不能被组件自己更改
使组件拥有属性的方式:
1. 在装载组件的时候传入
组件中属性的传递
let App extends React.Component{
render(){
return (
<h1>{this.props.info}</h1>
)
}
}
let info = "我是谁"
ReactDOM.render(<App {...info} />,doucment.getElementById("box"))
通过解构的方式将数据添加到组件的props/属性上
2. 父组件给子组件传入
父组件嵌套子组件的时候,给子组件传入,传入的方式和上面的方式一样,都是使用info={this.info}的这样的
class Father extends React.Component{
render(){
return(
<div>
这是父组件
<Son info={this.info}></Son>
</div>
)
}
}
3. 逻辑判断
根据属性或者状态,我们可以在render中的表达式里进行一些逻辑判断,可以使用||、三目运算符、子执行函数等等
getName(){
return this.props.name || '野狗子'
},
render:function () {
let {name} = this.props
return (
<div>
<p>我是子组件-{this.props.name || '野狗子'}</p>
<p>我是子组件-{this.props.name?this.props.name:'野狗子'}</p>
<p>我是子组件-{this.getName()}</p>
</div>
)
}
状态(state)
状态是组件描述某种情况的数据,由组件自己设置和更改,也就是说有组件自己维护,使用状态的目的就是wield在不同的状态下是组件的显示不同
在组件中可以通过constructor构造函数来给组件挂载初始状态,在类组件内部通过this.state获取状态
this.props和this.state是纯js对象,
d a t a 属 性 是 利 用 O b j e c t . d e f i n e P r o p e r t y 处 理 过 的 , 更 改 data属性是利用Object.defineProperty处理过的,更改 data属性是利用Object.defineProperty处理过的,更改data的数据的时候会触发数据的getter和setter,但是react中没有做这样的处理,如果直接更改的话,react是无法得知的,所以,需要使用特殊的更改状态的方法:
setState(params)
在setState助攻传入一个对象,就会将组件的状态中键值对的部分进行更改,还可以传入一个函数,这个歌回调函数必须返回和上面方式一样的一个对象,函数可以接收prevState和props参数。
– 参数是对象
state = {
count:1
}
// 1. 方法一,传入对象
this.setState = ({
count:this.state.count * 2
})
– 参数是方法
// 2. 方法二,传入一个函数
this.setState((prevState,props)=>{
return {
count : preveState.count *2
}
})
注意的是这个传入的函数接收两个参数,第一个是上一次的state, 第二个是props
setState
是异步的,所以想要获取到最新的state,没有办法获取,就有了第二个参数,这是一个可选的回调函数
this.setState(()=>{
return {
count : preveState.count *2
}
},()=>{
console.log("回调里的:"this.state.doing)
})
两种setState的比较
-
对象形式
这种setState方法会对自身进行浅层合并,短时间多次调用setState更新状态只会执行一次 -
函数形式
这种形式采用prevState来获取前一次的数据,连续多次执行时不会合并
函数式组件定义状态
在函数式组件中如何自定义状态?
----> 使用react中解构出的方法useState
const App = props =>{
const [count,setCount] = useState(0)
return(
<h1>
获取count的数量---{count}----
<button onClick={setCount(count+1)>点击修改count</button>
</h1>
)
}
扩充–> 关于constructor中的super()
super关键字用于访问和调用一个对象的父对象上的函数。
class App extends Component{
constructor(){
super()
}
}
属性和状态的对比
相似点:都是纯的js对象,都会触发render更新,都具有确定性(状态/属性相同,结果相同)
不同点:
- 属性能从父组件获取,状态不能
- 属性可以由父组件修改,状态不能
- 属性能在内部设置状态值,状态也可以
- 属性不在组件内部修改,状态可以
- 属性能设置子组件初始值,状态不可以
- 属性可以修改子组件的值,状态不可以
state
的主要作用是用于组件保存、控制、修改自己的可变状态。state
在组件内部初始化,可以被组件自身修改,而外部不能访问也不能修改。你可以认为 state
是一个局部的、只能被组件自身控制的数据源。state
中状态可以通过 this.setState
方法进行更新,setState
会导致组件的重新渲染。
props
的主要作用是让使用该组件的父组件可以传入参数来配置该组件。它是外部传进来的配置参数,组件内部无法控制也无法修改。除非外部组件主动传入新的 props
,否则组件的 props
永远保持不变。
没有 state
的组件叫无状态组件(stateless component),设置了 state 的叫做有状态组件(stateful component)。因为状态会带来管理的复杂性,我们尽量多写无状态组件,尽量少写有状态的组件。这样会降低代码维护的难度,也会在一定程度上增强组件的可复用性。