React框架入门学习(二)组件学习(state PK props)
组件就是页面编排过程中很重要的组成部件,就像搭积木一样,把组件一块一块地拼接起来,可以把这块拼上去,也可以把那块拆下来。
具体知识可以参照React官方手册。
React官方中文文档地址: https://doc.react-china.org/
state
一个组件的显示形态是可以由它数据状态和配置参数决定的。一个组件可以拥有自己的状态,就像一个按钮,可以有“同
意”和“不同意”状态,并且可以在这两种状态之间进行切换。
React.js 的 state
就是用来存储这种可变化的状态的。
setState
方法由父类 Component
所提供。当我们调用这个函数的时候,React.js 会更新组件的状态 state
,并且重新调
用 render
方法,然后再把 render
方法所渲染的最新的内容显示到页面上。
注意,当我们要改变组件的状态的时候,不能直接用 this.state = xxx
这种方式来修改,如果这样做 React.js 就没办法知道
你修改了组件的状态,它也就没有办法更新页面。所以,一定要使用 React.js 提供的 setState
方法,它接受一个对象或者
函数作为参数。
State中的属性只能在组件内部声明和使用。
setState 接受函数参数
这里还有要注意的是,当你调用 setState
的时候,React.js 并不会马上修改 state。而是把这个对象放到一个更新队列里面,稍后才会从队列当中把新的状态提取出来合并到 state
当中,然后再触发组件更新。这一点要好好注意。可以体会一下下面的代码:
...
handleClickOnLikeButton () {
console.log(this.state.isLiked)
this.setState({
isLiked: !this.state.isLiked
})
console.log(this.state.isLiked)
}
...
你会发现两次打印的都是 false
,即使我们中间已经 setState
过一次了。这并不是什么 bug,只是 React.js 的 setState
把你的传进来的状态缓存起来,稍后才会帮你更新到 state
上,所以你获取到的还是原来的 isLiked
。
所以如果你想在 setState
之后使用新的 state
来做后续运算就做不到了,例如:
...
handleClickOnLikeButton () {
this.setState({ count: 0 }) // => this.state.count 还是 undefined
this.setState({ count: this.state.count + 1}) // => undefined + 1 = NaN
this.setState({ count: this.state.count + 2}) // => NaN + 2 = NaN
}
...
上面的代码的运行结果并不能达到我们的预期,我们希望 count
运行结果是 3
,可是最后得到的是 NaN
。但是这种后续操作依赖前一个 setState
的结果的情况并不罕见。
这里就自然地引出了 setState
的第二种使用方式,可以接受一个函数作为参数。React.js 会把上一个 setState
的结果传入这个函数,你就可以使用该结果进行运算、操作,然后返回一个对象作为更新 state
的对象:
...
handleClickOnLikeButton () {
this.setState((prevState) => {
return { count: 0 }
})
this.setState((prevState) => {
return { count: prevState.count + 1 } // 上一个 setState 的返回是 count 为 0,当前返回 1
})
this.setState((prevState) => {
return { count: prevState.count + 2 } // 上一个 setState 的返回是 count 为 1,当前返回 3
})
// 最后的结果是 this.state.count 为 3
}
...
这样就可以达到上述的利用上一次 setState
结果进行运算的效果。
setState 合并
上面我们进行了三次 setState
,但是实际上组件只会重新渲染一次,而不是三次;这是因为在 React.js 内部会把 JavaScript 事件循环中的消息队列的同一个消息中的 setState
都进行合并以后再重新渲染组件。
深层的原理并不需要过多纠结,只需要记住的是:在使用 React.js 的时候,并不需要担心多次进行 setState
会带来性能问题。
而Props是上一层的组件传递给下一层的参数,比如:有两个组件,“main”和“view”,main是上一层的组件,view被包含在main当中,是main的子组件,那么main组件就可以把参数通过Props传递给view组件。这一过程是不可逆的,无法从view传回到main,也就涉及到了React框架的单向数据流的特性。如下图所示:
(这里摘自https://blog.csdn.net/daxiazouyizou/article/details/79754021)
ndex.js代码如下:前两个是react生成和render需要的包,import App from './App';是导入自己写的组件:
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
ReactDOM.render(<App/>, document.getElementById('root'));
在已经生成的my-new-app中,APP.js代码如下,这里采用继承React.Component组件的办法(类的方式)新建组件:
import React from 'react';
class App extends React.Component {
constructor(props) { //构造函数
super(props);
this.state = {
text : 'This is TEXT!'
}
}
render(){
return(<div>{this.state.text}</div>)
}
}
export default App;
下方的“export default App;”作用是将App组件发布出去,也就是说其他文件可以通过App这个名称从该文件中获取App组件。
保存后,可以看到:
下面来介绍Props的用法,既然要用到Props,就需要再创建一个组件内容,其构造方式与App组件相似,只是在render函数中return的标签内输入{ this.props.text },意思就是获取并显示上一个组件传到这个组件的数据中名称为“text”的属性值。如下所示:
import React from 'react';
class PropsTest extends React.Component {
constructor(props) { //构造函数
super(props);
this.state = {
}
}
render(){
return(<div>{this.props.text}</div>)
}
}
export default PropsTest;
对APP.js进行更改:
import React from 'react';
import PropsTest from './propsTest';
class App extends React.Component {
constructor(props) { //构造函数
super(props);
this.state = {
text : 'This is TEXT!'
}
}
render(){
let text = this.state.text;
return(<PropsTest text={text} />)
}
}
export default App;
在render函数里,通过let创建一个变量text,获取state中的text属性的值。
然后再return里面输入<PropsTest/> 标签,并在其中添加语句 text={ text },意思就是将上面let的text变量传输到PropsTest组件中。
保存两个文件,就能在网页窗口中看到和之前一样的内容,但之前是由App组件显示其State里的属性,而现在是由PropsTest组件获取App组件传来的Props中的text属性,然后将其显示出来。一个来自State,一个来自Props。
接下来完成的是react路由的选择 https://blog.csdn.net/weixin_30363263/article/details/80992288
上一篇: 咸鱼虾扯蛋
下一篇: 设计模式:State模式