之前做好的todoList程序几乎没有使用什么css,都是原生的html样式,看起来有点low,接下来使用element ui来给他装个皮肤
(在线体验)
效果图
修改后的代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue Todo</title>
<style>
body {
margin: 0;
padding: 0;
}
.completed {
text-decoration: line-through;
color: gray
}
.selected {
color: lightseagreen;
}
.empty {
border-color: red;
}
.editTodo {
font-size: 18px;
width: 80%;
}
</style>
<!-- 引入样式 -->
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
<!-- import Vue before Element -->
<script src="https://unpkg.com/vue/dist/vue.js"></script>
<!-- import JavaScript -->
<script src="https://unpkg.com/element-ui/lib/index.js"></script>
</head>
<body>
<div id="todo-app">
<el-row :gutter="20">
<el-col :span="16" :offset="4">
<div class="grid-content bg-purple">
<el-container style="min-width: 500px;margin: 0 auto;">
<el-header>
<div style="margin-top: 20px;">
<!-- <input type="button" v-if="onGoingTodosCount" @click="markAllAsCompleted" value="全部标为完成" /> -->
<!-- <input type="text" :class="{empty:emptyChecked}" placeholder="添加 todo" / v-model="newTodoTitle"
@keyup.enter="addTodo"> -->
<el-input placeholder="添加 todo" v-model="newTodoTitle" @keyup.enter.native="addTodo"
minlength=1 clearable>
</el-input>
<span v-if="emptyChecked" style="color: #FF0000;">请输入内容!</span>
</div>
</el-header>
<el-main>
<!-- todo list -->
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>代办清单:</span>
<el-button style="float: right; padding: 3px 0" type="text" size="mini"
v-if="onGoingTodosCount" @click="markAllAsCompleted">全部标为完成</el-button>
</div>
<div v-for='todo in filteredTodo' :key='todo.id' class="text item">
<el-card shadow="hover">
<el-tooltip v-if="editedTodo && editedTodo.id === todo.id" class="item"
effect="dark" content="按Enter确认,点击其他区域或按Esc取消编辑" placement="top">
<input type="text" value="编辑 todo..." class="editTodo"
v-model="todo.title" v-focus=1 @keyup.enter="editDone(todo)"
@keyup.esc="editCancle(todo)" @blur="editCancle(todo)" />
</el-tooltip>
<span :class="{completed: todo.completed}" v-else @dblclick="editTodo(todo)"
style="font-size: 20px;max-width: 80%;display: inline-block;">{{ todo.title
}}</span>
<!-- <input type="button" value="标记已完成" v-if="!todo.completed" @click="markAsCompleted (todo)" />
<input type="button" value="标记未完成" v-else @click="markAsCompleted (todo)" />
<input type="button" value="删除" @click="removeTodo(todo)">
-->
<div class='controlButtons' style="float: right;">
<el-tooltip class="item" effect="dark" content="编辑" placement="top">
<el-button type="primary" size="mini" icon="el-icon-edit" circle
@click="editTodo(todo)"></el-button>
</el-tooltip>
<el-tooltip v-if="!todo.completed" class="item" effect="dark"
content="标记完成" placement="top">
<el-button size="mini" type="success" icon="el-icon-check" circle
@click="markAsCompleted (todo)" style="margin: 0 5px;">
</el-button>
</el-tooltip>
<el-tooltip v-else class="item" effect="dark" content="标记未完成"
placement="top">
<el-button size="mini" @click="markAsCompleted (todo)" type="info"
icon="el-icon-close" circle style="margin: 0 5px;"></el-button>
</el-tooltip>
<el-tooltip class="item" effect="dark" content="删除" placement="top">
<el-popconfirm title="确定删除吗?" @Confirm="removeTodo(todo)">
<el-button size="mini" type="danger" circle
icon="el-icon-delete" slot="reference"></el-button>
</el-popconfirm>
</el-tooltip>
</div>
</el-card>
</div>
</el-card>
<!-- end todo list -->
</el-main>
<el-footer>
<div>
<span v-if="onGoingTodosCount">剩余 {{onGoingTodosCount}} 项未完成 ---</span>
<span v-else>无未完成代办事项</span>
<span>筛选:
<!-- <input type="button" :class="{selected:intention=='all'}" value="全部" @click="intention='all'"> -->
<el-button size="mini" :type="buttonType(intention)[0]"
@click="intention='all'">全部
</el-button>
<!-- <input type="button" :class="{selected:intention=='ongoing'}" value="进行中"
@click="intention='ongoing'"> -->
<el-button size="mini" :type="buttonType(intention)[1]"
@click="intention='ongoing'">进行中
</el-button>
<!-- <input type="button" :class="{selected:intention=='finished'}" value="已完成"
@click="intention='finished'"> -->
<el-button size="mini" :type="buttonType(intention)[2]"
@click="intention='finished'">已完成
</el-button>
<!-- <input type="button" v-if="onGoingTodosCount" value="清除已完成" @click="clearCompleted">
<input type="button" v-if="hasTodo" value="清除全部" @click="clearAll"> -->
<el-button size="mini" v-if="onGoingTodosCount" @click="clearCompleted">清除已完成
</el-button>
<el-button size="mini" v-if="hasTodo" @click="clearAll">清除全部</el-button>
</span>
</div>
<!-- <div>
<el-button @click="visible = true">Button</el-button>
<el-dialog :visible.sync="visible" title="Hello world">
<p>Try Element</p>
</el-dialog>
</div> -->
</el-footer>
</el-container>
</div>
</el-col>
</el-row>
</div>
<!-- <script src="https://cdn.bootcss.com/vue/2.5.16/vue.js"></script> -->
<script type="text/javascript">
let id = 0;
var STORAGE_KEY = 'vue2.x-todo-tutorial';
var todoStorage = {
fetch: function() {
var todos = JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]');
todos.forEach(function(todo, index) {
todo.id = index
});
todoStorage.uid = todos.length;
return todos
},
save: function(todos) {
localStorage.setItem(STORAGE_KEY, JSON.stringify(todos))
}
};
var app = new Vue({
el: '#todo-app',
data: function() {
return {
todoList: todoStorage.fetch(),
newTodoTitle: '',
checkEmpty: false,
removedTodo: [],
editedTodo: null, // 用于暂存编辑前的 todo 状态
intention: 'all',
visible: false,
buttonType: function(val) {
if (val == 'finished') {
return ['', '', 'primary']
} else if (val == 'ongoing') {
return ['', 'primary', '']
} else {
return ['primary', '', '']
}
}
}
},
methods: {
addTodo() {
if (this.newTodoTitle.length) {
this.todoList.push({
id: todoStorage.uid++,
title: this.newTodoTitle,
completed: false,
markButtonText: "标为完成",
});
this.newTodoTitle = ''
this.checkEmpty = false;
} else {
this.checkEmpty = true
}
},
markAsCompleted(todo) {
todo.completed = !todo.completed;
},
removeTodo(todo) {
let pos = this.todoList.indexOf(todo)
this.removedTodo.push({
pos: pos,
title: this.todoList.splice(pos, 1)[0]
})
},
restoreTodo() {
let todo = this.removedTodo.pop()
this.todoList.splice(todo.pos, 0, todo.title)
},
editTodo(todo) {
this.editedTodo = {
id: todo.id,
title: todo.title,
completed: todo.completed,
markButtonText: todo.markButtonText
}
},
editDone(todo) {
if (!todo.title) {
todo.title = this.editedTodo.title
this.removeTodo(todo)
}
this.editedTodo = null
},
editCancle(todo) {
todo.title = this.editedTodo.title
this.editedTodo = null
},
markAllAsCompleted() {
this.todoList.map(function(todo) {
todo.completed = true
})
},
clearAll() {
// if (!confirm('确认删除?')) {
// return
// }
this.$confirm('确认要删除代所有待办事项吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$message({
type: 'success',
message: '删除成功!'
});
this.todoList = []
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
},
clearCompleted() {
this.$confirm('确认要删除代已完成的事项吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$message({
type: 'success',
message: '删除成功!'
});
this.todoList = this.todoList.filter(todo => !todo.completed)
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
}
},
computed: {
emptyChecked() {
return !this.newTodoTitle.length && this.checkEmpty
},
hasRemovedTodo() {
return this.removedTodo.length
},
onGoingTodos() {
return this.todoList.filter(todo => !todo.completed)
},
onGoingTodosCount() {
return this.todoList.filter(todo => !todo.completed).length
},
filteredTodo() {
if (this.intention === 'ongoing') {
return this.onGoingTodos
} else if (this.intention === 'finished') {
return this.todoList.filter(todo => todo.completed)
} else {
return this.todoList
}
},
hasTodo() {
return this.todoList.length
},
},
directives: {
focus: {
inserted: function(el) {
el.focus()
}
},
},
watch: {
todoList: {
handler: function(todoList) {
todoStorage.save(todoList)
},
deep: true
}
},
})
</script>
</body>
</html>
注意点
注释掉的基本上是之前的代码,可以做一个对比。
删除单条数据的时候,本来写了一个弹框确定删除的函数,但是发现有更方便的办法,可以直接用<el-popconfirm></el-popconfirm>
这个标签来实现。有一个要注意的地方就是用了这个以后,button上原本绑定的click事件好像就失效了,可以改成在这个标签内使用@Confirm="removeTodo(todo)"
来代替。也有说要用@onConfirm
的,我试了好像不行。
还有就是input
标签里面绑定的@keyup.enter
事件要改成@keyup.enter.native
才行
疑问
最下面那一排筛选的按钮,本来是点击之后会增加一个.selected
的样式,代码是:class="{selected:intention=='all'} @click="intention='all'"
,用el-button之后想要动态的改变type样式,好像无法使用这种方式,最后只好用了一个数组来存放每个按钮的状态,感觉有点low,不知道有没有更好的办法。
存储的部分直接抄了教程的代码,没有搞的太明白,之后再研究研究。