用派发器做一个TodoList
目录如下
组件书写
toList/index.vue
<template>
<div>
<td-title :title="title"/>
<td-form @dispatch="dispatch"/>
<td-list :data="todoData" @dispatch="dispatch"/>
</div>
</template>
<script>
import TdTitle from './TdTitle.vue';
import TdForm from './TdForm.vue';
import TdList from './TdList.vue';
import dispatch from '@/dispatch/todoList';
export default {
name: "TodoList",
components: {
TdTitle,
TdForm,
TdList
},
data() {
return {
title: "todoList",
todoData: []
}
},
methods: {
dispatch(...args) {
dispatch(this)(...args);
}
}
}
</script>
todoList/TdTitle.vue
<template>
<h1>{{ title }}</h1>
</template>
<script>
export default {
name: "TdTitle",
props: {
title: String
}
}
</script>
todoList/TdForm.vue
<template>
<div>
<form
@submit.prevent="submitText"
>
<input
type="text"
v-model.trim="todoText"
placeholder="请输入"
/>
</form>
</div>
</template>
<script>
export default {
name: 'TdForm',
data() {
return {
todoText: ""
}
},
methods: {
submitText(e) {
if(this.todoText.length === 0) return;
this.$emit('dispatch', 'ADD', {
id: Date.now(),
text: this.todoText,
completed: false,//是否完成了
});
this.$nextTick(() => this.todoText = "")
}
}
}
</script>
todoList/TdList.vue
<template>
<div>
<ul class="todoList">
<list-item v-for="item of data" :key="item.id" :item="item" @handlerItem="handlerItem"/>
</ul>
</div>
</template>
<script>
import ListItem from './ListItem.vue';
export default {
name: 'TdList',
components: {
ListItem
},
props: {
data: Array,
default: () => []
},
methods: {
handlerItem(...args) {
this.$emit('dispatch', ...args);
}
}
}
</script>
todoList/ListItem.vue
<template>
<li>
<input
type="checkbox"
:checked="item.completed ? 'checked' : ''"
@click="handlerItem(COMPLETED, item.id)"
/>
<span :class="{completed: item.completed}">{{ item.text }}</span>
<button @click="handlerItem(REMOVE, item.id)">删除</button>
</li>
</template>
<script>
import {COMPLETED, REMOVE} from '@/actions/todoList';
export default {
name: "ListItem",
props: {
item: Object
},
data() {
return {
REMOVE,
COMPLETED
}
},
methods: {
handlerItem(...args) {
this.$emit('handlerItem', ...args);
}
}
}
</script>
<style>
.completed {
text-decoration: line-through;
}
</style>
书写派发器
actions/todoList.js
const COMPLETED = "COMPLETED";
const REMOVE = "REMOVE";
const ADD = "ADD";
export {
COMPLETED,
REMOVE,
ADD
}
reducers/todoList.js
export default function todoReducer(data) {//todoData
function addItem(newItem) {
return data.concat(newItem);
}
function removeItem(id) {
return data.filter(item => item.id !== id);
}
function changeCompleted(id) {
return data.map(item => {
if(item.id === id) {
item.completed = !item.completed;
}
return item;
})
}
return {
addItem,
removeItem,
changeCompleted
}
}
dispatch/todoList.js
import todoReducer from '@/reducers/todoList';
import { ADD, REMOVE, COMPLETED } from '@/actions/todoList'
export default (ctx) => {
const {
addItem,
removeItem,
changeCompleted
} = todoReducer(ctx.todoData);
return function(type, arg) {
switch(type) {
case ADD:
ctx.todoData = addItem(arg);
break;
case REMOVE:
ctx.todoData = removeItem(arg);
break;
case COMPLETED:
ctx.todoData = changeCompleted(arg);
break;
default:
break;
}
}
}
- 上述代码如下图所示: