《React+Redux前端开发实战》—2.5 组件化实战训练——TodoList

举报
华章计算机 发表于 2019/07/24 23:58:12 2019/07/24
【摘要】 本节书摘来自华章计算机《React+Redux前端开发实战》一书中的第2章,第2.5节,作者是徐顺发.

2.5  组件化实战训练——TodoList

  前面章节中学习了如何配置Webpack来搭建Hello World项目,以及React的组件、组件通信和生命周期等。接下来继续基于前面的这个项目来实现一个简单的TodoList,以此加深读者对组件化的了解。

  在这个简单的TodoList项目中,需要实现:

  •  通过input输入框输入todo内容;

  •  单击Submit按钮将输入的内容展示在页面上。

  在1.5节脚手架中,Webpack的loader只对JS和JSX做了识别,现在需要在项目中加入CSS的相关loader,目的是让Webpack识别和加载样式文件。

  (1)安装CSS的相关loader:

  

  npm install css-loader style-loader --save-dev

  

  (2)配置Webpack中的loader:

  

  var webpack = require("webpack");

  var path = require("path");

  const CleanWebpackPlugin = require("clean-webpack-plugin");

  var BUILD_DIR = path.resolve(__dirname, "dist");

  var APP_DIR = path.resolve(__dirname, "src");

  const HtmlWebpackPlugin = require("html-webpack-plugin");

  var config = {

    entry: APP_DIR + "/index.jsx",

    output: {

      path: BUILD_DIR,

      filename: "bundle.js"

    },

    module: {

      rules: [

        {

          test: /\.(js|jsx)$/,

          exclude: /node_modules/,

          use: {

            loader: "babel-loader"

          }

  },

  {

          test: /\.css$/,                                    // 只加载.css文件

          loader: 'style-loader!css-loader'        // 同时运行两个loader

        }

      ]

    },

    devServer: {

      port: 3000,

      contentBase: "./dist"

    },

    plugins: [

      new HtmlWebpackPlugin({

        template: "index.html",

        // favicon: 'theme/img/favicon.ico',

        inject: true,

        sourceMap: true,

        chunksSortMode: "dependency"

      }),

      new CleanWebpackPlugin(["dist"])

    ]

  };

  module.exports = config;

  

  至此,TodoList的项目脚手架配置结束。

  (3)接下来是相应组件的代码,入口页面App.jsx负责渲染组件头部Header和列表ListItems,并在当前组件内部state维护列表的项目和输入的内容。

  

  export default class App extends Component {

    constructor(props) {

      super(props);

      this.state = {

        todoItem: "",

        items: []

      };

    }

    render() {

      return (

        <div>

        </div>

      );

    }

  }

  

  从上述代码可以看到App组件的state内有todoItem和items。todoItem用于存储输入框输入的值;items用于存储输入框内提交的值,之后用于列表的渲染。

  (4)再来编写输入框输入内容时的onChange事件:

  

  onChange(event) {

      this.setState({

        todoItem: event.target.value

      });

  }

  <input value={this.state.todoItem} onChange={this.onChange} />

  

  从上述代码中可以看到,input的值来自于App组件内的state。用户每次输入后,onChange事件监听其变化,然后调用this.setState()将改变的值实时写入input中展示。

  (5)表单提交:

  

  onSubmit(event) {

      event.preventDefault();

      this.setState({

        todoItem: "",

        items: [

          ...this.state.items,

          this.state.todoItem

        ]

      });

  }

  <form className="form-wrap" onSubmit={this.onSubmit}>

      <input value={this.state.todoItem} onChange={this.onChange} />

  <button>Submit</button>

  </form>

  

  当单击Submit按钮时,输入框的值将通过表单提交的方式触发onSubmit事件,然后调用this.setState()添加输入框中的值到items数组,同时清空输入框。

  (6)将内容整理为3部分:头Header、表单form和列表ListItems。其中,Header和ListItems各为一个组件。

  ./src/Header.js内容如下:

  

  import React from 'react';

  const Header = props => (

    <h1>{props.title}</h1>

  );

  export default Header;

  

  ./src/ListItems.js内容如下:

  

  import React from 'react';

  const ListItems = props => (

    <ul>

      {

        props.items.map(

          (item, index) => <li key={index}>{item}</li>

        )

      }

    </ul>

  );

  export default ListItems;

  

  Header和ListItems都是无状态函数式组件,接收父级./src/app.jsx传入的props数据,用于各自的展示。

  (7)在入口./src/app.jsx 中引入组件:

  

  import React, { Component } from "react";

  import { render } from "react-dom";

  + import ListItems from "./ListItems";

  + import Header from "./Header";

  

  (8)引入样式:

  

  import React, { Component } from "react";

  import { render } from "react-dom";

  import ListItems from "./ListItems";

  import Header from "./Header";

  + import "./index.css";

  

  至此,所有内容完成,此时这个项目的结构如下:

  

  .

  ├── README.md

  ├── index.html

  ├── package-lock.json

  ├── package.json

  ├── src

  │   ├── Header.js

  │   ├── ListItems.js

  │   ├── app.jsx

  │   └── index.css

  └── webpack.config.js

  

  最终入口app.jsx文件的代码如下:

  /src/app.jsx内容如下:

  

  import React, { Component } from "react";

  import { render } from "react-dom";

  import PropTypes from 'prop-types';             // 定义组件属性类型校验

  import "./index.css";

  import ListItems from "./ListItems";

  import Header from "./Header";

  export default class App extends Component {

    constructor(props) {

      super(props);

      this.state = {

        todoItem: "",

        items: ["吃苹果","吃香蕉","喝奶茶"]

      };

     

      this.onChange = this.onChange.bind(this);

      this.onSubmit = this.onSubmit.bind(this);

    }

    // 输入框onChange事件

    onChange(event) {

      this.setState({

        todoItem: event.target.value

      });

    }

    // 表单提交按钮单击事件

    onSubmit(event) {

      event.preventDefault();

      this.setState({

        todoItem: "",

        items: [

          ...this.state.items,

          this.state.todoItem

        ]

      });

    }

    render() {

      return (

        <div className="container">

          <Header title="TodoList"/>

          <form className="form-wrap" onSubmit={this.onSubmit}>

            <input value={this.state.todoItem} onChange={this.onChange} />

            <button>Submit</button>

          </form>

          <ListItems items={this.state.items} />

        </div>

      );

    }

  }

  App.propTypes = {

    items: PropTypes.array,

    todoItem: PropTypes.string,

    onChange: PropTypes.func,

    onSubmit: PropTypes.func

  };

  render(

    <App />,

    document.getElementById("app")

  );

  

  本例最终的展示效果如图2.4所示。

 image.png

图2.4  TodoList展示效果

  项目源码可在GitHub进行下载 ,地址是https://github.com/khno/react-comonent-todolist 。


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。