【demo】使用React+Webpackt做一個簡單的todolist
使用React實現一個簡單的todolist,實現基本的增刪功能
GitHub:https://github.com/heyue-99/todolist
建立專案
建立的todo
主要採用node
包的方式,使用webpack
打包
初始化專案並建立一些基礎檔案
初始化專案之後,就需要安裝所需要的庫及其依賴。npm安裝方式可以為開發環境或生產選擇所安裝的依賴。
安裝完所需要的依賴之後,配置webpack。
webpack.config.js:
var path = require("path"); module.exports = { entry: { app: ["./app/app.js"] }, output: { path: path.resolve("./build"), filename: "main.js" }, module: { loaders: [ { test: /\.js$/, exclude: /(node_modules|bower_components)/, use: { loader: 'babel-loader', options: { presets: ['env','react'] } } }, { test: /\.css$/, use: [ 'style-loader', 'css-loader' ] }, { test: /\.less$/, use: [{ loader: "style-loader" // creates style nodes from JS strings }, { loader: "css-loader" // translates CSS into CommonJS }, { loader: "less-loader" // compiles Less to CSS }] } ]} };
執行
webpack-dev-server
啟動webpack伺服器,使用瀏覽器開啟 http://127.0.0.1:8080
就能看見。webpack-dev-server是為了監測前端檔案的變化,以便實時編譯打包前端檔案。
todolist
整體分析
React最大的賣點是輕量元件化。如果要分元件的話,我們大約可以分成一個總元件和兩個子元件。一個輸入內容的元件,一個顯示內容列表(帶刪除功能)的元件,外面再用一個總元件將兩個子元件包括起來。
顯示資料
既然是展示資料,首先要考慮資料儲存在哪裡,來自於哪裡。React提倡所有的資料都是由父元件來管理,通過props的形式傳遞給子元件來處理。
做一個todolist頁面需要一個父元件,兩個子元件。父元件當然就是todolist的總指揮,兩個子元件分別用來add和show、delete。
資料完全由父元件來管理和控制,子元件用來顯示、操作資料,得經過父元件的批准,父元件通過props的形式將資料傳遞給子元件,子元件拿到父元件傳遞過來的資料,再進行展示。
另外,根據React開發的規範,元件內部的資料由state控制,外部對內部傳遞資料時使用 props 。這麼看來,針對父元件來說,要儲存todolist的資料,那就是內部資訊(本身就是自己可控的資源,而不是『領導』控制的資源),用state來儲存即可。而父元件要將todolist資料傳遞給子元件,對子元件來說,那就是傳遞進來的外部資訊(是『領導』的資源,交付給你來處理),需要使用props。
新增資料子元件得到資料後,就需要將新資料新增到todolist的資料中。而todolist的資料是由父元件來管理的,子元件不能說改就改呀,得申請父元件的允許和同意呀。因此,我們需要讓父元件開放一個可以修改資料的介面,然後將這個介面作為props傳遞給子元件,讓其能修改資料。
另外,子元件呼叫父元件的介面對todolist資料進行修改了之後,相當於修改了React物件的state資料,此時就會觸發React的自動更新(就是通過virtual-dom對比,然後更新真實的dom那一套),React會將UI實時隨著資料更新,就不用我們操心了,這也是React比較強大的地方之一。
刪除資料刪除資料和新增資料,邏輯上是一樣的,都是需要父元件提供一個修改資料的介面,通過props形式傳遞給子元件,然後讓子元件來呼叫。
app.js
import React from "react";
import ReactDOM from "react-dom";
//import css from './style.css';
require('./style.css')
//TodoList元件是一個整體的元件,最終React也只渲染這個元件
//TodoList元件是兩個元件的集合
var TodoList = React.createClass({
getInitialState: function(){
return{
todolist:[]
};
},
handleAdd: function(mes){
this.setState({
todolist: mes
});
},
render: function(){
return(
<div>
<h2 className="top">react-todolist</h2>
<TypeNew add={this.handleAdd} todo={this.state.todolist} />
<ListTodo todo={this.state.todolist} del={this.handleAdd} />
</div>
);
}
});
var TypeNew = React.createClass({
addContent: function(e){
e.preventDefault();
var tet = this.refs.content.value.trim();
if(tet!=''){
this.props.todo.push(tet);
this.props.add(this.props.todo);
}
this.refs.content.value='';
},
render: function(){
return(
<form onSubmit={this.addContent} className="form">
<input type="text" ref="content" placeHolder="請輸入您的todolist" className="input" />
<input type="submit" value="新增" className="add" />
</form>
);
}
});
var ListTodo = React.createClass({
delContent: function(e){
var i = e.target.getAttribute("data-index");
this.props.todo.splice(i,1);
this.props.del(this.props.todo);
},
render: function(){
return(
<ul id="todo-list">
{
this.props.todo.map(function(mes,i){
return(
<li className="content">
<label>{mes}</label>
<span className="del" onClick={this.delContent} data-index={i}>×</span>
</li>
);
}.bind(this))
}
</ul>
);
}
});
ReactDOM.render(
<TodoList />,
document.getElementById("example")
);
加上style:
*{
padding: 0;
margin: 0;
}
body{
background-color: #F5A22C;
letter-spacing: 1px;
}
.top{
text-align: center;
margin-bottom: 20px;
font-size: 26px;
}
.form{
width: 430px;
height: 50px;
}
.input{
height:100%;
width: 350px;
border: none;
font-size: 17px;
padding-left: 10px;
color: #8B8383;
}
.add{
height: 100%;
width: 60px;
margin-left: 10px;
background-color: #FB731F;
border: none;
color: white;
font-size: 16px;
}
.add:hover{
cursor: pointer;
}
.content{
width: 420px;
background-color: rgba(255,255,255,.3);
margin-top: 20px;
list-style: none;
border-radius: 10px;
padding-left: 10px;
font-size: 17px;
line-height: 60px;
}
.content .del{
float: right;
padding-right: 10px;
color: #A19898;
}
.del:hover{
cursor: pointer;
}
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="example" style="width: 430px; margin: 100px auto;"></div>
<script type="text/javascript" src="/main.js"></script>
</body>
</html>