由于静态组件很枯燥,所以这里会包含组件的状态与交互。
组件内部状态
组件内部状态也叫做局部状态,可以保存修改和删除储存在组件内部的属性。使用ES6类组件可以在构造函数中初始化组件的状态。构造函数只会在组件初始化的时候调用一次。
class App extends Component {
constructor(props) {
super(props);
}
}
在这段代码中,App继承自Component
,如果在子类中使用了构造函数constructor
那么就必须使用super()
方法,关于constructor
的描述,请查阅constructor。
你也可以使用super(props)
,它会在你的构造器中设置this.props
,设置之后你就可以在构造函数中使用this.props
,如果没设置,使用this.props
会得到undefined
初始化组件数据
下面将举例初始化一个列表,现在先使用本地数据,通过api的方式获取数据在后面会讲到。
...
const list = [
{
id: 0,
truename: '小明',
age: 23
},
{
id: 1,
truename: '小红',
age: 24
},
{
id: 3,
truename: '小灰灰',
age: 12
}
]
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
list: list,
};
}
render() {
return (
<div>
{
this.state.list.map((item) => {
return (
<div key={item.id}>
<span>姓名:{item.truename}</span>
<span>年龄:{item.age}</span>
</div>
)
})
}
</div>
)
}
}
...
以上代码渲染的效果入下:
现在组件中的list数据已经设置成功并显示出来了,里可以继续对list添加、修改或者删除,每次数据被修改时都会触发render
函数以保证组件重新渲染并且展示正确数据。
需要注意的是,修改数据时不要直接修改原数据,必须使用serState()
方法来修改
修改组件数据
我们先增加一个按钮,并绑定点击事件,在事件触发时传递当前列表的id,以便在后续的处理函数中找到需要删除的项。在这里需要注意的是在map函数遍历时一定要使用箭头函数,例如下文中的map((item) => { ... })
以及button的onClick={() => this.onDismiss(item.id) }
如果你没有使用箭头函数,那么this
的指向会让你非常痛苦。
函数this关键字请查看:this
箭头函数请查看:箭头函数
class App extends React.Component {
...
render() {
return (
<div>
{
this.state.list.map((item) => {
return (
<div key={item.id}>
<span>姓名:{item.truename}</span>
<span>年龄:{item.age}</span>
// start
<span>
<button
onClick={() => this.onDismiss(item.id) }
type="button"
>
删除
</button>
</span>
</div>
)
})
}
</div>
)
}
}
看到这儿相信你按钮和点击事件已经绑定成功了,那么接下来我们将完成onDismiss
的功能,它通过接收一个函数来标识哪一项需要被删除,这个函数需要绑定到类中,所以访问它是使用this.onDismiss()
而不是onDismiss()
。
class App extends Component {
constructor(props) {
super(props);
this.state = {
list,
};
this.onDismiss = this.onDismiss.bind(this);
}
onDismiss(id) {
// 过滤出点击的id和列表中id不相等的所有数据
const updatedList = this.state.list.filter(item => item.id !== id)
// 修改list的数据
this.setState({ list: updatedList })
}
render() {
...
}
}
上面的方法中使用了this.setState()
方法来修改list的数据,它遵循了 React 中不可变数据的约定
效果如下:
和表单交互
在这一部分我们将尝试给表单组件一个初始值以及监听表单数据的变化。和vue不同的是表单的监听和赋值需要手动实现。
现在先让我们定义一个字符串text和一个input输入框
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
text: '我是一个默认值'
}
}
render() {
return (
<div>
<div>
<input />
</div>
</div>
)
}
}
效果:
接下来我们需要给输入框绑定上我们已经定义的默认数据text
并绑定上监听事件,在React中元素上绑定的所有事件被称为合成事件,如果感兴趣可以去官网中找到关于合成事件的介绍。
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
text: '我是一个默认值'
}
this.inputChange = this.inputChange.bind(this)
}
inputChange(event) {
this.setState({ text: event.target.value })
}
render() {
return (
<div>
<div>
<input
value={ this.state.text }
onChange={ (e) => this.inputChange(e) }
/>
</div>
</div>
)
}
}
实操测试
结合以上的知识编写简易版百度搜索页面。完整代码以及运行会放到文章最后,在这个案例中会安装两个插件mockjs
和axios
mockjs
可以拦截ajax请求,生成伪数据。
axios
是目前最流行的ajax封装库之一,可以方便地实现ajax请求的发送
关于插件的安装可以自行搜索,有大量教程讲解
import React from 'react';
import './App.css';
import axios from "axios"
const isSearched = searchTerm => item => item.title.toLowerCase().includes(searchTerm.toLowerCase())
const Shaerch = ({ value, onChange, children }) => {
return (
<div className="shaerch">
<div className="input-box">
<input
className="input"
onChange={ onChange() }
value={ value }
/>
<button
className="shaerch-btn"
>
{ children }
</button>
</div>
</div>
)
}
const Table = ({ list, pattern, onDismiss }) => {
return (
<ul className="news-body">
{
list.filter(isSearched(pattern)).map((item) => {
return (
<li key={item.id}>
<div className="news-a">
{/* eslint-disable-next-line */}
<a href="#">{ item.title }</a>
</div>
<div className="news-content">{ item.body }</div>
<span>
<Button
className='submit-btn'
onClick={ () => onDismiss(item.id) }
>不感兴趣</Button>
</span>
</li>
)
})
}
</ul>
)
}
const Button = ({ onClick, className = '', children }) => {
return (
<button
onClick={onClick}
className={className}
type="button"
>
{children}
</button>
);
}
class App extends React.Component {
constructor(props) {
super(props)
this.state = {
list: [],
shaerchText: ''
}
this.onDismiss = this.onDismiss.bind(this)
this.onShearchChange = this.onShearchChange.bind(this)
}
onDismiss(id) {
const updateList = this.state.list.filter(item => item.id !== id)
this.setState({
list: updateList
})
}
onShearchChange(event) {
this.setState({
shaerchText: event.target.value
})
}
getNewsList() {
axios.get("/news/list").then(res => {
this.setState({list: res.data.list})
}).catch(err => {
console.log(err);
})
}
componentDidMount() {
this.getNewsList();
}
render() {
const { list, shaerchText } = this.state
return (
<div className="App">
<div>
<Shaerch
value={shaerchText}
onChange={ () => this.onShearchChange }
>
搜索
</Shaerch>
<Table
list={list}
pattern={shaerchText}
onDismiss={this.onDismiss}
/>
</div>
</div>
);
}
}
export default App;