analysis:
① : initialize todo project
② : create 3 components and internal code
③ : prepare the style file of styles
④: App.vue is introduced for registration. The outermost container class name is todoapp
Prepare in advance: prepare the style file of styles (copy it from the preview materials) in app Vue introduction and use (there is a link behind)
// 1.0 Style Introduction import "./styles/base.css" import "./styles/index.css"
1. Laying to-do tasks
Purpose: to display the to-do tasks to todomain On Vue assembly
- Requirement 1: display the to-do tasks to todomain On Vue assembly
- Requirement 2: Associate selected status and set related styles
analysis:
①: App.vue – prepare array to pass into todomain Within Vue
② : v-for loop display data
③ The: v-model binding check box is selected
④ : sets the finish dash style according to the selected status
App.vue
<TodoMain :arr="showArr"></TodoMain> <script> export default { data() { return { list: [ { id: 100, name: "having dinner", isDone: true }, { id: 102, name: "sleep", isDone: false }, { id: 103, name: "Beat beans", isDone: true }, ], }; } }; </script>
TodoMain.vue
<template> <ul class="todo-list"> <!-- 2.2 Circular task-Association selected status-Laying data --> <!-- completed: Completed class name --> <li :class="{completed: obj.isDone}" v-for="(obj, index) in arr" :key='obj.id'> <div class="view"> <input class="toggle" type="checkbox" v-model="obj.isDone"/> <label>{{ obj.name }}</label> <!-- 4.0 Register click events --> <button class="destroy"></button> </div> </li> </ul> </template> <script> export default { props: ["list"] }; </script> <style> </style>
2. Add task
Objective: enter the task name to be completed in the top input box, and click enter to complete the new function
Demand: enter a task and press enter to add a to-do task
analysis:
①: TodoHeader.vue – input box – keyboard event – enter key
② : pass the child to the parent and send the to-do task – app Vue – add to the array list
③ : if the original array is changed, all the places used will be updated
④ : the input box is empty, prompting the user to enter content
TodoHeader.vue
<template> <header class="header"> <h1>todos</h1> <input id="toggle-all" class="toggle-all" type="checkbox" v-model="isAll"> <label for="toggle-all"></label> <!-- 3.0 Keyboard events-Enter key 3.1 Input box - v-model Get value --> <input class="new-todo" placeholder="Enter task name-Enter to confirm" autofocus @keydown.enter="downFn" v-model="task" /> </header> </template> <script> // 3. Objective - new task export default { data(){ return { task: "" } }, methods: { downFn(){ if (this.task.trim().length === 0) { alert("Task name cannot be empty"); return; } // 3.2 (important) - the name of the current task should be added to the list array // Son to father Technology this.$emit("create", this.task) this.task = "" } } } </script>
App.vue
<TodoHeader @create="createFn"></TodoHeader> methods: { createFn(taskName){ // Add task // 3.3 push to array let id = this.list.length == 0 ? 100 : this.list[this.list.length - 1].id + 1 this.list.push({ id: id, name: taskName, isDone: false }) }, }
3. Delete task
Objective: to achieve point x and delete the task function
Requirement: click x after the task to delete the current task
analysis:
① : x tag – click event – pass in id area
② : pass the child to the parent, and return the id – app In Vue – delete a corresponding object in the array list
③ : if the original array is changed, all the places used will be updated
App.vue - incoming custom event waiting to receive sequence number to be deleted
<TodoMain :arr="showArr" @del="deleteFn"></TodoMain> methods: { deleteFn(theId){ // Delete task let index = this.list.findIndex(obj => obj.id === theId) this.list.splice(index, 1) }, },
TodoMain.vue - pass the id back to delete (delete the data wherever you want)
<!-- 4.0 Register click events --> <button class="destroy" @click="delFn(obj.id)"></button> methods: { delFn(id){ // 4.1 son to father this.$emit('del', id) } }
4. Bottom statistics
Objective: to display the total number of current tasks
Demand: count the number of current tasks
analysis:
①: App.vue - array list - passed to todofooter vue
② : display / define calculation properties directly on the label for display
③ : as long as the original array is changed, all places where this array is used will be updated
TodoFooter.vue - direct display of received list statistics
<template> <footer class="footer"> <span class="todo-count">surplus<strong>{{ count }}</strong></span> <ul class="filters"> <li> <a class="selected" href="javascript:;">whole</a> </li> <li> <a href="javascript:;">hang in the air</a> </li> <li> <a href="javascript:;">Completed</a> </li> </ul> <button class="clear-completed">Cleanup completed</button> </footer> </template> <script> export default { // 5.0 props definition props: ['farr'], // 5.1 calculation attribute - task quantity computed: { count(){ return this.farr.length } }, } </script> <style> </style>
App.vue - incoming data
<TodoFooter :farr="showArr"></TodoFooter>
5. Data switching
Purpose: click the bottom to switch data
Requirement 1: click the switch at the bottom - who has a border
Requirement 2: switch different data display correspondingly
analysis:
①: TodoFooter.vue – define isSel – the value is all, yes, no, one of them
② selected: multiple classes determine who should have the class name
③ : Click to modify the value of isSel
④ : pass the child to the parent, and pass the type isSel to app vue
⑤ : define the calculation attribute showArr to determine which data to display to todomain from the list Vue and todofooter vue
App.vue
<TodoFooter :farr="showArr" @changeType="typeFn"></TodoFooter> <script> export default{ data(){ return { // ... Other omissions getSel: "all" // Show all by default } }, methods: { // ... Other omissions typeFn(str){ // 'all', 'yes',' no '/ / modify type this.getSel = str }, }, // 6.5 define showArr array - filtered by list matching conditions computed: { showArr(){ if (this.getSel === 'yes') { // Show completed return this.list.filter(obj => obj.isDone === true) } else if (this.getSel === 'no') { // Show incomplete return this.list.filter(obj => obj.isDone === false) } else { return this.list // show all } } }, } </script>
TodoFooter.vue
<template> <footer class="footer"> <span class="todo-count">surplus<strong>{{ count }}</strong></span> <ul class="filters" @click="fn"> <li> <!-- 6.1 Determine who should have a highlighted style: dynamic class 6.2 User clicks to switch isSel Values saved in --> <a :class="{selected: isSel === 'all'}" href="javascript:;" @click="isSel='all'">whole</a> </li> <li> <a :class="{selected: isSel === 'no'}" href="javascript:;" @click="isSel='no'">hang in the air</a> </li> <li> <a :class="{selected: isSel === 'yes'}" href="javascript:;" @click="isSel='yes'">Completed</a> </li> </ul> <!-- 7. target: Cleanup completed --> <!-- 7.0 Click event --> <button class="clear-completed" >Cleanup completed</button> </footer> </template> <script> // 5. Objective: quantity statistics export default { // 5.0 props definition props: ['farr'], // 5.1 calculation attribute - task quantity computed: { count(){ return this.farr.length } }, // 6. Goal: who lights up // 6.0 variable isSel data(){ return { isSel: 'all' // All: 'all', completed 'yes', incomplete' no ' } }, methods: { fn(){ // Toggle filter criteria // 6.3 child - > parent type string is passed to app vue this.$emit("changeType", this.isSel) } } } </script>
6. Emptying completed
Purpose: click the button in the lower right corner to clear the completed tasks
Requirements: click the link tab in the lower right corner to clear the completed tasks
analysis:
① : empty tab – click event
② Child to parent – app Vue – an emptying method
③ : filter the incomplete overlay list array (regardless of recovery)
App.vue - pass in a custom event first - because you have to receive todofooter Click events in Vue
<TodoFooter :farr="showArr" @changeType="typeFn" @clear="clearFun"></TodoFooter> <script> methods: { // ... Omit others clearFun(){ // Cleanup completed this.list = this.list.filter(obj => obj.isDone == false) } } </script>
TodoFooter.vue
<!-- 7. target: Cleanup completed --> <!-- 7.0 Click event --> <button class="clear-completed" @click="clearFn">Cleanup completed</button> <script> methods: { clearFn(){ // Empty completed tasks // 7.1 trigger app clearFun method corresponding to events in Vue this.$emit('clear') } } </script>
7. Data cache
Purpose: after adding / modifying status / deleting, synchronize the data to the local storage of the browser immediately
Requirements: no matter what changes – ensure that the data is still after refresh
analysis:
①: App.vue - Listen list array change - depth
② : overwrite save locally – note that only JSON strings can be saved locally
③ : refresh the page – the list should take value locally by default – empty array without data should be considered
App.vue
<script> export default { data(){ return { // 8.1 default value from local list: JSON.parse(localStorage.getItem('todoList')) || [], // 6.4 first transfer receiving type string getSel: "all" // Show all by default } }, // 8. Target: data cache watch: { list: { deep: true, handler(){ // 8.0 as long as the list changes - overwrite save to localStorage localStorage.setItem('todoList', JSON.stringify(this.list)) } } } }; </script>
8. Select all function
Objective: click the v in the upper left corner to set one key to complete, and then click again to cancel the selection of all
Requirement 1: click Select all – the small selection box is affected
Requirement 2: select all the small boxes (manually) – select all and select automatically
analysis:
①: TodoHeader.vue – calculate attributes - isAll
②: App.vue – pass in the array list – affect the small checkbox in the set of isAll
③ : count the last status of the small selection box in the get of isAll, affect isAll – affect the status of all selection
④ : consider the empty array without data - select all and should not be checked
Tip: it is to traverse all objects and modify the value of their completion status attribute
TodoHeader.vue
<!-- 9. target: Select all status 9.0 v-model Associated select all status Page change(Tick true, Unchecked false) -> v-model -> isAll variable --> <input id="toggle-all" class="toggle-all" type="checkbox" v-model="isAll"> <script> export default { // ... Other omissions // 9.1 defining calculation attributes computed: { isAll: { set(checked){ // Only true / false // 9.3 isDone attribute that affects the binding of each small checkbox in the array this.arr.forEach(obj => obj.isDone = checked) }, get(){ // 9.4 statistical status of small selection box - > select all box // 9.5 if there is no data, directly return false - do not make all checked return this.arr.length !== 0 && this.arr.every(obj => obj.isDone === true) } } }, } </script>
App.vue
<TodoHeader :arr="list" @create="createFn"></TodoHeader>
Download all codes -- Click here -- extraction code: 8888