上一篇说了cli环境安装这篇说组件传值 此文参考
state 和 props 主要的区别在于 props 是不可变的,而 state 可以根据与用户交互来改变。这就是为什么有些容器组件需要定义 state 来更新和修改数据。 而子组件只能通过 props 来传递数据。
关于React的一个重大交易是它如何处理数据,它使用
属性(称为props)
和state
来实现;
-
父子组件传值 (Props)
我们将tb数据 组成数组对象由父组件=>App.js传递到Table.js ,现在我们将Table.js整理下
//App.js
//必须在App内部创建这个数组 "render()"
render(){
const characters = [
{
name: 'Charlie',
job: 'Janitor',
},
{
name: 'Mac',
job: 'Bouncer',
},
{
name: 'Dee',
job: 'Aspring actress',
},
{
name: 'Dennis',
job: 'Bartender',
},
]
return(
<div className="container">
<Table characterData={ characters } />
<Time />
</div>
)
}
//Table.js:
//提取组件 将table组件提取成 Header Body两个小组件
const TableHeader = () => {
return (
<thead>
<tr>
<th>Name</th>
<th>Job</th>
</tr>
</thead>
)
}
const TableBody = props=> {
const rows=props.characterData.map((item,i)=>{ // 映射
return (
<tr key={i}>
<td>{item.name}</td>
<td>{item.job}</td>
</tr>
)
})
return <tbody>{rows}</tbody>
}
class Table extends Component {
// 类组件必须包含render(),并且return只能返回一个父元素。
render() {
const { characterData}=this.props // 父组件传递的值
return (
<table>
<TableHeader/>
<TableBody characterData={characterData} />
</table>
)
// 如果return包含在一行中,则不需要括号。
}
}
tips:数组对象需要在App组件里建立
JavaScript Map es6 此时应该跟上篇显示效果是一样的
-
现在我们来实现一个时钟显示的功能小组件:
-
思路:
显示初始值
=>构造函数
=>每隔1s执行一次并渲染到ui
定义一个Time组件方便之后使用 (组件命名规则首字母大写,属性:小驼峰)
//App.js:
const Time=()=>{
return <h3>{new Date().toLocaleTimeString()}</h3>
}
//App组件内部
<div className="container">
<Table characterData={ characters } removeCharacter={this.removeCharacter} />
<Time />
</div>
-
toLocaleTimeString
:可根据本地时间把 Date 对象的时间部分转换为字符串,并返回结果。 - React 非常灵活,但它也有一个严格的规则:
所有 React 组件都必须像纯函数一样保护它们的 props 不被更改。
这时候我们使用state
,在不违反上述规则的情况下,state 允许 React 组件随用户操作、网络响应或者其他变化而动态更改输出内容。
// 将Time修改
class Time extends Component{
constructor(props) { //构造函数 将props 传递到父类的构造函数中
super(props);
this.state={time:new Date()} // 给state赋值
}
render(){
return <h3>{this.state.time.toLocaleTimeString()}</h3>
}
}
-
constructor
:是一种用于创建和初始化创建的对象的特殊方法 查看具体请点击 - 现在需要在组件挂载时开始每秒渲染 实现 时钟。这就需要使用到 生命周期:
componentDidMount(挂载) , componentWillUnmount(卸载)
componentDidMount() { // 挂载
this.TimeId=setInterval(()=>{
this.tick()
},1000);// 每秒执行一次
}
componentWillUnmount() { // 卸载
clearInterval(this.timerID); //清除
}
tick() { // 赋值time
this.setState({
time: new Date()
});
}
全部代码:
class Time extends Component{
constructor(props) { //构造函数
super(props);
this.state={time:new Date()}
}
componentDidMount() { // 挂载
this.TimeId=setInterval(()=>{
this.tick()
},1000);// 每秒执行一次
}
componentWillUnmount() { // 卸载
clearInterval(this.timerID); //清除
}
tick() { // 赋值time
this.setState({
time: new Date()
});
}
render(){
return <h3>{this.state.time.toLocaleTimeString()}</h3>
}
}
//App 组件的 return部分
return(
<div className="container">
<Table characterData={ characters }/>
<Time />
</div>
)
对表格行进行操作 也就是上面显示的 Delete按钮的图片
- 首先将样子搭出来 修改下 Table.js 中
header
及body
组件
//TableHeader
<thead>
<tr>
<th>Name</th>
<th>Job</th>
<th>Remove</th> // 添加标题
</tr>
</thead>
// TableBody 添加一个button按钮 触发删除事件 事件由 父组件传递过来
<tr key={i}>
<td>{item.name}</td>
<td>{item.job}</td>
<td>
<button onClick={()=>{props.removeCharacter(i)}}>Delete</button>
</td>
</tr>
// table
<TableBody characterData={characterData} removeCharacter={removeCharacter}/>
tips: 为每个表行添加了一个键索引,有助于识别每个列表项。该onClick函数必须通过一个返回该removeCharacter()方法的函数,否则它将尝试自动运行。
- 现在显示没问题了 开始做数据处理
将characters
存在state里:
state = {
characters:[
{
name: 'Charlie',
job: 'Janitor',
},
{
name: 'Mac',
job: 'Bouncer',
},
{
name: 'Dee',
job: 'Aspring actress',
},
{
name: 'Dennis',
job: 'Bartender',
},
],
}
删除数组项:removeCharacter
App类上创建一个方法:
// 删除 某个数据
removeCharacter = index => {
const { characters } = this.state // 读取当前的数据
this.setState({
characters: characters.filter((character, i) => {
return i !== index // 对数组筛选 并返回符合项
}),
})
}
tips:filter不改变原数组而是创建一个新数组,并且是在JavaScript中修改数组的首选方法。这个特殊的方法是测试一个索引与数组中的所有索引,并返回除了传递的所有索引之外的所有索引
Filter 链接;在App render 时不要忘记 提取数据 const { characters} = this.state
在render(){}
添加。
全部代码 包含之前的
//App.js:
import React,{Component} from 'react';
import Table from './Table';
class Time extends Component{
constructor(props) { //构造函数
super(props);
this.state={time:new Date()}
}
componentDidMount() { // 挂载
this.TimeId=setInterval(()=>{
this.tick()
},1000);// 每秒执行一次
}
componentWillUnmount() { // 卸载
clearInterval(this.timerID); //清除
}
tick() { // 赋值time
this.setState({
time: new Date()
});
}
render(){
return <h3>{this.state.time.toLocaleTimeString()}</h3>
}
}
class App extends Component{
// state
state = {
characters:[
{
name: 'Charlie',
job: 'Janitor',
},
{
name: 'Mac',
job: 'Bouncer',
},
{
name: 'Dee',
job: 'Aspring actress',
},
{
name: 'Dennis',
job: 'Bartender',
},
],
}
// 删除 某个数据
removeCharacter = index => {
const { characters } = this.state
this.setState({
characters: characters.filter((character, i) => {
return i !== index
}),
})
}
render(){
const { characters} = this.state
// const characters = [
// {
// name: 'Charlie',
// job: 'Janitor',
// },
// {
// name: 'Mac',
// job: 'Bouncer',
// },
// {
// name: 'Dee',
// job: 'Aspring actress',
// },
// {
// name: 'Dennis',
// job: 'Bartender',
// },
// ]
return(
<div className="container">
<Table characterData={ characters } removeCharacter={this.removeCharacter} />
<Time />
</div>
)
}
}
export default App
//Table.js
import React, { Component } from 'react'
const TableHeader = () => {
return (
<thead>
<tr>
<th>Name</th>
<th>Job</th>
<th>Remove</th>
</tr>
</thead>
)
}
const TableBody = props=> {
const rows=props.characterData.map((item,i)=>{
return (
<tr key={i}>
<td>{item.name}</td>
<td>{item.job}</td>
<td>
<button onClick={()=>{props.removeCharacter(i)}}>Delete</button>
</td>
</tr>
)
})
return <tbody>{rows}</tbody>
}
// [[1, 2], [3, 4]].map(([a, b]) =>{
// console.log(a)
// console.log(b)
// return a + b
// });
class Table extends Component {
// 类组件必须包含render(),并且return只能返回一个父元素。
render() {
const { characterData , removeCharacter}=this.props
return (
<table>
<TableHeader/>
<TableBody characterData={characterData} removeCharacter={removeCharacter}/>
</table>
)
// 如果return包含在一行中,则不需要括号。
}
}
export default Table
如果中间执行有问题的话 多看看 代码 整理下,不是很难。也可以跟我联系沟通
网友评论