React学习

React学习

最近课好少啊,芜湖起飞~

主要的参考资料:

1.React元素渲染

1.1 从官方模板开始

值得注意的是,react启动之后,直接修改代码然后ctrl+s,页面会重新reload,非常的人性化~

我们从零开始,在刚新建好react项目的中可以看到./public/index.html页面可以看到有个<div id="root"></div>的节点,我们的react组件其实都是渲染在这个里面的。

我们看到./src/index.js,其实就是将一个<App />对象渲染到root节点上,这个<App />对象是在./src/App.js中定义的,通过import导入进来的。

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
// 使用ReactDOM.render方法渲染,将<App />渲染到root节点上
ReactDOM.render(<App />,document.getElementById('root'));
serviceWorker.unregister();
wW4Du4.png

可能会对<App />的样子所迷惑,其实就是一个对象,我们换种方式写可能会更加清楚(下面代码的效果同上)

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
// <App />就是我们的一个组件对象
let app = <App />;
let root = document.getElementById('root');
ReactDOM.render(app ,root);
serviceWorker.unregister();

这样就非常明了,ReactDOM.render()方法其实就是接收两个参数,将组件对象渲染到一个DOM节点上。

1.2 尝试自己编写对象

我们大概知道渲染的工作流程,我们就可以编写自己的对象,然后渲染到节点。这个代码非常简单,直接看~

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
// 定义一个对象,比如这里的一个h1标签,这里没有用"括起来,这是JSX的写法
// JSX是JS的语法扩展,运用于React中
// 值得注意的是这个对象只能有一个根结点
let h1 = <h1>hello world</h1>;
let root = document.getElementById('root');
ReactDOM.render(h1, root);

wWTlin.png

不过有一点值得注意,这样的JS对象只能有一个根结点,也就是说下面这种写法是不允许的!

let h1 = <h1>hello world</h1><h2>yeah</h2>;

所以如果有需要我们一般使用<div>标签括起来:

let h1 = <div><h1>hello world</h1><h2>yeah</h2></div>;

wWTvYn.png

有时候可能对象比较冗长,为了美观,我们用括号括起来,采用下面这种写法:

let h1 = (
  <div>
    <h1>hello world</h1>
    <h2>yeah</h2>
  </div>
);

1.3 写点高级的对象

成天hello world也太枯燥了叭,我们来实现一个时钟吧!

其实也非常的简单,我们只需要使用JS标准对象Date获取之间,然后显示即可,当然为了让时钟能够实时更新,所以我们需要使用到间隔函数setInterval()

上代码:

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
// way1
function clock(){
  let time = new Date().toTimeString();
  // JSX传入参数和JS语法也有一些小区别
  let element = (
  <div>
    <h1>现在时间是:{time}</h1>
  </div>
  )
  let root = document.getElementById('root');
  ReactDOM.render(element, root);
}

setInterval(clock, 1000);   // 间隔函数,实现页面刷新, 1000ms刷新一次

wfCxhV.png

1.4 函数式组件

上面的时钟还有另外一种实现的方式,就是使用函数式组件,就类似于刚开始官方模板中的App那样的对象

值得注意的是,函数式组件首字母要大写,然后就能顺利的使用函数式组件了,使用格式<name para = {}/>,注意不要漏掉了后面的/符号

上代码:

// way2
// 函数式组件,注意函数式组件命名首字母要大写!!
function Clock(para){  // para为传入参数
  return (
    <div>
      <h1>现在时间是:{para.date.toLocaleTimeString()}</h1>
    </div>
  )
}
// 使用函数式组件 <name para = {}/>
function run(){
  ReactDOM.render(
    <Clock date = {new Date()}/>,
    document.getElementById('root')
  )
}
// run()
setInterval(run, 1000);
serviceWorker.unregister();

时钟效果和上文1.3相同

2.JSX

React使用JSX替代常规的Javascript,类似于XML的Javascript扩展,相较于JS他有许多是好处

  • JSX执行更快,在编译成JavaScript代码后进行了优化
  • 更加安全,以为其将变量放在{}中,在渲染时会过滤传入的值,确保不会遭受注入攻击
  • 编写模板也十分简单快速(没vue快吧_

但是也有一些值得注意的地方

  • JSX必须要有根节点
  • 正常的HTML元素要小写,大写会被认为是组件

2.1 jsx表达式{}

2.1.1 放变量

这个比较简单,前面我们也有使用过

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
let name = 'panfeng'		// 放入变量
let h1 = (
  <div>
    <h1>hello {name}</h1>
  </div>
);
let root = document.getElementById('root');
ReactDOM.render(h1, root);
serviceWorker.unregister();

wfmHPJ.png

2.1.2 放表达式

注意只能放入一个表达式

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
let h1 = (
  <div>
    <h1>1+1={1+1}</h1>
  </div>
);
let root = document.getElementById('root');
ReactDOM.render(h1, root);
serviceWorker.unregister();

wfn3Mq.png

2.1.3 放HTML标签
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
// 放入标签
let h1 = (
  <div>
    <h1>你你你你要跳舞吗?</h1>
    <h1>{<button>yes</button>}</h1>
  </div>
);
let root = document.getElementById('root');
ReactDOM.render(h1, root);
serviceWorker.unregister();
2.1.4 放入CSS样式

新建一个css文件:

.beRed{
    background-color: red;
}
.h{
    height: 200px;
}

然后在JS文件中使用

import React from 'react';
import ReactDOM from 'react-dom';
import './panfeng.css';   // 引入样式文件
import App from './App';
import * as serviceWorker from './serviceWorker';
// 放入css样式
let h1 = (
  <div className = {'beRed h'}>
    <h1>你你你你要跳舞吗?</h1>
  </div>
);
let root = document.getElementById('root');
ReactDOM.render(h1, root);
let root = document.getElementById('root');
ReactDOM.render(h1, root);
serviceWorker.unregister();

这样就加入了样式

wf3Uns.png

但是只能注意的是尽量使用className,因为class也是JS的一个关键字

2.1.5 注释

在对象中注释也是需要用{}

let h1 = (
  <div className = {'beRed'}>
    {/*我是注释 */}
    <h1>你你你你要跳舞吗?</h1>
    <img alt = 'baidu' src = 'https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png'></img>
    <h1>{<button>yes</button>}</h1>
  </div>
);

3.React样式

除了使用css样式,我们也可以使用React的样式,但是React样式必须使用驼峰法,比如borderBottom,和css不一致,用起来很不方便T_T,算了吧,还是用css吧~

import React from 'react';
import ReactDOM from 'react-dom';
import './panfeng.css';   // 引入样式文件
import App from './App';
import * as serviceWorker from './serviceWorker';
// 使用react样式
let styleExample1 = {
  background:"blue",
  borderBottom:"4px solid red"
}
let h1 = (
  <div style = {styleExample1}>
    <h1>你你你你要跳舞吗?</h1>
  </div>
);
let root = document.getElementById('root');
ReactDOM.render(h1, root);
serviceWorker.unregister();

4.React组件

4.1 函数式组件

这个我们前面已经使用过了, 函数式组件又被称为静态组件,因为其没有状态或者生命周期可言

我们来看一个嵌套的函数式组件

import React from 'react';
import ReactDOM from 'react-dom';
import './panfeng.css';   // 引入样式文件
//import App from './App';
import * as serviceWorker from './serviceWorker';
// 函数式组件
// 第一个组件
function Dance(para){
  return(
  <h1>Do you want dance {para.name} ?</h1>
  )
}
// 第一个组件放入第二个组件
function Hello(para){
  return(
    <div>
        <h1>Hello {para.name}</h1>
        <Dance name = {para.name}/>
    </div>
  )
}
function run(){
  let root = document.getElementById('root');
  ReactDOM.render(<Hello name = {'panfeng'}/>, root);
}
run();
serviceWorker.unregister();

4.2 类组件

4.2.1 类组件传参

类组件又被称为动态组件,这里我感觉学的还是比较浅,之后再加一些高级的功能吧~这里只是简单的用了一下类组件

值得注意的是,传参后,类组件内使用this.props获取参数

import React from 'react';
import ReactDOM from 'react-dom';
import './panfeng.css';   // 引入样式文件
//import App from './App';
import * as serviceWorker from './serviceWorker';
// 类组件定义
class Hello extends React.Component{
  render(){
    return(
      <div>
        <h1>hello world {this.props.name}</h1>
      </div>
    ) 
  }
}
ReactDOM.render(<Hello name = {'panfeng'}/>, document.getElementById('root'));
serviceWorker.unregister();
4.2.2 类组件状态

温馨提示:想直接看正确操作请跳到最后

样例1 时钟

类组件的状态就类的属性,比如我们仍然希望实现一个时钟页面,我们就能用一个属性来存储时间,然后我们可能就会写出如下代码:

import React from 'react';
import ReactDOM from 'react-dom';
import './panfeng.css';   // 引入样式文件
//import App from './App';
class Clock extends React.Component{
  constructor(props){
    super(props)
    this.state = {    // 类组件state
      time:new Date().toLocaleTimeString()
    }
  }
  render(){
    return(
      <div>
        <h1>当前时间:{this.state.time}</h1>
      </div>
    )
  }
}
ReactDOM.render(<Clock />, document.getElementById('root'))

然而我们会发现我们的时钟并不会动,这也能够理解,因为只渲染了一次嘛,于是我们心中萌生了一个想法,使用setInterval()多次渲染就可以了,恰巧React类中有一个生命周期函数componentDidMount(),会再类组件完成渲染后调用,于是我们又会写出如下的代码:

import React from 'react';
import ReactDOM from 'react-dom';
import './panfeng.css';   // 引入样式文件
//import App from './App';
class Clock extends React.Component{
  constructor(props){
    super(props)
    this.state = {    // 类组件state
      time:new Date().toLocaleTimeString()
    }
  }
  render(){
    return(
      <div>
        <h1>当前时间:{this.state.time}</h1>
      </div>
    )
  }

  // 生命周期函数,再组件完成渲染时调用的函数
  componentDidMount(){
    setInterval(()=>{
      ReactDOM.render(<Clock />, document.getElementById('root'));
    },1000)
  }
}
ReactDOM.render(<Clock />, document.getElementById('root'))

很不巧的是,我们会发现时钟还是没有动起来,这时候我们才醒悟过来,类的属性值可能一直都没有修改,于是我们又会写出如下的代码:

import React from 'react';
import ReactDOM from 'react-dom';
import './panfeng.css';   // 引入样式文件
//import App from './App';
class Clock extends React.Component{
  constructor(props){
    super(props)
    this.state = {    // 类组件state
      time:new Date().toLocaleTimeString()
    }
  }
  render(){
    return(
      <div>
        <h1>当前时间:{this.state.time}</h1>
      </div>
    )
  }

  // 生命周期函数,再组件完成渲染时调用的函数
  componentDidMount(){
    setInterval(()=>{
      this.state.time = new Date().toLocaleTimeString();    // 更新时间
      ReactDOM.render(<Clock />, document.getElementById('root'));
    },1000)
  }
}
ReactDOM.render(<Clock />, document.getElementById('root'))

但是此时系统又温馨的提示我们不要直接修改state,而使用setState()函数

wfaak9.png

于是我们终于修改好了,并且发现此时甚至不需要我们手动重新渲染整个页面了,妙啊~

import React from 'react';
import ReactDOM from 'react-dom';
import './panfeng.css';   // 引入样式文件
//import App from './App';
class Clock extends React.Component{
  constructor(props){
    super(props)
    this.state = {    // 类组件state
      time:new Date().toLocaleTimeString()
    }
  }
  render(){
    return(
      <div>
        <h1>当前时间:{this.state.time}</h1>
      </div>
    )
  }

  // 生命周期函数,再组件完成渲染时调用的函数
  componentDidMount(){
    setInterval(()=>{
      this.setState({
        time:new Date().toLocaleTimeString()     // 更新时间
      })
    },1000)
  }
}
ReactDOM.render(<Clock />, document.getElementById('root'))

并且我们使用setState()时其并不是立马修改DOM中的内容,而是修改虚拟DOM,等setState()执行完后,再对比虚拟DOM和DOM中的内容,再做统一修改,提高效率(不知比之前重新渲染页面效率要高多少~)

样例2 列表切换

列表切换我们就需要做到两个标签的显示于隐藏,我们就能使用类组件中的状态来实现,这里面有许多的细节,但是代码中也是做了比较详细的注释,直接上代码吧

import React from 'react';
import ReactDOM from 'react-dom';
import './panfeng.css';   // 引入样式文件
//import App from './App';
class Clock extends React.Component{
  constructor(props){
    super(props)
    this.state = {    // 类组件state
      c1:'visible',
      c2:'unvisible'
    }
    this.clickEvent = this.clickEvent.bind(this)  // 需要绑定一下!!
  }

  clickEvent(e){
    console.log(e.target.dataset.index)
    let index = e.target.dataset.index;   // 获取点击
    if(index == '1'){   // 判断是哪个按钮点击
      this.setState({
          c1:'visible',
          c2:'unvisible'
        })
    }
    else{
      this.setState({
          c1:'unvisible',
          c2:'visible'
        })
    }
  }
  render(){
    return(
      <div>{/*绑定按钮事件*/}
        <button data-index = '1' onClick = {this.clickEvent}>按钮1</button>
        <button data-index = '2' onClick = {this.clickEvent}>按钮2</button>
        {/*在此处使用状态*/}
        <div className = {this.state.c1}>
          <h1>内容1</h1>
        </div>
        <div className = {this.state.c2}>
          <h1>内容2</h1>
        </div>
      </div>
    )
  }
}
ReactDOM.render(<Clock />, document.getElementById('root'))
4.2.3 类组件父传子

其实就是我们普通的传参方式,将参数传入到子元素,控制子元素的状态(其中状态再父元素中保存)

直接上代码:

import React from 'react';
import ReactDOM from 'react-dom';
import './panfeng.css';
// 创建父元素
class ParentCom extends React.Component{
  constructor(props){
    super(props);
    this.state = {
      isActive:true   // 控制子元素的状态
    }
    this.clickFunc = this.clickFunc.bind(this);   // 绑定
  }
  clickFunc(){
    this.setState({
      isActive: ! this.state.isActive   // 点击函数,每次点击就对子元素的状态求反
    })
  }
  render(){
    return (
    <div>
      <button onClick = {this.clickFunc}>控制子元素显示</button>{/*控制子元素的按钮*/}
      <ChildCom isActive = {this.state.isActive}/>{/*添加子元素*/}
    </div>
    )
  }
}
// 子元素
 class ChildCom extends React.Component{
   constructor(props){
     super(props);
   }
   render(){
     // 获取参数
     let classType = (this.props.isActive == true ? ' active':'');
     return (
       <div className = {'content'+classType}>{/*使用参数*/}
         <h1>我是子元素</h1>
       </div>
     )
   }
 }

 ReactDOM.render(<ParentCom />, document.getElementById('root'));

实现效果,按钮控制元素显示

wIPs81.png

4.2.4 类组件子传父

有时候我们也有需要修改父元素的需要,但是通过参数传入父元素的this.state的值并不能完成修改,但是我们还要其他的方式,可以通过参数传入父元素的函数,然后子元素调用这个父元素的函数就能完成对父元素的修改了,其实思路也是非常简单。

我们用如下一个简单的栗子说明一下吧,做了详细的注释~

import React from 'react';
import ReactDOM from 'react-dom';
import './panfeng.css';
// 创建父元素
class ParentCom extends React.Component{
  constructor(props){
    super(props);
    this.state = {
      str:null    // 待父元素的属性值
    }
  }
  render(){
    return (
      <div>
        <h1>子元素传给父元素一个:{this.state.str}</h1>
        <ChildCom change = {this.changeStr}/>{/*将父元素的函数作为参数传给子元素*/}
      </div>
    )
  }
  // 使用如下的箭头函数写法就不需要写绑定
  changeStr = (data)=>{ // 传入的修改函数,其中设置了参数,用于修改父元素的属性值
    this.setState({
      str:data
    })
  }
}
// 创建子元素
 class ChildCom extends React.Component{
   constructor(props){
     super(props);
   }
   render(){
     return(
       <div>
         <button onClick = {this.clickFunc}>发送给父元素</button>{/*使用这个按钮来调用函数*/}
         <input id = 'inputBox' type = 'text'></input>
       </div>
     )
   }
   clickFunc = ()=>{  // 调用父元素传入的函数
     this.props.change(document.getElementById('inputBox').value);
   }
 }
 ReactDOM.render(<ParentCom />, document.getElementById('root'))

点击按钮就能建文本输入框中的字符串传给父元素了~

wIN52n.png

5.React事件

React事件和html原生事件还要有一些区别的

  1. 绑定事件的命名使用驼峰命名法(小驼峰)
  2. 使用{}传入一个函数,而不是字符串
  3. 事件对象,React返回的事件对象是代理的原生事件对象,如果想要查看事件对象的具体值,必须直接输出事件对象的属性
  4. 代理对象也不能直接通过return flase阻止默认行为,但是能过通过调用函数解决(e.preventDefault())。
  5. 传入参数最好使用箭头函数,匿名函数需要进行绑定this
import React from 'react';
import ReactDOM from 'react-dom';
import './panfeng.css';
class ParentCom extends React.Component{
  constructor(props){
    super(props);
  }
  render(){
    return(
      <div>
        <form action = 'https://www.baidu.com/?tn=40039514_2_oem_dg'>
          <input id = 'inputBox'></input>
          <button onClick = {(e)=>{this.clickFunc(e, document.getElementById('inputBox').value)}}>提交</button>
          {/*匿名函数等价写法,需要绑定 <button onClick = {function(e){this.clickFunc(e, document.getElementById('inputBox').value)}.bind(this)}>提交</button> */}
        </form>
      </div>
    )
  }
  clickFunc = (e, str)=>{
    console.log(str);   // 传入的字符串
    console.log(e);
    e.preventDefault();   // 阻止页面跳转
  }
}
ReactDOM.render(<ParentCom />, document.getElementById('root'))

可以看到返回的事件对象并不能看到事件的具体值

wIBcbq.png

6.React列表渲染

我们可能有需要将一个数组中的内容渲染在页面中,这时候我们可能就需要用到列表渲染了

6.1 弟中弟版本

我们首先试试直接将数组放置在页面中会怎么样?

import React from 'react';
import ReactDOM from 'react-dom';
import './panfeng.css';

let arr = ['Alice','Jack','Bob'];   // 待显示的数组

class Display extends React.Component{
  constructor(props){
    super(props);
  }
  render(){
    return (
      <div>
        <dl>
          {arr}
        </dl>
      </div>
    )
  }
}

ReactDOM.render(<Display></Display>, document.getElementById('root'))

可以看到就是简单粗暴的一个一个展开

wIWVJI.png

显然这不是我们想要的效果,聪明的我们立马就想到了,只需要将数组中的元素变成一个一个的JSX对象不就可以了吗?good idea!

let arr = [<li>Alice</li>,<li>Jack</li>,<li>Bob</li>];   // 待显示的数组

wIWLX8.png

6.2 弟弟版本

如果我们初始的数组内不是一个一个的JSX对象呢?

那没办法,那就一个一个处理吧~

于是就有了下面的弟弟版本

import React from 'react';
import ReactDOM from 'react-dom';
import './panfeng.css';

class Display extends React.Component{
  constructor(props){
    super(props);
    this.state = {
      courseArr : [ // 待显示的数组,类似于JSON格式
        {
          title:'第一节课 计算机组成原理',
          content:'内容:忘记了~'
        },
        {
          title:'第二节课 C语言',
          content:'内容:排序算法的讲解'
        },
        {
          title:'第三节课 数据解构',
          content:'内容:令人头晕的二叉树'
        }
      ]
    }
  }
  render(){
    // 使用map函数生成我们想要的结构
    let showArr = this.state.courseArr.map((item, index)=>{
      return (
        <dt key = {index}>
          <h3>{item.title}</h3>
          <p>{item.content}</p>
        </dt>
      )
    })
    return (
      <div>
        <dl>
          <h1>课程记录</h1>
          {showArr}
        </dl>
      </div>
    )
  }
}

ReactDOM.render(<Display></Display>, document.getElementById('root'))

6.3 函数版本

如果我们需要渲染的是一个静态列表,那么我们完全可以用函数式组件实现,这里实现和6.2一样的效果

import React from 'react';
import ReactDOM from 'react-dom';
import './panfeng.css';
// 定义一个函数式组件来循环渲染我们的内容
function ListDisplay(props){
  return (
    <dt key = {props.index}>
      <h3>{props.item.title}</h3>
      <p>{props.item.content}</p>
    </dt>
  )
}
class Display extends React.Component{
  constructor(props){
    super(props);
    this.state = {
      courseArr : [ // 待显示的数组,类似于JSON格式
        {
          title:'第一节课 计算机组成原理',
          content:'内容:忘记了~'
        },
        {
          title:'第二节课 C语言',
          content:'内容:排序算法的讲解'
        },
        {
          title:'第三节课 数据解构',
          content:'内容:令人头晕的二叉树'
        }
      ]
    }
  }
  render(){
    // 使用map函数生成我们想要的结构
    let showArr = this.state.courseArr.map((item, index)=>{
      return <ListDisplay key = {index} item = {item} index ={index}></ListDisplay>
    })
    return (
      <div>
        <dl>
          <h1>课程记录</h1>
          {showArr}
        </dl>
      </div>
    )
  }
}

ReactDOM.render(<Display></Display>, document.getElementById('root'))

6.4 类版本

有时候我们可能渲染的列表不是一个静态的内容,可能是一个动态的内容,这时我们就可以使用类组件进行渲染

import React from 'react';
import ReactDOM from 'react-dom';
import './panfeng.css';
// 定义一个函数式组件来循环渲染我们的内容
class ListDisplay extends React.Component{
  constructor(props){
    super(props);
  }
  render(){
    return (
      <dt onClick = {()=>{alert('这是第'+String(this.props.index+1)+'节课')}}>
        <h3>{this.props.item.title}</h3>
        <p>{this.props.item.content}</p>
      </dt>
    )
  }
}
class Display extends React.Component{
  constructor(props){
    super(props);
    this.state = {
      courseArr : [ // 待显示的数组,类似于JSON格式
        {
          title:'第一节课 计算机组成原理',
          content:'内容:忘记了~'
        },
        {
          title:'第二节课 C语言',
          content:'内容:排序算法的讲解'
        },
        {
          title:'第三节课 数据解构',
          content:'内容:令人头晕的二叉树'
        }
      ]
    }
  }
  render(){
    // 使用map函数生成我们想要的结构
    let showArr = this.state.courseArr.map((item, index)=>{
      return <ListDisplay key = {index} item = {item} index ={index}></ListDisplay>
    })
    return (
      <div>
        <dl>
          <h1>课程记录</h1>
          {showArr}
        </dl>
      </div>
    )
  }
}

ReactDOM.render(<Display></Display>, document.getElementById('root'))

这样就为做了一个动态的列表(虽然就是一个小弹窗)

wITHUO.png

7. React入门项目:肺炎数据统计

现成的数据可以在这取:

链接:https://pan.baidu.com/s/1s0H7rGYyrJh5YTPEC2dObw
提取码:x6ug

肺炎数据可以从各个统计网页获得,这里就跳过了

然后就直接上代码吧,其实没有用到什么新的东西,就是一个列表渲染,当然可以选择多种渲染方式(函数组件、类组件都是OK的),这个比较简单,直接看代码也比较轻松~

import React from 'react';
import ReactDOM from 'react-dom';
import jsonData from './feiyan3.json'   // 导入肺炎数据

console.log(jsonData);
let province ={}        // 初步用于保存数据的对象
jsonData.data.list.forEach((item, index)=>{     // 提取各个省份的数据
    if(province[item.province] == undefined){   // 如果该省份数据未定义
        province[item.province] = {
            province:item.province,
            confirm:0,
            suspect:0,
            heal:0,
            dead:0
        }
    }
    item.confirm = (item.confirm == null? 0 : item.confirm);    // 如果该数据为null,则置为0
    item.suspect = (item.suspect == null? 0 : item.suspect);
    item.heal = (item.heal == null? 0: item.heal);
    item.dead = (item.dead == null? 0 :item.dead);
    province[item.province] = {
        province:item.province,
        confirm:province[item.province].confirm + item.confirm,
        suspect:province[item.province].suspect + item.suspect,
        heal:province[item.province].heal + item.heal,
        dead:province[item.province].dead + item.dead
    }
})
let provinceList = [];      // 将省份对象数据转化为数组
for(let key in province){
    provinceList.push(province[key]);
}
provinceList.sort((a,b)=>{      // 对省份数据进行排序
    if(a.confirm < b.confirm){
        return 1;
    }
    return -1;
})
console.log(provinceList);
function Feiyan(props){         // 用函数组件显示数据
    //let showArr = []
    let showArr = props.province.map((item, index)=>{       // 列表渲染常规操作
        return(
        <dt key = {index}>
            <h3>{item.province}</h3>
            <p>确诊人数:{item.confirm}   疑症人数:{item.suspect}</p>
            <p>康复人数:{item.heal}   死亡人数:{item.dead}</p> 
        </dt>
        )
    })
    return(
        <div>
            <h1>2020中国肺炎数据</h1>
            {showArr}
        </div>
    )
}
ReactDOM.render(<Feiyan province = {provinceList}></Feiyan>, document.getElementById('root'));

显示的效果:

wqKgoQ.png

8.生命周期

生命周期就是组件从实例化到渲染到最终页面中销毁,整个过程就是生命周期,在这生命周期中,我们有许多可以调用的事件,也俗称为钩子函数

生命周期的3个状态:

  1. Mounting:(挂载状态),将组件插入到DOM中
  2. Updating:(更新),将数据更新到DOM中
  3. Unmounting:(卸载),将组件移出DOM

生命周期的钩子函数:

  • componentWillMount 在渲染前调用
  • componentDidMount : 在第一次渲染后调用
  • componentWillReceiveProps 在组件接收到一个新的 prop (更新后)时被调用。
  • shouldComponentUpdate 返回一个布尔值。在组件接收到新的props或者state时被调用。在初始化时或者使用forceUpdate时不被调用。
    可以在你确认不需要更新组件时使用。
  • componentWillUpdate在组件接收到新的props或者state但还没有render时被调用。在初始化时不会被调用。
  • componentDidUpdate 在组件完成更新后立即调用。在初始化时不会被调用。
  • componentWillUnmount在组件从 DOM 中移除之前立刻被调用。

我们直接看一个简单的例子就能很快了解这些钩子函数

我写了两个组件,通过母组件调用子组件完成了上述钩子函数的演示,代码非常通俗易懂

import React,{Component} from 'react';
import ReactDOM from 'react-dom';

class Comlife extends Component{        // 子组件,用于演示钩子函数
    constructor(props){
        super(props);
        this.state = {
            msg:''
        }
    }
    componentWillMount(){
        console.log('componentWillMount在渲染前调用');
    }
    componentDidMount(){
        console.log('componentDidMount在第一次渲染后调用');
    }
    componentWillReceiveProps(){
        console.log('componentWillReceiveProps在接受到一个新的props时调用');
    }
    componentWillUpdate(){
        console.log('componentWillUpdate在组件更新时调用');
    }
    componentDidUpdate(){
        console.log('componentDidUpdate在组件完成更新后调用');
    }
    componentWillUnmount(){
        console.log('componentWillUnmount在组件从DOM中移除前调用');
    }
    render(props){
        return(
            <div>
                <h1>Hello {this.props.name + this.state.msg}</h1>
                <button onClick = {this.sayHello}>感叹号</button>
            </div>
        )
    }
    sayHello = ()=>{
        this.setState({
            msg:'!'
        })
    }
}
class ParentCom extends Component{      // 母组件,调用子组件,协助完成钩子函数的展示
    constructor(props){
        super(props);
        this.state = {
            showSub:true,
            subStr:'xxx'
        }
    }
    render(){
        if(this.state.showSub){
            return (
                <div>
                    <button onClick = {this.setName}>输入你的姓名</button>
                    <input id = 'inputBox' type = 'text'></input>
                    <Comlife name = {this.state.subStr}></Comlife><br></br>
                    <button onClick = {this.remmove}>给我消失!</button>
                </div>
            )
        }
        else{
            return (
                <h1>消失啦~</h1>
            )
        }
    }
    setName = ()=>{
        this.setState({
            subStr: document.getElementById('inputBox').value
        })
    }
    remmove = ()=>{
        this.setState({
            showSub : false
        })
    }
}
ReactDOM.render(<ParentCom></ParentCom>, document.getElementById('root'));

然后生成的页面就如下图所示,然后依次按照顺序点击,就能够看到钩子函数的调用顺序了

wq69nf.png

如下就是钩子函数的调用情况:

wqyg7F.png

9. 中国肺炎疫情小项目

使用前面入门小项目的数据,然后完成一个较为完整的疫情项目(其实非常的简单),算是最近学习的一个总结(准备跑路~),代码链接

最终项目效果:

09BDlF.png

主要有三个功能组件:

  1. 地图组件:用于显示中国地图以及相关数据

09BoOH.png

  1. 搜索组件:用于搜索相关省份的疫情信息,支持子串搜索

09BOtP.png

  1. 表格组件:将疫情数据按照感染人数排序的一个表格信息

09Bx1S.png

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值