《React+Redux前端开发实战》—2.5 组件化实战训练——TodoList
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所示。
图2.4 TodoList展示效果
项目源码可在GitHub进行下载 ,地址是https://github.com/khno/react-comonent-todolist 。
- 点赞
- 收藏
- 关注作者
评论(0)