美文网首页
toDoList案例

toDoList案例

作者: 冰点雨 | 来源:发表于2022-04-06 10:13 被阅读0次

    1.组件化编码流程
    (1)拆分静态组件:组件要按照功能点拆分,命名不要与 html 元素冲突
    (2)实现动态组件:考虑好数据的存放位置,数据是一个组件在用,还是一些组件在用
    a.一个组件在用,放在组件自身即可
    b.一些组件在用:放在他们共同的父组件上()
    (3)实现交互:从绑定事件开始

    2.props 适用于:
    (1)父组件 ==> 子组件 通信
    (2)子组件 ==> 父组件 通信(要求先给子一个函数)
    3.使用 v-model 时要切记:v-model 绑定的值不能是 props 传过来的值,因为 props 是不可以修改的
    4.props 传过来的若是对象类型的值,修改对象中的属性时 Vue 不会报错,但不推荐这样做


    e77a0010f82ea8861182a5b39fb115b.png

    App.vue

    <template>
      <div id="root">
        <div class="todo-container">
          <div class="todo-wrap">
            <MyHeader :addTodo="addTodo" />
            <MyList
              :todos="todos"
              :changeTodo="changeTodo"
              :deleteTodo="deleteTodo"
            />
            <MyFooter
              :todos="todos"
              :checkAllTodo="checkAllTodo"
              :clearAllTodo="clearAllTodo"
            />
          </div>
        </div>
      </div>
    </template>
    
    <script>
    // 引入组件
    import MyHeader from './components/MyHeader'
    import MyList from './components/MyList'
    import MyFooter from './components/MyFooter'
    
    export default {
      name: 'App',
      components: {
        MyHeader,
        MyList,
        MyFooter,
      },
      data() {
        return {
          todos: [],
        }
      },
      methods: {
        // 添加
        addTodo(todoObj) {
          this.todos.unshift(todoObj)
        },
        // 选择
        changeTodo(id) {
          this.todos.forEach((todo) => {
            if (todo.id === id) todo.done = !todo.done
          })
        },
        // 删除
        deleteTodo(id) {
          this.todos = this.todos.filter((todo) => {
            return todo.id !== id
          })
        },
        // 全选
        checkAllTodo(done) {
          this.todos.forEach((todo) => {
            todo.done = done
          })
        },
        //清除所有已完成的todo
        clearAllTodo() {
          this.todos = this.todos.filter((todo) => {
            return !todo.done
          })
        },
      },
    }
    </script>
    
    <style>
    </style>
    

    MyHeader.vue

    <template>
      <div class="todo-header">
        <input
          type="text"
          placeholder="请输入你的任务名称,按回车键确认"
          v-model="title"
          @keyup.enter="add"
        />
      </div>
    </template>
    
    <script>
    import { nanoid } from 'nanoid'
    export default {
      name: 'MyHeader',
      data() {
        return {
          title: '',
        }
      },
      props: ['receive'],
      methods: {
        add() {
          if (!this.title.trim()) return alert('输入不能为空')
          // 将用户的输入包装成一个todo对象
          const todoObj = { id: nanoid(), title: this.title, done: false }
          // 通知APP组件去添加一个todo对象
          this.receive(todoObj)
          // 清空输入框数据
          this.title = ''
        },
      },
    }
    </script>
    
    <style scoped>
    </style>
    

    MyList.vue

    <template>
      <ul class="todo-main">
        <MyItem
          v-for="todoObj in todos"
          :key="todoObj.id"
          :todo="todoObj"
          :changeTodo="changeTodo"
          :deleteTodo="deleteTodo"
        />
      </ul>
    </template>
    
    <script>
    import MyItem from './MyItem'
    export default {
      name: 'MyList',
      components: { MyItem },
      props: ['todos', 'changeTodo', 'deleteTodo'],
    }
    </script>
    
    <style scoped>
    </style>
    

    MyFooter.vue

    <template>
      <div class="todo-footer" v-show="total">
        <label>
          <!-- <input type="checkbox" :checked="isAll" /> -->
           <input type="checkbox" v-model="isAll"/>
        </label>
        <span>
          <span>已完成{{ doneTotal }}</span>/全部{{total}}
        </span>
        <button class="btn btn-danger" @click="clearAll">清除已完成任务</button>
      </div>
    </template>
    
    <script>
    export default {
      name: 'MyFooter',
      props: ['todos','checkAllTodo','clearAllTodo'],
      computed: {
        total(){
          return this.todos.length
        },
        doneTotal() {
          // return this.todos.reduce((pre,current)=>{
          //   return pre+(current.done ? 1 :0)
          // },0)
          return this.todos.reduce(
            (pre, current) => pre + (current.done ? 1 : 0),
            0
          )
        },
        isAll:{
          get(){
             return this.doneTotal === this.total && this.total > 0
          },
          set(value){
             this.checkAllTodo(value)
          }
        }
      },
      methods:{
        clearAll(){
            this.clearAllTodo()
        }
      }
    }
    </script>
    
    <style scoped>
    </style>
    

    MyItem.vue

    <template>
      <li>
        <label>
          <input
            type="checkbox"
            :checked="todo.done"
            @change="handleCheck(todo.id)"
          />
          <!-- 如下代码也能实现功能,但是不太推荐,因为有点违反原则,修改了props-->
          <!-- <input
            type="checkbox"
            v-model="todo.done"
          /> -->
          <span>{{ todo.title }}</span>
        </label>
        <button class="btn btn-danger" @click="handleDelete(todo.id)">删除</button>
      </li>
    </template>
    
    <script>
    export default {
      name: 'MyItem',
      // 声明接收todo对象
      props: ['todo', 'changeTodo', 'deleteTodo'],
      methods: {
        handleCheck(id) {
          // 通知APP对象将对应的todo对象done取反
          this.changeTodo(id)
        },
        handleDelete(id) {
          if (confirm('确定删除吗?')) {
            this.deleteTodo(id)
          }
        },
      },
    }
    </script>
    
    <style scoped>
    li {
      list-style: none;
      height: 36px;
      line-height: 36px;
      padding: 0 5px;
      border-bottom: 1px solid #ddd;
    }
    
    li label {
      float: left;
      cursor: pointer;
    }
    
    li label li input {
      vertical-align: middle;
      margin-right: 6px;
      position: relative;
      top: -1px;
    }
    
    li button {
      float: right;
      display: none;
      margin-top: 3px;
    }
    
    li:before {
      content: initial;
    }
    
    li:last-child {
      border-bottom: none;
    }
    
    li:hover {
      background-color: #ddd;
    }
    
    li:hover button {
      display: block;
    }
    </style>
    
    

    相关文章

      网友评论

          本文标题:toDoList案例

          本文链接:https://www.haomeiwen.com/subject/vosjdrtx.html