1. 程式人生 > 實用技巧 >vue基礎(五),對todos的操作

vue基礎(五),對todos的操作

對於totos的操作

入口main.js檔案

// 引入vue

import Vue from 'vue'
// 引入App
import App  from './App'

// 配置vue物件

new Vue({
  el:"#root",
  // 註冊元件,渲染元件
  render : h=> h(App)

})

App元件

<template>
  <div class="todo-container">
    <div class="todo-wrap">
      <Header :todos="todos" :updateO
="updateO"></Header> <Main :todos="todos" :changeStatus= "changeStatus" :dltO="dltO" ></Main> <Footer :todos="todos" :delQc="delQc"></Footer> </div> </div> </template> <script> // 引入元件 import Header from
'@/components/Header' import Main from '@/components/Main' import Footer from '@/components/Footer' export default { name:'App', data() { return { todos:[ {id:1,content:'抽菸', isOver:false}, {id:2,content:'喝酒', isOver:true}, {id:3,content:'燙頭', isOver:false}, ] }; }, methods:{
//接收header的資料 updateO(obj){ //新增的物件的id是最後一個id加1 let id = this.todos[this.todos.length-1].id+1 obj.id =id //陣列往頂部新增一個物件 this.todos.unshift(obj) console.log(this.todos) }, //item元件點選單選框,改變狀態 changeStatus(index){ //取反 this.todos[index].isOver = !this.todos[index].isOver }, //item元件點選刪除按鈕 dltO(index){ this.todos.splice(index,1) }, //對於footer元件中過濾的新陣列賦值給原陣列 delQc(newTodos){ this.todos =newTodos } }, // 註冊元件 components:{ Header, Main, Footer, } }; </script> <style scoped lang="less"> /*app*/ .todo-container { width: 600px; margin: 0 auto; } .todo-container .todo-wrap { padding: 10px; border: 1px solid #ddd; border-radius: 5px; } </style>

Header元件

<template>
  <div class="todo-header">
    <input type="text" placeholder="請輸入你的任務名稱,按回車鍵確認"  v-model="content"  @keyup.enter="update" />
  </div>
</template>

<script>
export default {
  //輸入框一個按鍵事件,新增li

  name:'Header',
  data() {
    return {
      content:'',
    };
  },

  // 接收父元件的資料
  props:{
    todos:Array,
    updateO:Function
  },

  methods:{
    //輸入框輸入資料,組成一個新物件,給父元件傳遞過去
    update(){
      let {content} =this
      if(content.trim()){
        //新物件
        let obj ={
          content,
          isOver:false
        }

        //傳遞資料給父元件
        this.updateO(obj)
        this.content=''
      }
    }
  }


};
</script>

<style scoped  lang="less">
/*header*/
.todo-header input {
  width: 560px;
  height: 28px;
  font-size: 14px;
  border: 1px solid #ccc;
  border-radius: 4px;
  padding: 4px 7px;
}

.todo-header input:focus {
  outline: none;
  border-color: rgba(82, 168, 236, 0.8);
  box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(82, 168, 236, 0.6);
}

</style>

Main元件

<template>
  <ul class="todo-main">
    <Item 
      v-for="(todo, index) in todos" :key="todo.id"
      :todo="todo"
      :index="index"
      :changeStatus= "changeStatus"
      :dltO="dltO"
    ></Item>
   
  </ul>
</template>

<script>
import Item from './Item'
export default {
  name:'Main',
  data() {
    return {};
  },

  props:{
    todos:Array,
     changeStatus:Function,
     dltO:Function,
  },

  //註冊元件
  components:{
    Item
  }
};
</script>

<style scoped  lang="less">
/*main*/
.todo-main {
  margin-left: 0px;
  border: 1px solid #ddd;
  border-radius: 2px;
  padding: 0px;
}

.todo-empty {
  height: 40px;
  line-height: 40px;
  border: 1px solid #ddd;
  border-radius: 2px;
  padding-left: 5px;
  margin-top: 10px;
}
</style>

Item元件

<template>
  <li  @mouseenter="isShow=true"  @mouseleave="isShow=false" :class="{myClass:isShow}">
    <label>
      <input type="checkbox" :checked="todo.isOver"  @click="changeZt" />
      <span>{{todo.content}}</span>
    </label>
    <button class="btn btn-danger" 
      v-show="isShow"
      @click="deleteO"
      
    
    >刪除</button>
  </li>
</template>

<script>
export default {
  //1.點選li中的單選按鈕,需要父元件的資料更改狀態,需要傳遞一個index引數,定位是那個li
  //2.點選刪除按鈕,需要父元件運算元組的邏輯,需要傳遞一個index引數,定位是那個li
  //3.移入,移出事件,li變化顏色,而且刪除按鈕也會跟著改變


  name:"Item",
  props:{
    todo:Object,
    index:Number,
    changeStatus:Function,
    dltO:Function,
  },
  data() {
    return {
      //定義一個狀態
      isShow:false
    };
  },

  methods:{
    changeZt(){
      //點選單選框,更改狀態
      this.changeStatus(this.index)

    },

    //點選刪除按鈕
    deleteO(){
      //給組價傳遞index
      this.dltO(this.index)
    }
  }


};
</script>

<style scoped  lang="less">
/*item*/

.myClass{
  background-color: hotpink;
}

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;
}

</style>

Footer元件

<template>
  <div class="todo-footer">
    <label>
      <input type="checkbox"  v-model="ischeck" />
       <!-- isCheckAll的資料是和checked屬性值進行關聯的 -->
      <!-- 
        v-model 如果input當中是有value的,那麼v-model影響的就是value的值
        對於文字輸入框密碼輸入框來說一定是有value的
        對於單選輸入框和多選輸入框,如果沒有寫value,那麼影響的的是checked的值
       --> 
    </label>
    <span> <span>已完成{{qcNum}}</span> / 全部{{qbNum}} </span>
    <button class="btn btn-danger"  @click="deleteQc">清除已完成任務</button>
  </div>
</template>

<script>
export default {

  //1.父元件傳遞todos元件,計算已完成和全部數量
  // 2.對於全選按鈕,需要判斷兩種情況,一種是獲取,一種是修改
  // 對於獲取邏輯,需要判斷已完成數量和全部數量是否全等,
  //對於修改邏輯,則需要對遍歷todos的每個物件,狀態進行修改
  //3.對於清除已完成的任務,需要判斷已經狀態為true的物件清除


  name:'Footer',
  props:{
    todos:Array,
    delQc:Function,
  },
  data() {
    return {};
  },

  methods:{
    deleteQc(){
      //將新陣列傳遞父元件,讓父元件對原陣列跟新
      let newTodos=  this.todos.filter(item =>!item.isOver)
      this.delQc(newTodos)

    }
  },

  // 計算屬性,元件中沒有的屬性

  computed:{
    //計算完成的數量
    qcNum(){
      return this.todos.filter(item =>item.isOver).length
    },

    //計算全部的數量
    qbNum(){
      return this.todos.length
    },

    ischeck:{
      
      //獲取方法
      get(){
        return  this.qcNum ===this.qbNum && this.qbNum>0
      },

      //修改方法
      set(value){
        //遍歷todos,將每一項的isOver都隨著vlaue改變
        this.todos.forEach(item =>item.isOver = value)
      }
    }


  }




};
</script>

<style scoped  lang="less">

/*footer*/
.todo-footer {
  height: 40px;
  line-height: 40px;
  padding-left: 6px;
  margin-top: 5px;
}

.todo-footer label {
  display: inline-block;
  margin-right: 20px;
  cursor: pointer;
}

.todo-footer label input {
  position: relative;
  top: -1px;
  vertical-align: middle;
  margin-right: 5px;
}

.todo-footer button {
  float: right;
  margin-top: 5px;
}

</style>