实现一个todoList组件

图片展示:

 功能:添加,删除,按类展示,全选

要点:

1、已勾选的文字画横线效果是根据数据源的done(完成与否)属性,动态绑定class实现的

2、列表展示的是原todos过滤之后的数据,实现删除后就动态显示还存在的数据

3、底部的 All Active Complete 按钮去切换过滤文件的key选择要显示的过滤好的数据,默认就是所有

4、点击文字出现input框通过 v-show控制,绑定鼠标事件把value传出来更改原数据

5、全选实现方式就是把原数据的所有done属性改成true

代码

TodoList组件

<template>
  <section class="todoapp">
    <!-- 头部区域 -->
    <header class="header">
      <input class="new-todo" placeholder="请输入一条待办事项" @keyup.enter="addTodo">
    </header>
    <!-- 中间部分 -->
    <section class="main" v-show="todos.length">
      <input class="toggle-all" id="toggle-all" type="checkbox" :checked="allChecked" @change="toglleAll({done: !allChecked })">
      <!-- 这个是那个小三角 -->
      <label for="toggle-all"></label>
      <!-- todo子组件主体 -->
      <ul class="todo-list">
        <todo v-for="(todo,index) in filteredTodos" :key="index" :todo="todo" @toggleTodo="toggleTodo" @editTodo="editTodo" @deleteTodo="deleteTodo"></todo>
      </ul>
    </section>
    <!-- 底部区域 -->
    <footer class="footer" v-show="todos.length">
      <span>{{remaining}} items left</span>
      <ul class="filters">
        <li v-for="(val, key) in filters" :key="key">
          <a :class="{selected: visibility === key}" @click.prevent="visibility = key">{{key | capitalize}}</a>
        </li>
      </ul>
    </footer>
  </section>
</template>

<script>
import Todo from './Todo.vue'
export default {
  components: { Todo },
  filters: {
    capitalize: s => s.charAt(0).toUpperCase() + s.slice(1)
  },
  name: 'TodoList',
  data () {
    return {
      visibility: 'all',
      todos: [
        { text: 'star this repository', done: false },
        { text: 'fork this repository', done: false },
        { text: 'follow author', done: false },
        { text: 'vue-element-admin', done: true },
        { text: 'vue', done: true },
        { text: 'element-ui', done: true },
        { text: 'axios', done: true },
        { text: 'webpack', done: true }
      ],
      filters: {
        all: todos => todos,
        active: todos => todos.filter(todo => !todo.done),
        complete: todos => todos.filter(todo => todo.done)
      }
    }
  },
  methods: {
    addTodo (e) {
      const text = e.target.value
      if (text.trim()) {
        this.todos.push({ text, done: false })
      }
      // 为啥要清空,下次再添加value不就已经变了吗
      // 是因为这没有用v-model收集的原因吗?
      e.target.value = ''
    },
    toglleAll ({ done }) {
      this.todos.forEach(todo => {
        todo.done = done
      })
    },
    toggleTodo (todo) {
      todo.done = !todo.done
    },
    deleteTodo (todo) {
      this.todos.splice(this.todos.indexOf(todo), 1)
    },
    editTodo ({ todo, value }) {
      todo.text = value
    }
  },
  computed: {
    allChecked () {
      return this.todos.every(todo => todo.done)
    },
    remaining () {
      return this.todos.filter(todo => !todo.done).length
    },
    filteredTodos () {
      return this.filters[this.visibility](this.todos)
    }
  }
}
</script>

<style lang="scss">
@import './index.scss';
</style>

Todo组件

<template>
  <li :class="{completed:todo.done, editing:editing}" class="todo">
    <!-- 可视区域 -->
    <div class="view">
      <!-- 勾选框 -->
      <input type="checkbox" class="toggle" :checked="todo.done" @change="toggleTodo(todo)">
      <!-- 待办事项文字 -->
      <label v-text="todo.text" @dblclick="editing = true"></label>
      <!-- 删除按钮 -->
      <button class="destroy" @click="deleteTodo(todo)"></button>
    </div>
    <!-- 当编辑才能出现的输入框 -->
    <input v-show="editing" :value="todo.text" class="edit" @keyup.enter="doneEdit" @keyup.esc="cancelEdit" @blur="doneEdit">
  </li>
</template>

<script>
export default {
  name: 'Todo',
  props: {
    todo: {
      type: Object,
      default: function () {
        return {}
      }
    }
  },
  data () {
    return {
      editing: false
    }
  },
  methods: {
    toggleTodo (todo) {
      this.$emit('toggleTodo', todo)
    },
    deleteTodo (todo) {
      this.$emit('deleteTodo', todo)
    },
    editTodo ({ todo, value }) {
      this.$emit('editTodo', { todo, value })
    },
    doneEdit (e) {
      const value = e.target.value.trim()
      const { todo } = this
      if (!value) {
        this.deleteTodo(todo)
      } else if (this.editing) {
        this.editTodo({
          todo,
          value
        })
        this.editing = false
      }
    },
    cancelEdit (e) {
      e.target.value = this.todo.text
      this.editing = false
    }
  }
}
</script>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值