运用了v3+ts 实现 ,
实现的功能:
1. 添加数据
2.删除数据
3.修改状态
4. 全部/未完成/已完成
代码如下:
app.vue
<script setup lang="ts">
import "./styles/base.css"
import "./styles/index.css"
import TodoHeader from "./components/TodoHeader.vue";
import TodoMain from "./components/TodoMain.vue";
import TodoFooter from "./components/TodoFooter.vue";
import { computed, ref, watch } from "vue";
// 给listData 一个初始值
const listData = ref<Array<{ name: string, state:boolean }>>([]);
// 读取本地数据
const storedData = localStorage.getItem('listData');
if (storedData) {
listData.value = JSON.parse(storedData);
}
// 添加本地数据
const addData = () => {
localStorage.setItem('listData',JSON.stringify(listData.value))
}
const change = (name) => {
console.log(name)
listData.value.push({ name: name, state:true })
// 添加本地数据
addData()
}
// 删除数据
const del = (index) => {
console.log(index);
listData.value.splice(index, 1);
// 移除本地存储数据 , 重新保存数据
addData()
console.log(listData.value);
}
// 修改状态
const changeState = (index:number):void => {
listData.value[index].state = !listData.value[index].state;
addData()
}
// 当前显示的状态
const type = ref<string>('all')
const todos = computed(() => {
if (type.value === 'all') {
return listData.value
} else if(type.value === 'yes') {
return listData.value.filter(t => t.state) // filter(a,b) 函数, 返回一个包含b所
} else {
return listData.value.filter(t =>!t.state) // filter(a,b) 函数, 返回a所包
}
})
// 长度
const dataLanght = ref()
dataLanght.value = listData.value.length
// watch 监听 todos 数据的变化 ,修改状态获取剩余个数
watch(todos, (newVal, oldval) => {
console.log(newVal.length)
dataLanght.value = newVal.length
})
// 子组件的绑定事件
const updata = (str:string) => {
console.log(str)
type.value = str
}
</script>
<template>
<section class="todoapp">
<TodoHeader @change="change"></TodoHeader>
<TodoMain @delete="del" :listData="todos" @changeState="changeState" ></TodoMain>
<TodoFooter @updata="updata" :dataLanght="dataLanght"></TodoFooter>
</section>
</template>
TodoHeader.vue
<template>
<header class="header">
<h1>todos</h1>
<input id="toggle-all" class="toggle-all" type="checkbox" >
<label for="toggle-all"></label>
<input
class="new-todo"
placeholder="输入任务名称-回车确认"
autofocus
v-model="name"
@keydown="newTodo"
/>
</header>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const emit = defineEmits(['change'])
const name = ref('')
const newTodo = (e) => {
if(!name.value) return
if (e.key === 'Enter') {
console.log(name.value)
emit('change', name.value)
name.value= ''
}}
</script>
TodoMain.vue
<script setup lang="ts">
const props = defineProps<{
listData
}>()
const emit = defineEmits(['delete','changeState'])
const del = (index) => {
emit('delete',index)
}
// 修改状态
const changeState = (index) => {
emit('changeState',index)
}
</script>
<template>
<ul class="todo-list">
<!-- completed: 完成的类名 -->
<li v-for="(item,index) in props.listData" :key="item" :class="{completed :!item.state} ">
<div class="view">
<input class="toggle" @click="changeState(index)" type="checkbox"/>
<label>{{item.name}}</label>
<button @click="del(index)" class="destroy"></button>
</div>
</li>
</ul>
</template>
TodoFooter.vue
<script setup lang="ts">
import { onMounted } from 'vue';
const props = defineProps<{
dataLanght:number
}>()
const emit = defineEmits<{
(e: 'updata', type:string ) :void
}>()
const getListStore = (type) => {
// console.log(type)
emit('updata',type)
}
</script>
<template>
<footer class="footer">
<span class="todo-count">剩余<strong>{{dataLanght }}</strong></span>
<ul class="filters">
<li>
<a class="selected" href="javascript:;" @click="getListStore('all')">全部</a>
</li>
<li>
<a href="javascript:;" @click="getListStore('no')">未完成</a>
</li>
<li>
<a href="javascript:;" @click="getListStore('yes')">已完成</a>
</li>
</ul>
<button class="clear-completed" >清除已完成</button>
</footer>
</template>