1.index.js
import dva from 'dva';
const app=dva();
app.model(require('./models/todos').default);
app.router(require('./router').default)
app.start('#root');
2.Models/todos.js
let currentId=2;
export default{
namespace:'todos',
state:[
{id:1,text:'hello',completed:true},
{id:2,text:'heelo',completed:false}
],
reducers:{
del(state,{payload:{ id }}){
return state.filter((item)=>item.id!==id);
},
add(state,{payload:{text}}){
return [...state,{id: ++currentId,text,completed:false}];
},
complete(state,{payload:{id}}){
return state.map((item)=>(item.id===id)?{...item,completed:!item.completed}:item)
}
}
}
3.routes/Todos.jsx
import {connect} from 'dva';
import TodoListItem from '../components/TodoListItem';
import AddTodo from '../components/Addtodo';
const Todos=({todos,delTodo,completeTodo,addTodo})=>{
return(
<div>
<h1>TodoList</h1>
<div>
{
todos.map((todo)=>{
return <TodoListItem key={todo.id} todo={todo} delTodo={delTodo} completeTodo={completeTodo}/>;
})
}
</div>
<AddTodo addTodo={addTodo} />
</div>
)
}
export default connect(({todos})=>({todos}),
(dispatch)=>({
delTodo(id){
dispatch({
type:'todos/del',
payload:{
id
}
})
},
addTodo({text}){
dispatch({
type:'todos/add',
payload:{
text
}
})
},
completeTodo(id){
dispatch({
type:'todos/complete',
payload:{
id
}
})
}
}))(Todos);
4.components/AddTodo.jsx
import PropTypes from 'prop-types';
import {useState} from 'react';
const Addtodo=({addTodo})=>{
const [value,setValue]=useState('');
const onClick=(e)=>{
e.preventDefault();
if(!value) return;
addTodo({text:value});
setValue('');
}
return(
<div>
<input type="text" value={value} onChange={(e)=>setValue(e.target.value)}/>
<button onClick={onClick}>添加</button>
</div>
)
}
Addtodo.PropTypes={
addTodo:PropTypes.func.isRequired
}
export default Addtodo;
5.components/TodoListItem.jsx
import PropTypes from 'prop-types';
const TodoListItem=({todo,delTodo,completeTodo})=>{
return(
<ul>
<li style={{textDecoration:todo.completed?'line-through':''}}>{todo.text}
<button onClick={()=>delTodo(todo.id)}>刪除</button>
<button onClick={()=>completeTodo(todo.id)}>完成</button>
</li>
</ul>
)
}
TodoListItem.PropTypes={
todo:PropTypes.object.isRequired,
completeTodo:PropTypes.func.isRequired,
delTodo:PropTypes.func.isRequired
}
export default TodoListItem;
6.router.jsx
import Todos from './routes/Todos';
import {Route,Router,Switch} from 'dva/router';
function RouterConfig({ history }) {
return (
<Router history={history}>
<Switch>
<Route path="/" exact component={Todos} />
</Switch>
</Router>
);
}
export default RouterConfig;
效果图