前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >「React 手册 」组件生命周期相关函数——componentWillMount

「React 手册 」组件生命周期相关函数——componentWillMount

原创
作者头像
前端达人
修改2020-01-08 14:36:11
4620
修改2020-01-08 14:36:11
举报
文章被收录于专栏:前端达人前端达人

大家好,在前面的几篇文章中,我们已经初步学习了组件的使用方法,但是这些内容只是开始,关于组件的内容还是比较多,比如在组件生命周期内提供了处理数据的方法,在特定的应用场景更新我们的应用,这对我们开发十分重要,因此我们有必要深入学习。在接下来的几篇文章里,我经通过实例的方式和大家一起学习组件生命周期相关的主要方法,本篇文章我们将通过一个待办事项的例子(Todo list)来深入学习如何使用 componentWillMount 函数。

componentWillMount 函数介绍

componentWillMount 函数的触发时机是在组件将要装载,在组件render之前调用。与其相对的是另外一个函数 componentDidMount,在组件加载完成, render之后调用,关于这个函数的介绍,将会在下一篇文章进行介绍。

有一点需要说明的是,componentWillMount 函数将会在未来 v17.0 版本中被移除,在目前最新的 v16.12 版本中还能够使用,但是你会在浏览器控制台里收到如下的信息警告:

「React 手册 」组件生命周期相关函数——componentWillMount
「React 手册 」组件生命周期相关函数——componentWillMount

如何修复以上的错误问题,我们可以使用 UNSAFE_componentWillMount 方法来替代 componentWillMount。虽然在未来的版本中即将废弃,但是不妨碍我们现在使用,还是有必要了解下的。

Todo list 实例

1、首先我们来看看本示例完成后的效果,如下图所示,首先界面初始化一些历史任务信息,我们可以进行更新完成状态同时可以进行删除,输入框用于添加新任务

「React 手册 」组件生命周期相关函数——componentWillMount
「React 手册 」组件生命周期相关函数——componentWillMount

2、接下来基于上篇文章的项目代码,我们在 components 目录创建一个 Todo 的文件夹,然后新建 Todo.js、Todo.css 文件 ,以下为 Todo 组件的基本结构代码:

代码语言:javascript
复制
import React, { Component } from 'react';
import './Todo.css';

class Todo extends Component {
    constructor() {
        super();
    }

    componentWillMount() {

    }

    render() {
        return (
            <div className="Todo">
                <h1>New Task:</h1>
            </div>

        );
    }
}

export default Todo;

// File: src/components/Todo/Todo.js”

3、然后我们在构造函数中初始化本地的数据状态,对于任务列表 Todo list,我们需要定义任务(task)及列表数组(items )

代码语言:javascript
复制
constructor() {
    super();

    // Initial state...
    this.state = {
        task: '',
        items: []
    };
} 

4、接下来我们开始定义 componentWillMount() 方法,这个方法我们在文章的开头提及过了,在组件被渲染之前调用,这个例子,我们在组件 render 之前初始化我们的任务数据,由于在目前的版本使用 componentWillMount() 有警告提示,在未来的17版本中将会被删除,在这里我们使用了 UNSAFE_componentWillMount() 进行了替代,示例代码如下:

代码语言:javascript
复制
UNSAFE_componentWillMount() {
        this.setState({
            items:[
                {
                    id: uuidv4(),
                    task: 'Pay the rent',
                    completed: false
                },
                {
                    id: uuidv4(),
                    task: 'Go to the gym',
                    completed: false
                },
                {
                    id:uuidv4(),
                    task:'Do my homework',
                    completed:false
                }
            ]
        });
    }

5、在上述初始化数据时,我们使用了 uuidv4() 方法,这里我们需要安装相关的第三方依赖包,安装命令如下:

代码语言:javascript
复制
npm install uuid

6、接下来我们在文件的开头引入第三方依赖:

代码语言:javascript
复制
import uuidv4 from 'uuid/v4';

7、定义完默认数据状态后,我们需要定义组件的外观,即 render() 渲染相关的内容——我们的任务列表(Todo list)示例代码如下:

代码语言:javascript
复制
render() {
    return (
        <div className="Todo">
            <h1>New Task:</h1>

            <form onSubmit={this.handleOnSubmit}>
                <input
                    value={this.state.task}
                    onChange={this.handleOnChange}
                />
            </form>

            <List
                items={this.state.items}
                markAsCompleted={this.markAsCompleted}
                removeTask={this.removeTask}
            />
        </div>
    );
}

8、上述的组件 JSX 分为两个部分,第一部分是输入表单,关联我们的数据状态 this.state.task 部分,当用户提交表单时,我们保存新添加的任务,到任务列表数组中。第二部分是调用任务列表组件,我们传递了 items 数组 和 操作任务完成状态方法(markAsCompleted)和 删除任务方法(removeTask)这三个属性。

9、接下来我们来看看 handleOnChange() 方法,这个方法和我们的数据状态task数据关联,示例代码如下:

代码语言:javascript
复制
handleOnChange = e => {
    const { target: { value } } = e;

    // Updating our task state with the input value...
    this.setState({
        task: value
    });
}

10、接着我们来继续定义我们的表单提交方法 handleOnSubmit(), 这个方法主要是将我们新添加的数据保存到任务数组中,示例代码如下:

代码语言:javascript
复制
  handleOnSubmit = e =>{
      e.preventDefault();
      if (this.state.task.trim() !==''){
          this.setState({
              task:'',
              items:[
                  ...this.state.items,
                  {
                      id: uuidv4(),
                      task: this.state.task,
                      complete:false
                  }
              ]
          })
      }
    };

11、markAsCompleted() 方法接收一个任务 ID 标识参数,这个方法用于标识任务已完成,其逻辑主要先查找到对应 ID 的任务,将其更新已完成,然后刷新本地的数据状态,示例代码如下:

代码语言:javascript
复制
   markAsCompleted = id => {
        const  foundTask = this.state.items.find(
            task => task.id === id
        );
        foundTask.completed = true;
        console.log(this.state.items);
        this.setState({
            items:[
                ...this.state.items
            ]
        });
    };

12、接下来我们来定义任务删除方法 removeTask(),这个方法同 markAsCompleted() 一样,接收 ID 参数,用于移除对应任务,示例代码如下:

代码语言:javascript
复制
removeTask = id => {
        const  filteredTasks = this.state.items.filter(
            task => task.id !== id
        );
        this.setState({
           items:filteredTasks
        });
    };

13、这样我们的 Todo 组件就完成了,让我们将代码组合在一起,完整的代码如下:

代码语言:javascript
复制
import React, {Component} from "react";
import './Todo.css'
import  uuidv4 from  'uuid/v4'
import './List'
import List from "./List";

class Todo extends  Component{

    constructor() {
        super();
        this.state={
            task:'',
            items:[]
        };
    }

    handleOnChange = e => {
        const { target: { value } } = e;
        this.setState({
            task: value
        });
    };

    handleOnSubmit = e =>{
      e.preventDefault();
      if (this.state.task.trim() !==''){
          this.setState({
              task:'',
              items:[
                  ...this.state.items,
                  {
                      id: uuidv4(),
                      task: this.state.task,
                      complete:false
                  }
              ]
          })
      }
    };

   markAsCompleted = id => {
        const  foundTask = this.state.items.find(
            task => task.id === id
        );
        foundTask.completed = true;
        console.log(this.state.items);
        this.setState({
            items:[
                ...this.state.items
            ]
        });
    };

    removeTask = id => {
        const  filteredTasks = this.state.items.filter(
            task => task.id !== id
        );
        this.setState({
           items:filteredTasks
        });
    };

    UNSAFE_componentWillMount() {
        this.setState({
            items:[
                {
                    id: uuidv4(),
                    task: 'Pay the rent',
                    completed: false
                },
                {
                    id: uuidv4(),
                    task: 'Go to the gym',
                    completed: false
                },
                {
                    id:uuidv4(),
                    task:'Do my homework',
                    completed:false
                }
            ]
        });
    }

    render() {
        return (
          <div className="Todo">
              <h1>New Task:</h1>
              <form onSubmit={ this.handleOnSubmit }>
                  <input
                      value={ this.state.task }
                      onChange={ this.handleOnChange }
                  />
              </form>

              <List
                  items={this.state.items}
                  markAscompleted={this.markAsCompleted}
                  removeTask={this.removeTask}
              />

          </div>
        );
    }
}

export  default Todo;

// File: src/components/Todo/Todo.js

14、然后我们来完成我们的列表展示组件,我们在 todo 目录下创建 List.js 文件,示例代码如下,代码比较简单,这里就不过介绍了。

代码语言:javascript
复制
import React from "react";

const  List =  props => (
    <ul>
        {props.items.map( (item,key) => (
         <li
             key={ key }
             className={`${item.completed ? 'completed' : 'pending'}`}
         >
             { item.task }
             <div className="actions">
                 <span
                     className={item.completed ? 'hide' : 'done' }
                     onClick={ () => props.markAscompleted(item.id)}
                 >
                  <i className="fa fa-check"></i>
                 </span>
                 <span
                     className="trash"
                     onClick={ ()=>props.removeTask(item.id) }
                 >
                     <i className="fa fa-trash"></i>
                 </span>
             </div>
         </li>
        ))}
    </ul>
);

export  default  List;

// File: src/components/Todo/List.js

15、在我们调用 map 函数渲染列表时,别忘记 key 这个属性加入到列表元素上,否则浏览器控制台将会收到如下的警告:

16、你可能注意到,在我们的界面中,我们引入了一些 Font Awesome 图标,我们需要在我们 index.html 文件引入图标的 CSS 文件,部分示例代码如下:

代码语言:javascript
复制
<head>
    <title>React App</title>
    <link
        href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"
        rel="stylesheet"
    />
</head>

/* File: public/index.html */

17、最后我们来定义我们的组件样式,代码部分如下:

代码语言:javascript
复制
.Todo {
    background-color: #f5f5f5;
    border-radius: 4px;
    border: 1px solid #e3e3e3;
    box-shadow: inset 0 1px 1px rgba(0,0,0,.05);
    margin-bottom: 20px;
    margin: 50px auto;
    min-height: 20px;
    padding: 19px;
    text-align: left;
    width: 70%;
}

.Todo ul {
    margin: 20px 0px;
    padding: 0;
    list-style: none;
}

.Todo ul li {
    background-color: #fff;
    border: 1px solid #ddd;
    display: flex;
    justify-content: space-between;
    margin-bottom: -1px;
    padding: 10px 15px;
    position: relative;
}

.Todo ul li .hide {
    border: 1px solid red;
    visibility: hidden;
}

.Todo ul li.completed {
    background-color: #dff0d8;
}

.Todo ul li .actions {
    display: flex;
    justify-content: space-between;
    width: 40px;
}

.Todo ul li span {
    cursor: pointer;
}

.Todo ul li .done {
    color: #79c41d;
    display: block;
}

.Todo ul li .trash {
    color: #c41d1d;
    display: block;
}

.Todo form input {
    background-color: #fff;
    border-radius: 4px;
    border: 1px solid #ccc;
    box-shadow: inset 0 1px 1px rgba(0,0,0,.075);
    color: #555;
    font-size: 14px;
    height: 34px;
    line-height: 34px;
    padding: 6px 12px;
    width: 40%;
}

.Todo form button {
    background: #2ba6cb;
    border: 1px solid #1e728c;
    box-shadow: 0 1px 0 rgba(255, 255, 255, 0.5) inset;
    color: white;
    cursor: pointer;
    display: block;
    font-size: 14px;
    font-weight: bold;
    line-height: 1;
    margin: 20px auto;
    padding: 10px 20px 11px;
    position: relative;
    text-align: center;
    text-decoration: none;
}

/* File: src/components/Todo/Todo.css */

18、还有最后一步,我们别忘记修改我们的 App 组件,否则我们 Todo 核心组件将无法渲染,完成后代码如下:

代码语言:javascript
复制
import React from 'react';
import './App.css';
// 引入布局相关的组件
import Header from "../shared/components/Header/Header";
import Content from "../shared/components/Content/Content";
import Footer from "../shared/components/Footer/Footer";

import Todo from "./Todo/Todo";


function App() {
  return (
    <div className="App">
     <Header title="Todo List"/>
        <Content>
            <Todo/>
        </Content>
      <Footer/>
    </div>
  );
}

export default App;

// File: src/components/App.js

19、如果你按照上述顺序正确完成后,接下来在控制台输入 npm run start 命令, 你将会看到如下界面:

  • 数据首次加载初始化的界面:
「React 手册 」组件生命周期相关函数——componentWillMount
「React 手册 」组件生命周期相关函数——componentWillMount
  • 然后我们在输入框输入新的任务信息
「React 手册 」组件生命周期相关函数——componentWillMount
「React 手册 」组件生命周期相关函数——componentWillMount
  • 按下回车键后,你将会看到完成后的添加信息
「React 手册 」组件生命周期相关函数——componentWillMount
「React 手册 」组件生命周期相关函数——componentWillMount
  • 点击对应对号图标,标记对应的任务已完成
「React 手册 」组件生命周期相关函数——componentWillMount
「React 手册 」组件生命周期相关函数——componentWillMount
  • 点击垃圾箱图标,删除对应的任务
「React 手册 」组件生命周期相关函数——componentWillMount
「React 手册 」组件生命周期相关函数——componentWillMount

小节

本节的内容就给大家介绍到这里,想必大家通过这个练习已经熟悉了 componentWillMount 函数的用法,在下一篇文章里我们继续通过做实例的形式,学习另外一个与其对应的方法 componentDidMount(),敬请期待...

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • componentWillMount 函数介绍
  • Todo list 实例
  • 小节
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档