vue3实现todolist案例

在这里插入图片描述

<template>
  <div>
    <!-- 新增todo -->
    <input type="text" v-model="newTodo" @keyup.enter="addTodo" autofocus placeholder="新增今日待办"
      autocomplete="off">
    <!-- todo列表 -->
    <ul>
      <li v-for="todo in filterdTodos" :key="todo.id"
        :class="{completed:todo.completed,editing:todo===editedTodo}">
        <!-- 绑定完成状态 -->
        <div class="view">
          <input type="checkbox" v-model="todo.completed">
          <label @dblclick="editTodo(todo)">{{todo.title}}</label>
          <button @click="removeTodo(todo)">X</button>
        </div>
        <!-- 编辑待办 -->
        <input type="text" class="edit" v-model="todo.title" v-todo-focus="todo===editedTodo"
          @blur="doneEdit(todo)" @keyup.enter="doneEdit(todo)" @keyup.escape="cancelTodo(todo)">
      </li>
    </ul>
    <!-- 过滤 -->
    <p class="filters">
      <span @click="visibility='all'" :class="{selected:visibility==='all'}">All</span>
      <span @click="visibility='active'" :class="{selected:visibility==='active'}">Active</span>
      <span @click="visibility='completed'"
        :class="{selected:visibility==='completed'}">Completed</span>
    </p>
  </div>
</template>

<script>
import { reactive, toRefs, computed, watchEffect } from 'vue'

const filters = {
  all (todos) {
    return todos
  },
  active (todos) {
    return todos.filter(todo => !todo.completed)
  },
  completed (todos) {
    return todos.filter(todo => todo.completed)
  }
}

//缓存操作
const todoStorge = {
  fetch () {
    let todos = JSON.parse(localStorage.getItem('vue3-todos') || '[]')
    todos.forEach((todo, index) => {
      todo.id = index + 1
    })
    return todos
  },
  save (todos) {
    localStorage.setItem("vue3-todos", JSON.stringify(todos))
  }
}
export default {
  setup () {
    const state = reactive({
      newTodo: '',
      todos: todoStorge.fetch(),
      beforeEditCache: '',//缓存编辑前的title
      editedTodo: null,//正在编辑的todo
      visibility: 'all',
      filterdTodos: computed(() => {
        return filters[state.visibility](state.todos)
      })
    })
    function addTodo () {
      state.todos.push({
        id: state.todos.length + 1,
        title: state.newTodo,
        completed: false
      })
      state.newTodo = ''
    }
    function removeTodo (todo) {
      state.todos.splice(state.todos.indexOf(todo), 1)
    }
    function editTodo (todo) {
      state.beforeEditCache = todo
      state.editedTodo = todo
    }

    function cancelTodo (todo) {
      todo.title = state.beforeEditCache
      state.editedTodo = null
    }
    function doneEdit (todo) {
      state.editedTodo = null
    }

    watchEffect(() => {
      todoStorge.save(state.todos)
    })
    
    return {
      ...toRefs(state),
      addTodo,
      removeTodo,
      editTodo,
      cancelTodo,
      doneEdit,
    }
  },
  directives: {
    "todo-focus": (el, { value }, vnode) => {
      if (value) {
        el.focus();
      }
    }
  }
}
</script>

<style scoped>
.completed label {
  text-decoration: line-through;
}
.edit,
.editing .view {
  display: none;
}
.view,
.editing .edit {
  display: block;
}

.filters > span {
  padding: 2px 4px;
  margin-right: 4px;
  border: 1px solid transparent;
}
.filters > span.selected {
  border-color: rgba(173, 47, 47, 0.2);
}
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值