寫做時間:2019-12-10javascript
版本信息:Vue.js 2.6.10css
官網文檔:cn.vuejs.org/html
學習 Vue 的最佳方式之一是「請馬上查閱 Vue.js 的官方文檔」,簡單看一下「基礎」部分,配合本文食用更佳。vue
在開始寫代碼以前,首先去 BootCDN 上找一下目前最新版本完整版的 Vue.js 的連接:cdn.bootcss.com/vue/2.6.10/… ,與壓縮版(vue.min.js)不一樣,它(vue.js)包含完整的警告和調試模式。java
爲了儘量地保持簡單,本文不使用 Vue CLI 來構建項目,而是像用 jQuery 開發那樣,直接在 HTML 文件裏引入 Vue.js 文件。app
若是文章中的代碼有不明白的地方,個人建議是:直接抄代碼,看效果,看文檔,改代碼,看效果,如此循環往復。ide
瞭解一下 Vue 官網的基礎部分的「聲明式渲染」部分 ,咱們能夠建立以下代碼:函數
此時預覽 index.html 文件,會看到頁面上出現 Hello, Vue.js! 的文字。學習
咱們把要作的 To-Do App 拆分紅一個個小組件,目前先來一個組件 TodoList 和一個它的子組件 TodoItem 。經過熟悉 官網上的「組件基礎」教程 咱們來繼續作下去。ui
先來作一下 TodoList 組件。我把代碼都粘貼過來,方便取用學習。 此文章以後的代碼都是在下面這段代碼的基礎上修改,到時我就只放修改的部分代碼了,有必要的時候我會把所有代碼貼出來。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vue.js To-Do App</title>
</head>
<body>
<div id="app">
<todo-list></todo-list>
</div>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script> Vue.component('todo-list', { data: function() { return {} }, template:` <ul> <li>Todo A</li> <li>Todo B</li> <li>Todo C</li> </ul> ` }) new Vue({ el: '#app', data: {} }) </script>
</body>
</html>
複製代碼
須要注意的內容:
改寫 TodoList 組件,添加所需數據:
<!DOCTYPE html>
<html lang="zh-hans">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vue.js To-Do App</title>
</head>
<body>
<div id="app">
<todo-list v-bind:todos="todos"></todo-list>
</div>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script> Vue.component('todo-list', { data: function() { return {} }, props: ['todos'], template:` <div class="todo-list"> <p>已完成:{{todos.filter(todo => todo.done === true).length}}</p> <p>未完成:{{todos.filter(todo => todo.done === false).length}}</p> <div class="todo-item" v-for="todo in todos"> <div class="title">{{todo.title}}</div> <div class="content">{{todo.content}}</div> <div class="button" v-show="!todo.done">點擊完成</div> <div class="button" v-show="todo.done">已完成</div> </div> </div> ` }) new Vue({ el: '#app', data: { todos: [ { title: '待辦 1', content: '上課以前要抄一下同窗的做業。', done: false }, { title: '待辦 2', content: '課間和朋友去球場打籃球。', done: true }, { title: '待辦 3', content: '英語課上故意調皮一下讓美麗的英語老師注意到而後提問我。', done: false }, { title: '待辦 4', content: '放學後趕忙跑,絕對不能聽某些人的話:「放學後你給我等着」。', done: false } ] } }) </script>
</body>
</html>
複製代碼
須要注意的內容:
<div id="app">
<todo-list v-bind:todos="todos"></todo-list>
</div>
複製代碼
Vue.component('todo-list', {
// ... 省略 ...
props: ['todos'],
template:` <div class="todo-list"> <p>已完成:{{todos.filter(todo => todo.done === true).length}}</p> <p>未完成:{{todos.filter(todo => todo.done === false).length}}</p> <div class="todo-item" v-for="todo in todos"> <div class="title">{{todo.title}}</div> <div class="content">{{todo.content}}</div> <div class="button" v-show="!todo.done">點擊完成</div> <div class="button" v-show="todo.done">已完成</div> </div> </div> `
})
複製代碼
雖然寫了給某些元素寫了 class 可是尚未寫任何樣式,如今打開 index.html 預覽是這樣的:
如今咱們把 class 爲 todo-item 的元素提取出來做爲單獨的組件,除此以外咱們什麼也不作,預覽效果與剛纔一致。
Vue.component('todo-item', {
props: ['todo'],
template: ` <div class="todo-item"> <div class="title">{{todo.title}}</div> <div class="content">{{todo.content}}</div> <div class="button" v-show="!todo.done">點擊完成</div> <div class="button" v-show="todo.done">已完成</div> </div> `
})
Vue.component('todo-list', {
data: function() {
return {}
},
props: ['todos'],
template:` <div class="todo-list"> <p>已完成:{{todos.filter(todo => todo.done === true).length}}</p> <p>未完成:{{todos.filter(todo => todo.done === false).length}}</p> <todo-item v-for="(todo, index) in todos" v-bind:key="index" v-bind:todo="todo"> </todo-item> </div> `
})
複製代碼
接下來加入編輯的功能
Vue.component('todo-item', {
props: ['todo'],
data: function() {
return {
isEditing: false
}
},
template: ` <div> <div class="todo-item" v-show="!isEditing"> <div class="title">{{todo.title}}</div> <div class="content">{{todo.content}}</div> <div class="button edit" v-on:click="showForm">編輯 ✏</div> <div class="button" v-show="!todo.done">點擊完成</div> <div class="button" v-show="todo.done">已完成</div> </div> <div class="todo-item" v-show="isEditing"> <div class="form"> <div class="field"> <label>Title</label> <input type="text" v-model="todo.title" /> </div> <div class="field"> <label>Content</label> <input type="text" v-model="todo.content" /> </div> <button class="close" v-on:click="closeForm">保存並關閉編輯模式</button> </div> </div> </div> `,
methods: {
showForm: function() {
this.isEditing = true
},
closeForm: function() {
this.isEditing = false
}
}
})
複製代碼
添加的代碼作了這幾點:
Vue.component('todo-item', {
// ... 省略 ...
template: ` <div> <div class="todo-item" v-show="!isEditing"> <div class="title">{{todo.title}}</div> <div class="content">{{todo.content}}</div> <div class="button edit" v-on:click="showForm">編輯 ✏</div> <div class="button delete" v-on:click="deleteTodo(todo)">刪除 ×××</div> <div class="button" v-show="!todo.done">點擊完成</div> <div class="button" v-show="todo.done">已完成</div> </div> // ... 省略 ... </div> `,
methods: {
// ... 省略 ...
deleteTodo(todo) {
this.$emit('delete-todo', todo)
}
},
})
複製代碼
在 TodoItem 組件中添加刪除按鈕,並添加刪除的方法,這個方法會向父組件 TodoList 發送一個 delete-todo 事件以及要刪除的 todo 數據。
父組件 TodoList 中添加一個刪除事件,並監聽來自子組件的 delete-todo 事件。
Vue.component('todo-list', {
data: function() {
return {}
},
props: ['todos'],
template:` <div class="todo-list"> <p>已完成:{{todos.filter(todo => todo.done === true).length}}</p> <p>未完成:{{todos.filter(todo => todo.done === false).length}}</p> <todo-item v-for="(todo, index) in todos" v-bind:key="index" v-bind:todo="todo" v-on:delete-todo="deleteTodo" > </todo-item> </div> `,
methods: {
deleteTodo(todo) {
const index = this.todos.indexOf(todo)
this.todos.splice(index, 1)
}
},
})
複製代碼
新建一個 AddTodo 組件,將組件添加到 TodoList 組件中。
Vue.component('add-todo', {
data: function() {
return {
isAdding: false,
todo: {
title: '',
content: '',
done: false
}
}
},
template: ` <div> <div v-on:click="showForm">添加 +++</div> <div class="form" v-show="isAdding"> <div class="field"> <label>標題</label> <input type="text" v-model="todo.title" /> </div> <div class="field"> <label>內容</label> <input type="text" v-model="todo.content" /> </div> <button class="close" v-on:click="saveForm">保存</button> <button class="close" v-on:click="closeForm">取消</button> </div> </div> `,
methods: {
showForm() {
this.isAdding = true
},
saveForm() {
if (this.todo.title && this.todo.content) {
this.$emit('add-todo', this.todo)
this.closeForm()
}
},
closeForm() {
this.isAdding = false
this.todo = {
title: '',
content: '',
done: false
}
}
}
})
Vue.component('todo-list', {
// ... 省略 ...
template:` <div class="todo-list"> <add-todo v-on:add-todo="addTodo"></add-todo> <p>已完成:{{todos.filter(todo => todo.done === true).length}}</p> <p>未完成:{{todos.filter(todo => todo.done === false).length}}</p> <todo-item v-for="(todo, index) in todos" v-bind:key="index" v-bind:todo="todo" v-on:delete-todo="deleteTodo" > </todo-item> </div> `,
methods: {
// ... 省略 ...
addTodo(todo) {
this.todos.push(todo)
}
},
})
複製代碼
AddTodo 組件默認只顯示一個添加按鈕,當點擊添加按鈕的時候顯示須要填寫的表單,填寫完成後點擊保存,將向父組件 TodoList 發送一個 add-todo 事件以及表單信息。
父組件 TodoList 監聽 add-todo 事件並在事件觸發後向 todos 數據中新增一條由 AddTodo 組件發送的數據。
TodoItem 組件中,點擊完成按鈕,發送 complete-todo 事件給父組件 TodoList 。
父組件 TodoList 監聽 complete-todo 事件並在事件觸發後從 todos 數據中要完成的那條數據標記爲已完成。
Vue.component('todo-item', {
// ... 省略 ...
template: ` <div> <div class="todo-item" v-show="!isEditing"> <div class="title">{{todo.title}}</div> <div class="content">{{todo.content}}</div> <div class="button edit" v-on:click="showForm">編輯 ✏</div> <div class="button delete" v-on:click="deleteTodo(todo)">刪除 ×××</div> <div class="button" v-show="!todo.done" v-on:click="completeTodo(todo)">點擊完成</div> <div class="button" v-show="todo.done">已完成</div> </div> ...... `,
methods: {
// ... 省略 ...
completeTodo(todo) {
this.$emit('complete-todo', todo)
}
}
})
Vue.component('todo-list', {
// ... 省略 ...
template:` <div class="todo-list"> ...... <todo-item v-for="(todo, index) in todos" v-bind:key="index" v-bind:todo="todo" v-on:delete-todo="deleteTodo" v-on:complete-todo="completeTodo" > </todo-item> </div> `,
methods: {
// ... 省略 ...
completeTodo(todo) {
const index = this.todos.indexOf(todo)
this.todos[index].done = true
}
}
})
複製代碼
至此,一個基本功能還算健全的 To-Do App 就完成了。
最終的完整代碼以下,能夠直接拿走本身運行預覽一下。
<!DOCTYPE html>
<html lang="zh-hans">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Vue.js To-Do App</title>
</head>
<body>
<div id="app">
<todo-list v-bind:todos="todos"></todo-list>
</div>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script></script>
</body>
</html>
複製代碼
(完)