Vue.js实现To do list
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TodoList</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
.completed {
color: #999999;
text-decoration: line-through;
}
</style>
</head>
<body>
<div id="app">
<h2>To do list</h2>
<input type="text" v-model="inputValue">
<button @click="addTolist">添加</button>
<ul>
<li v-for="item of filterList" :key="item.id" :class="{completed:item.completed}"
@click="onCompletedList(item.id)" @dblclick="onDeleteList(item.id)">
{{item.id}} | {{item.text}}
</li>
</ul>
<button @click="onFilterList(1)" :disabled = "filterType === 1">全部</button>
<button @click="onFilterList(2)" :disabled = "filterType === 2">已完成</button>
<button @click="onFilterList(3)" :disabled = "filterType === 3">未完成</button>
</div>
</body>
<script>
new Vue({
el: '#app',
data: {
inputValue: '',
list: [], // 备份数据
filterList: [], // 展示数据
filterType: 1
},
methods: {
// 添加商品
addTolist() {
// 当有输入的内容时, 把输入的内容存储到list中
if (this.inputValue !== '') {
// data存储数据
const data = {
id: Date.now(),
text: this.inputValue,
completed: false
}
// 头部插入
this.list.unshift(data) // 把data添加到备份数据中
this.filterList.unshift(data) // 把data添加到展示数据中
}
this.inputValue = ''
},
// 把事件设置为已完成
onCompletedList(id) {
// 从list中查找符合要求的第一个元素
const index = this.list.findIndex((item) => item.id === id)
this.list[index].completed = true
this.filterList[index].completed = true
},
// 删除选中list
onDeleteList(id) {
const index = this.list.findIndex(item => item.id === id)
this.list.splice(index, 1) // 修改备份数据
this.filterList.splice(index, 1) // 从数组中删除
},
// 事件过滤
onFilterList(type) {
this.filterType = type
// 所有的过滤操作不能改变原数据
// 深拷贝数组
const list = JSON.parse(JSON.stringify(this.list))
switch (type) {
case 1: // 全部的数据
this.filterList = list
break
case 2: // 已完成的数据
this.filterList = list.filter(item => item.completed)
break
case 3: // 未完成的数据
this.filterList = list.filter(item => !item.completed)
break
}
}
}
})
</script>
</html>
Vue-cli组件化实现To do list
- Main.js
// 创建通信总线
// Vue.prototype.bus = new Vue()
- App.vue
<template>
<div id="app">
<!-- <h2 @click="handleClick">hello</h2> -->
<!-- 响应子组件的事件 @子组件定义的事件且组件默认响应自定义事件
使用事件修饰符.native才会触发JS的原生事件-->
<!-- bus method -->
<!-- <t-input
@add = "addToList"
@click.native = "handleClick"
></t-input>
<t-list :list ="list" ></t-list> -->
<t-input
@add = "addToList"
@click.native = "handleClick"
></t-input>
<t-list
:list ="list"
@update="updateList"
@delete="deleteList">
</t-list>
</div>
</template>
<script>
import TInput from './components/Input'
import TList from './components/List'
export default {
name: 'App',
components: {
TInput,
TList
},
data () {
return {
list: [
/* {
id: 1,
text: 'aaa'
},
{
id: 2,
text: 'bbb'
},
{
id: 3,
text: 'ccc'
} */
]
}
},
// 总线机制
/* mounted() {
// console.log(this.bus)
this.bus.$on('completed', id => {
// console.log('app bus:', id)
this.updateList(id)
})
this.bus.$on('delete', id => {
// console.log('app bus:', id)
this.deleteList(id)
})
}, */
methods: {
addToList (res) {
// console.log(res)
this.list.push({
id: Date.now(),
text: res,
completed: false
})
},
updateList (id) {
// console.log('app', id)
// 修改id对应的数据
const task = this.list.find(item => item.id === id)
task.completed = true
},
deleteList (id) {
// 删除id对应的数据
const index = this.list.findIndex(item => item.id === id)
this.list.splice(index, 1)
},
handleClick () {
// alert('123')
}
}
}
</script>
<style>
</style>
- Components/ Input.vue
<template>
<div>
<!-- <h1 @click="$emit('click')">HELLO</h1> -->
<h1>hello</h1>
<input type="text" v-model.trim="inputValue" />
<button @click="handleClick">Add to list</button>
</div>
</template>
<script>
export default {
data () {
return {
inputValue: ''
}
},
methods: {
handleClick () {
if (this.inputValue !== '') {
// console.log(this.inputValue)
// 把this.inputValue传递到父组件
// this.$emit(事件名, 要传递的数据)
this.$emit('add', this.inputValue)
// 清空输入框
this.inputValue = ''
}
}
}
}
</script>
<style scoped>
</style>
- Components/ List.vue
<template>
<ul>
<!-- <list-item
v-for = "item of list"
:key = "item.id"
:item = "item"
@delete = "handleDelete"
></list-item> -->
<list-item
v-for="item of list"
:key="item.id"
:item="item"
@completed="handleCompleted"
@delete="handleDelete"
></list-item>
</ul>
</template>
<script>
import ListItem from './ListItem'
export default {
// 接收属性
// 需要限制属性的类型
// props: ['list'],
props: {
list: {
type: Array,
required: true
// 如果是引用类型, 默认值必须是函数, 然后引用类型
// default(){
// return [1, 2, 3]
// }
}
/* age :{
type: Number,
// 当父组件的传递数据未定义的时候取默认值
default: 20,
// 自定义验证
validator(value){
// 参数value就是父组件传递过来的数据
// console.log('validator', value)
// 必须返回布尔类型
return value >= 0
}
} */
},
components: {
ListItem
},
methods: {
handleCompleted (id) {
// console.log('list', id)
// 通知父组件做修改
this.$emit('update', id)
},
handleDelete (id) {
this.$emit('delete', id)
}
},
// 生命周期
mounted () {
// 使用通过属性传递的数据
console.log(this.list)
}
}
</script>
<style>
</style>
- Components/ ListItem.vue
<template>
<li
@click="handleClick"
:class="{ completed: item.completed }"
@dblclick="handleDblclick"
>
{{ item.text }}
</li>
</template>
<script>
export default {
props: {
item: Object
},
methods: {
handleClick () {
// 把当前的item的complete的值变为true
// 不能在组件中直接修改父组件传递的值
// 通知父组件修改处理
this.$emit('completed', this.item.id)
// console.log(this.bus)
// 通过bus触发了一个事件
// this.bus.$emit('completed', this.item.id)
},
handleDblclick () {
this.$emit('delete', this.item.id)
// 通过bus触发了一个事件
// this.bus.$emit('delete', this.item.id)
}
}
}
</script>
<style>
.completed {
color: #999;
text-decoration: line-through;
}
</style>