图片展示:
功能:添加,删除,按类展示,全选
要点:
1、已勾选的文字画横线效果是根据数据源的done(完成与否)属性,动态绑定class实现的
2、列表展示的是原todos过滤之后的数据,实现删除后就动态显示还存在的数据
3、底部的 All Active Complete 按钮去切换过滤文件的key选择要显示的过滤好的数据,默认就是所有
4、点击文字出现input框通过 v-show控制,绑定鼠标事件把value传出来更改原数据
5、全选实现方式就是把原数据的所有done属性改成true
代码
TodoList组件
<template>
<section class="todoapp">
<!-- 头部区域 -->
<header class="header">
<input class="new-todo" placeholder="请输入一条待办事项" @keyup.enter="addTodo">
</header>
<!-- 中间部分 -->
<section class="main" v-show="todos.length">
<input class="toggle-all" id="toggle-all" type="checkbox" :checked="allChecked" @change="toglleAll({done: !allChecked })">
<!-- 这个是那个小三角 -->
<label for="toggle-all"></label>
<!-- todo子组件主体 -->
<ul class="todo-list">
<todo v-for="(todo,index) in filteredTodos" :key="index" :todo="todo" @toggleTodo="toggleTodo" @editTodo="editTodo" @deleteTodo="deleteTodo"></todo>
</ul>
</section>
<!-- 底部区域 -->
<footer class="footer" v-show="todos.length">
<span>{{remaining}} items left</span>
<ul class="filters">
<li v-for="(val, key) in filters" :key="key">
<a :class="{selected: visibility === key}" @click.prevent="visibility = key">{{key | capitalize}}</a>
</li>
</ul>
</footer>
</section>
</template>
<script>
import Todo from './Todo.vue'
export default {
components: { Todo },
filters: {
capitalize: s => s.charAt(0).toUpperCase() + s.slice(1)
},
name: 'TodoList',
data () {
return {
visibility: 'all',
todos: [
{ text: 'star this repository', done: false },
{ text: 'fork this repository', done: false },
{ text: 'follow author', done: false },
{ text: 'vue-element-admin', done: true },
{ text: 'vue', done: true },
{ text: 'element-ui', done: true },
{ text: 'axios', done: true },
{ text: 'webpack', done: true }
],
filters: {
all: todos => todos,
active: todos => todos.filter(todo => !todo.done),
complete: todos => todos.filter(todo => todo.done)
}
}
},
methods: {
addTodo (e) {
const text = e.target.value
if (text.trim()) {
this.todos.push({ text, done: false })
}
// 为啥要清空,下次再添加value不就已经变了吗
// 是因为这没有用v-model收集的原因吗?
e.target.value = ''
},
toglleAll ({ done }) {
this.todos.forEach(todo => {
todo.done = done
})
},
toggleTodo (todo) {
todo.done = !todo.done
},
deleteTodo (todo) {
this.todos.splice(this.todos.indexOf(todo), 1)
},
editTodo ({ todo, value }) {
todo.text = value
}
},
computed: {
allChecked () {
return this.todos.every(todo => todo.done)
},
remaining () {
return this.todos.filter(todo => !todo.done).length
},
filteredTodos () {
return this.filters[this.visibility](this.todos)
}
}
}
</script>
<style lang="scss">
@import './index.scss';
</style>
Todo组件
<template>
<li :class="{completed:todo.done, editing:editing}" class="todo">
<!-- 可视区域 -->
<div class="view">
<!-- 勾选框 -->
<input type="checkbox" class="toggle" :checked="todo.done" @change="toggleTodo(todo)">
<!-- 待办事项文字 -->
<label v-text="todo.text" @dblclick="editing = true"></label>
<!-- 删除按钮 -->
<button class="destroy" @click="deleteTodo(todo)"></button>
</div>
<!-- 当编辑才能出现的输入框 -->
<input v-show="editing" :value="todo.text" class="edit" @keyup.enter="doneEdit" @keyup.esc="cancelEdit" @blur="doneEdit">
</li>
</template>
<script>
export default {
name: 'Todo',
props: {
todo: {
type: Object,
default: function () {
return {}
}
}
},
data () {
return {
editing: false
}
},
methods: {
toggleTodo (todo) {
this.$emit('toggleTodo', todo)
},
deleteTodo (todo) {
this.$emit('deleteTodo', todo)
},
editTodo ({ todo, value }) {
this.$emit('editTodo', { todo, value })
},
doneEdit (e) {
const value = e.target.value.trim()
const { todo } = this
if (!value) {
this.deleteTodo(todo)
} else if (this.editing) {
this.editTodo({
todo,
value
})
this.editing = false
}
},
cancelEdit (e) {
e.target.value = this.todo.text
this.editing = false
}
}
}
</script>