Function is introduced

  1. You can enter to-do items
  2. Enter the enter key to add a to-do list and display it in the input box to form a to-do list
  3. If you don’t want a to-do item, you can delete it
  4. When a to-do item is complete, you can check it off
  5. You also need to display unfinished items
  6. You can choose all of them
  7. You can filter tasks (completed, unfinished) and switch the status of to-do items
  8. Local storage

ToDoList feature list

  • Add a to-do list
  • Delete the to-do list
  • Edit your to-do list
  • Toggle the to-do list
  • Store to-do lists

The project structure

Vue3 project construction was completed using vuE-CLI scaffolding.

  1. main.js

Project entry, mount of the root instance

import { createApp } from 'vue'
import App from './App.vue'

createApp(App).mount('#app')
Copy the code
  1. App.vue

TodoList style was introduced, and the basic HTMl structure was built. In order to eliminate vue3 learning noise, styles and HTMl shelf code can be customized

  • HTML structure
    • header
      • Title (TODOS)
      • To-do entry box
    • section
      • To-do list
    • footer
      • Number of todo items
      • To-do list filter items (all, to do, done)

Next, complete the Todolist feature list using the VUe3 API we learned from the front end

Function 1: Add a to-do list

Analysis: To add a text box of to-do items, bind a data. When the user enters the to-do items, record the data and press Enter to store the data in an array for later display

<input
    class="new-todo"
    placeholder="What needs to be done?"
    autocomplete="off"
    autofocus
    v-model="input" // Use v-model to bind user input data with variable input
    @keyup.enter="addTodo" // the addTodo method addTodo is called when enter
    >
Copy the code

We can do todo add-ons in setup, but we learned from the compositionAPI that the same interaction is wrapped in a function for later use. With this in mind, we wrapped the todo add-ons in a function

// 1. Add a to-do list
const useAdd = todos= > {
  // Use ref to declare a reactive base data for the input box binding and return
  const input = ref(' ')
  // Declare an add todo method
  const addTodo = () = > {
    const text = input.value && input.value.trim()

    if(text.length === 0) return;
    // Store todo in array, including contents, and completion state (incomplete when added)
   // Note that todos is also responsive data, so todos.value
    todos.value.unshift({
      text,
      completed: false})}return {
    input,
    addTodo
  }
}
Copy the code

Use useAdd in setup to declare a responsive variable (TODOS) with an array of values to collect added TODos

. setup () {// For toDO storage, this data changes todolist list is also refreshed so it is also reactive data, use ref
    const todos = ref([])
    return{ todos, ... useAdd(todos) } }, ...Copy the code

Render the todo collected from Todos

    <ul class="todo-list">
       <li
         v-for="todo in todos"/ / usev-forInstructions to traverse thetodos
         :key="todo"
         :class="{completed: todo.completed }"/ / usetodoComplete State Control Class >
         <div class="view">
           <label>{{ todo.text }}</label>// Display todo content</div>
       </li>
     </ul>
Copy the code

Good!!!!!! Finish adding to-do items first

Delete todo

Find the todolist, add a delete button to todolist, bind a click event, and call remove

<ul class="todo-list">
        <li
          v-for="todo in todos"
          :key="todo"
          :class="{completed: todo.completed }"
        >
          <div class="view">.<label >{{ todo.text }}</label>
            <button class="destroy" @click="remove(todo)"></button>// Delete button</div>.</li>
      </ul>
Copy the code

As with add, remove is encapsulated as a function

const useRemove = todos= > {
    const remove = todo= > {
        const index = todos.value.indexOf(todo)
        todos.value.splice(index, 1)}return {
        remove // Return the remove method to be used by the instance}}Copy the code

Note that toDOS is reactive data and requires. Value to be consumed. A little sad

Edit your to-do list

Analysis: this function is responsible for a bit, if we felt that we have added the backlog of input is wrong, you want to edit, you can double-click the to-do list, enter a state of edit box, and lets the input box to get the focus (the some difficult, need a custom instruction), the original backlog echo in the input box, and then you can edit and save. If it is empty, press Enter to delete the todo summary:

  • Double-click the to-do list to display the edit text box
  • Press Enter or edit the text box to lose focus and modify the data
  • Press Esc to cancel editing
  • Clear the edit text box and press Enter to delete this item
  • Gets focus when the edit text box is displayed
// 3. Edit to-do items
const useEdit= remove= > {
  // This is used to cache the content before the edit. If the edit is cancelled, the change value is used. This value does not affect dom updates and ref is not required
  let beforeEditingText = ' '
  // Edit the content, bind the edit input text box
  const editingTodo = ref(null)
  const editTodo = todo= > {
    beforeEditingText = todo.text;
    editingTodo.value = todo
  }
  // Delete if all contents are cleared during editing
  const doneEdit = todo= > {
    if(! editingTodo.value)return
    todo.text = todo.text.trim()
    todo.text || remove(todo) / / delete
    editingTodo.value = null
  }
  // Cancel the edit method
  const cancelEdit = todo= > {
    editingTodo.value = null
    todo.text = beforeEditingText
  }

  return {
    editingTodo,
    editTodo,
    doneEdit,
    cancelEdit
  }
}
Copy the code

There’s a remove method that needs to be passed in. Find the position associated with traversal, bind the edit state, and bind the method editTodo corresponding to the double click edit event. The input text box binds the focus event, the doneEdit method, and the ESC event binds the cancelEdit method.

<ul class="todo-list">
        <li
          v-for="todo in todos"
          :key="todo"/ / herekeyThe best bindingtodoobject:class="{ editing: todo === editingTodo }"// Edit status is hiddenviewdom
        >
          <div class="view">
            <input class="toggle" type="checkbox" v-model="todo.completed">
            <label @dblclick="editTodo(todo)">{{ todo.text }}</label>// Bind double click, editTodo<button class="destroy" @click="remove(todo)"></button>
          </div>
          <input
            class="edit"
            type="text"
            v-editing-focus="todo === editingTodo"
            v-model="todo.text"
            @keyup.enter="doneEdit(todo)"/ / bindingenterEvent, deletetodo
            @blur="doneEdit(todo)"
            @keyup.esc="cancelEdit(todo)"// Unedit >
        </li>
      </ul>
Copy the code

Note: How do I make the cursor appear when I double click the textbox

Double-click the text box to get the focus

Custom instruction

  • When the second argument is an object:

vue 2.x

Vue.directive('editingFocus', {
    bind(el, binding,vnode, prevVnode) {},
    inserted() {},
    update() {},
    componentUploadtes() {},
    unbind(){}})Copy the code

Vue 3.0

Vue.directive('editingFocus', {
    beforeMount(el, binding,vnode, prevVnode) {},
    mounted() {},
    beforeUpdate() {},
    updated() {},
    beforeUnmount() {},
    unmounted(){}})Copy the code

Vue 3 directive hook functions and component hook functions are the same, which is easier to understand and less mental burden to use. But custom directive hook functions perform a little differently than component hook functions.

  • When the second argument is a function, vue2. X is no different from vue3
app.directive('editingFocus'.(el, binding) = > {
    binding.value && el.focus()
})
Copy the code

We can use a custom directive to be the focus of the manipulation text box, and we’ll call that a custom directive v-Editing focus

    <input
    class="edit"
    type="text"
    v-editing-focus="todo === editingTodo"
    v-model="todo.text"
    @keyup.enter="doneEdit(todo)"
    @blur="doneEdit(todo)"
    @keyup.esc="cancelEdit(todo)"
    >
    directives: {
        editingFocus: (el, binding) => {
            binding.value && el.focus()
        }
        
    }
Copy the code

This causes the changed element to fire the focus event when the binding value is true

Finish two-thirds, continue tomorrow….