自定義文件夾和文件名稱,咱們用它來裝咱們今天的項目css
npm init -y // 初始化項目html
npm i -S underscore vue todomvc-app-css //下載這三個文件,由於咱們後期要用到vue
如圖這樣node
在index.html裏邊輸入Vue的基本樣式和引入css、html:npm
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <link rel="stylesheet" href="./node_modules/todomvc-app-css/index.css"> </head> <body> <section class="todoapp"> <header class="header"> <h1>todos</h1> <input class="new-todo" placeholder="What needs to be done?" autofocus="" > </header> <section class="main" v-show="showList"> <input class="toggle-all" id="toggle-all" type="checkbox"> <label for="toggle-all">Mark all as complete</label> <ul class="todo-list"> <li> <div class="view"> <input class="toggle" type="checkbox" > <label></label> <button class="destroy" ></button> </div> <input class="edit"> </li> </ul> </section> <footer class="footer" v-show="showList"> <span class="todo-count"> <strong></strong></span> <ul class="filters"> <li> <a class="selected" href="#/">All</a> </li> <li> <a href="#/active" >Active</a> </li> <li> <a href="#/completed" >Completed</a> </li> </ul> <button class="clear-completed" >Clear completed</button> </footer> </section> <script src="./../../vue.js"></script> <script> var app = new Vue({ el:".todoapp", data:{ } }) </script> </body> </html>
data:{ todoList:[ { text:"Vue很難", //這個是任務的名稱 checkbox:false // checkbox的false表示未完成,true表示已完成 }, { text:"不難,只要用心", checkbox:false } ] }
<li v-for="(todo,index) in todoList"> <div class="view"> <input class="toggle" type="checkbox"> <label>{{todo.text}}</label> <button class="destroy"></button> </div> <input class="edit"> </li>
<li v-for="(todo,index) in todoList" :class="{completed: todo.checked}">
<input class="toggle" type="checkbox" v-model="todo.checked"/>數組
這樣咱們就能夠看到點擊複選框的效果了。mvc
data: { newTodo:"", todoList: [{ text: "Vue很難", //這個是任務的名稱 checked: false // checkbox的false表示未完成,true表示已完成 }, { text: "不難,只要用心", checked: false } ] }
<input class="new-todo" placeholder="你接下來須要完成什麼?" autofocus="" v-model="newTodo" @keyup.enter.trim="addTodo" />
methods: { addTodo() { this.newTodo = this.newTodo.trim(); //這句是去除空格 // 判斷輸入內容是否爲空,爲空不提交 if (this.newTodo.length < 1) { return; } //把新數據添加到數組當中,默認爲未完成 this.todoList.unshift({ text: this.newTodo, checked:false }) this.newTodo = "" } }
<button class="destroy" @click="deleteTodo(todo)"></button> <script src="./node_modules/underscore/underscore-min.js" charset="utf-8"></script>
deleteTodo(todo){app
this.todoList = _.without(this.todoList, todo)
}dom
computed:{ showList(){ return this.todoList.length > 0 } }
<footer class="footer" v-show="showList">
<input class="edit" type = "text" v-model = "todo.text">fetch
editingIndex: -1
<label @dblclick="editTodo(index)">{{ todo.text }}</label>
editTodo(index) {
// 設置一下當前正在編輯的索引 this.editingIndex = index;
}
<li:class="{completed: todo.checked, editing: index === editingIndex}"
v-for="(todo,index) in todoList">
// 註冊一個全局自定義指令 v-focus
Vue.directive('focus', {
// 當綁定元素插入到 DOM 中。
inserted(el) {
// 聚焦元素 el.focus()
},
// 當綁定元素更新的時候
update(el) {
el.focus();
}
})
<input class="edit" type="text" v-model="todo.text" v-focus="index === editingIndex" @blur="saveTodo(todo)" @keyup.enter="saveTodo(todo)"/>
saveTodo(todo) {
this.editingIndex = -1 if (todo.text.trim().length < 1) { this.deleteTodo(todo) }
}
activeCount() {
return this.todoList.filter(item => { return !item.checked }).length;
}
<span class="todo-count">
<strong>{{activeCount}}</strong>
</span>
在store.js中填寫
var STORAGE_KEY = 'todoList'
window.todoStorage = {
fetch() { try { return JSON.parse(localStorage.getItem(STORAGE_KEY) || '[]'); } catch(error) { return []; } }, save(todoList) { localStorage.setItem(STORAGE_KEY, JSON.stringify(todoList)); }
}
在data裏添加
todoList: todoStorage.fetch()
watch: {
todoList: {
deep: true, handler: todoStorage.save
}
}
// 是否全部任務都完成
allDone: {
get() { // 未完成的數量爲0表示所有完成,所有完成返回true return this.activeCount === 0; }, set(value) { this.todoList.forEach(todo => { todo.checked = value }); }
}
<input class="toggle-all" id="toggle-all" type="checkbox" v-model="allDone" />
var filters = {
all: function (todos) {
return todos;
},
active: function (todos) {
return todos.filter(function (todo) { return !todo.checked; });
},
completed: function (todos) {
return todos.filter(function (todo) { return todo.checked; });
}
};
visibility: 'all'
computed: {
...
// 未完成的任務數量
activeCount() {
return filters.active(this.todoList).length;
},
}
computed: {
...
// 過濾任務列表
filteredTodoList: function () {
return filters[this.visibility](this.todoList);
}
}
<li><a:class="{selected:visibility==='all'}"href="#/"@click="visibility='all'">all
</li>
<li>
<a
:class="{selected: visibility === 'active'}"
href="#/active"
@click="visibility = 'active'"
active
</li>
<li>
<a
:class="{selected: visibility === 'completed'}"
href="#/completed"
@click="visibility = 'completed'">completed
</li>
列表渲染的循環語句修改:
<li
:class="{completed: todo.checked, editing: index === editingIndex}"
v-for="(todo,index) in filteredTodoList" :key="'todo-'+index"
var visibility = location.hash.substr(location.hash.indexOf('/')+1);
visibility = visibility === '' ? 'all' : visibility
data: {
visibility: visibility,
...
}
computed: {
...
// 已完成的任務數量
completedCount() {
return filters.completed(this.todoList).length;
}
}
methods: {
...
// 清空已完成的任務列表
clearCompleted() {
this.todoList = filters.active(this.todoList)
}
}
<button class="clear-completed" @click="clearCompleted" v-show="completedCount > 0">清空已完成</button>