Vue实现Todo List
@[TOC](基于Vue实现的Todo List)
实现效果
完成功能
- Vue 的基础案例
- Vue 的组件
- Vue 父组件向子组件传值
- Vue 子组件向父组件传值
- Vue 的动态样式绑定
- Layui 的弹窗实践
代码
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>Todo List</title>
<link rel="stylesheet" href="https://www.layuicdn.com/layui/css/layui.css">
<style>
ul li {
list-style: circle !important;
}
.finished {
text-decoration: line-through;
}
</style>
</head>
<body>
<div id="todoApp" style="margin:1.5% 2% 0 2%">
<hr>
<div class="layui-progress layui-progress-big" lay-showpercent="true" lay-filter="schedule">
<div class="layui-progress-bar" lay-percent="100%"></div>
</div>
<hr>
<div class="layui-form-item">
<div class="layui-input-inline">
<input type="text" name="input" autocomplete="off" class="layui-input" v-model="todoValue">
</div>
<button style="float: left;" type="button" class="layui-btn layui-btn-radius layui-btn-normal"
v-on:click="addItem">提交
</button>
<button style="float: left;" type="button" class="layui-btn layui-btn-radius layui-btn-normal" disabled
v-on:click="finish">完成一件
</button>
</div>
<div>
<ul>
<!-- <li v-for="item in todoList">{{item}}</li>-->
<my-todo-item v-for="(item,index) in todoList"
v-bind:item="item"
v-bind:index="index"
v-on:finish="finishItemHandler">
</my-todo-item>
</ul>
</div>
</div>
</body>
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://www.layuicdn.com/layui/layui.js"></script>
<script type="text/javascript">
let $, element, layer;
layui.use(['element', 'layer', 'jquery'], function () {
$ = layui.jquery;
layer = layui.layer;
element = layui.element; //Tab的切换功能,切换事件监听等,需要依赖element模块
});
Vue.component('my-todo-item', {
template: "<li style='margin-left: 1rem;;margin-top: 1rem;' v-bind:class='{finished: item.finish}'>" +
"{{ item.value }} " +
"<button v-on:click='finishItem' style='margin-left: 1rem' type='button' class='layui-btn layui-btn-radius layui-btn-normal'>{{item.finish ? '取消完成':'完成'}}" +
"</button></li>",
props: ['item', "index"],
methods: {
finishItem: function () {
this.$emit("finish", this.index);
}
}
});
let todoApp = new Vue({
el: "#todoApp",
data: {
todoValue: "",
todoList: [],
index: 0,
accomplish: 0
},
methods: {
addItem: function () {
if (this.todoValue.length !== 0) {
const item = {
id: this.index++,
value: this.todoValue,
finish: false
};
this.todoList.push(item);
// 清空输入框
this.todoValue = "";
// 重新计算进度条
this.calcSchedule();
} else {
layer.msg('输入能容为空。。。', {icon: 5});
}
},
finish: function () {
if (this.accomplish < this.todoList.length) {
this.accomplish++;
this.calcSchedule();
}
},
calcSchedule: function () {
// 重新计算进度条
const schedule = this.accomplish / this.todoList.length * 100;
//设置进度
element.progress('schedule', schedule.toFixed(2) + '%');
},
finishItemHandler: function (index) {
this.todoList[index].finish = !this.todoList[index].finish;
if (this.todoList[index].finish) {
this.accomplish++;
} else {
this.accomplish--;
}
this.calcSchedule();
}
}
});
</script>
</html>
传值解读
此处todoApp
可看做是父组件,my-todo-item
是子组件
todoApp
通过my-todo-item
中的 props 将需要的值传递到my-todo-item
中
my-todo-item
中button按钮触发的finishItem
事件向父组件发布了一个finish
事件,并携带了 index 这个参数,而父组件使用v-on
指令,监听了组件的finish
事件并将该事件交由finishItemHandler
函数处理
评论区