• vue part5.2 vuex todolist 改写


    代码

    main部分

    index.html

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width,initial-scale=1.0">
        <link rel="stylesheet" href="./static/css/bootstrap.css">
        <title>vue_demo</title>
    
        <style>
          .router-link-active {
            color: red !important;
          }
        </style>
    
      </head>
    
      <body>
        <div id="app">
    
        </div> <!--app -->
      </body>
    
    </html>
    View Code

    src/base.css

    body {
      background: #fff;
    }
    
    .btn {
      display: inline-block;
      padding: 4px 12px;
      margin-bottom: 0;
      font-size: 14px;
      line-height: 20px;
      text-align: center;
      vertical-align: middle;
      cursor: pointer;
      box-shadow: inset 0 1px 0 rgba(225, 225, 225, 0.2), 0 1px 2px rgba(0, 0, 0,0.15);
      border-radius: 4px;
    }
    
    .btn-danger {
      color: #fff;
      background-color: #da4f49;
      border: 1px solid #bd362f;
    }
    
    .btn-danger:hover {
      color: #fff;
      background-color: #bd362f;
    }
    
    .btn:focus {
      outline: none;
    }
    View Code

    src/main.js

    /**
     * Created by infaa on 2018/9/19.
     */
    import Vue from 'vue'
    import App from './components/App'
    import store from './store'
    import './base.css'
    /* eslint-disable no-new */
    
    new Vue({
      el: '#app',
      render: h => h(App),
      store
    })
    View Code

    工具部分

    src/util/storageUtil.js

    /**
     * Created by infaa on 2018/9/20.
     */
    const TODO_KEY = 'todos_key'
    export default {
      saveTodos (value) {
        window.localStorage.setItem(TODO_KEY, JSON.stringify(value))
      },
      readTodos () {
        return JSON.parse(window.localStorage.getItem(TODO_KEY) || '[]')
      }
    }
    View Code

    store 部分  (vuex)

    src/store/action.js

    /**
     * Created by infaa on 2018/9/22.
     */
    import {ADD_TODO, DELETE_TODO, SELECT_ALL_TODOS, CLEAR_ALL_COMPLETED, RECEIVE_TODOS} from './mutation-types'
    import storeageUtil from '../util/storageUtil'
    export default {
      addTodo ({commit}, todo) {
        commit(ADD_TODO, {todo})
      },
      deleteTodo ({commit}, index) {
        commit(DELETE_TODO, {index})
      },
      selectAllTodos ({commit}, check) {
        commit(SELECT_ALL_TODOS, {check})
      },
      clearALLCompleted ({commit}) {
        commit(CLEAR_ALL_COMPLETED)
      },
      reqTodos ({commit}) {
        // 模拟异步获取延迟1秒
        setTimeout(() => {
          const todos = storeageUtil.readTodos()
          commit(RECEIVE_TODOS, todos)
        }, 1000)
      }
    }
    View Code

    src/store/getters.js

    /**
     * Created by infaa on 2018/9/22.
     */
    export default {
      totalCount (state) {
        return state.todos.length
      },
      completeCount (state) {
        return state.todos.reduce((preTotal, todo) => {
          return preTotal + (todo.complete ? 1 : 0)
        }, 0)
      },
      isAllSelected (state, getters) {
        return getters.totalCount === getters.completeCount && state.todos.length > 0
      }
    }
    View Code

    src/store/index.js

    /**
     * Created by infaa on 2018/9/22.
     */
    import Vue from 'vue'
    import Vuex from 'vuex'
    import state from './state'
    import mutations from './mutations'
    import actions from './actions'
    import getters from './getters'
    
    Vue.use(Vuex)
    
    /* eslint-disable new-cap */
    
    export default new Vuex.Store({
      state,
      mutations,
      actions,
      getters
    })
    View Code

    src/store/mutation-types.js

    /**
     * Created by infaa on 2018/9/22.
     * mutation 名称常量
     */
    export const ADD_TODO = 'add_todo'
    export const DELETE_TODO = 'delete_todo'
    export const SELECT_ALL_TODOS = 'select_all_todos'
    export const CLEAR_ALL_COMPLETED = 'clear_all_completed'
    export const RECEIVE_TODOS = 'receive_todos' // 接收todos
    View Code

    src/store/mutation.js

    /**
     * Created by infaa on 2018/9/22.
     */
    import {ADD_TODO, DELETE_TODO, SELECT_ALL_TODOS, CLEAR_ALL_COMPLETED, RECEIVE_TODOS} from './mutation-types'
    export default {
      [ADD_TODO] (state, {todo}) {
        state.todos.unshift(todo)
      },
      [DELETE_TODO] (state, {index}) {
        state.todos.splice(index, 1)
      },
      [SELECT_ALL_TODOS] (state, {check}) {
        state.todos.forEach(todo => (todo.complete = check))
      },
      [CLEAR_ALL_COMPLETED] (state) {
        state.todos = state.todos.filter(todo => (!todo.complete))
      },
      [RECEIVE_TODOS] (state, todos) {
        state.todos = todos
      }
    }
    View Code

    src/store/state.js

    /**
     * Created by infaa on 2018/9/22.
     */
    export default {
      todos: []
    
    }
    View Code

    组件部分

    components/App.vue

    <template>
    <div class="todo-container">
        <div  class="todo-wrap">
          <TodoHeader></TodoHeader>
          <TodoList></TodoList>
          <TodoFooter></TodoFooter>
        </div>
      </div>
    </template>
    
    <script>
    import TodoHeader from './TodoHeader.vue'
    import TodoList from './TodoList.vue'
    import TodoFooter from './TodoFooter.vue'
    // import storageUtil from '../util/storageUtil.js'
    export default {
      mounted () {
        // 发送命令到acitong,模拟异步获取todos数据,由action处理
        this.$store.dispatch('reqTodos')
      },
      components: {
        TodoHeader,
        TodoList,
        TodoFooter
      }
    //  methods: {
    //
    //  },
    //  watch: {
    //    todos: {
    //      deep: true,
    //      handler: storageUtil.saveTodos
    //    }
    //
    //  }
    }
    </script>
    
    <style>
     .todo-container {
         600px;
        margin: 0 auto;
        }
        .todo-container .todo-wrap {
          padding: 10px;
          border: 1px solid #ddd;
          border-radius: 5px;
        }
    </style>
    View Code

    components/TodoFooter.vue

    <template>
          <div class="todo-footer">
            <label>
              <input type="checkbox" v-model="isAllChecked">
            </label>
            <span>
              <span>已完成{{completeCount}}</span>/全部{{totalCount}}
            </span>
            <button class="btn btn-danger" v-show="completeCount" @click="clearALLCompleted">清除已完成任务</button>
          </div>
    </template>
    
    <script>
    import {mapGetters, mapActions} from 'vuex'
    export default {
      computed: {
        ...mapGetters(['totalCount', 'completeCount', 'isAllSeleted']),
        isAllChecked: {
          get () {
            return this.$store.getters.isAllSelected
          },
          set (value) {
            this.$store.dispatch('selectAllTodos', value)
          }
        }
      },
      methods: {
        ...mapActions(['clearALLCompleted'])
      }
    
    }
    
    </script>
    
    <style>
      .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>
    View Code

    components/TodoHeader.vue

    <template>
          <div class="todo-header">
            <input type="text" placeholder="请输入你的任务名称,按回车键确认"
                   v-model="inputTodo" @keyup.enter="addItem">
          </div>
    </template>
    
    <script>
    export default {
      data () {
        return {
          inputTodo: ''
        }
      },
      methods: {
        addItem () {
          const title = this.inputTodo.trim()
          if (!title) {
            alert('title Kong')
            return
          }
          const todo = {
            title,
            complete: false
          }
          this.$store.dispatch('addTodo', todo)
          this.inputTodo = '' // 注意这里要操作this对象而不是函数内局部变量title
          // 验证合法性  生成对象  添加  还原
        }
      }
    }
    
    </script>
    
    <style>
      .todo-header input {
         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.75), 0 0 8px rgba(82, 168, 236, 0.5);
      }
    </style>
    View Code

    components/TodoItem.vue

    <template>
            <li :style="{background: bgColor}" @mouseenter="handleEnter(true)" @mouseleave="handleEnter(false)">
              <label>
                <input type="checkbox" v-model="todo.complete">
                <span>{{todo.title}}</span>
              </label>
              <button class="btn btn-danger" @click="deleteItem" v-show="isShow">删除</button>
            </li>
    </template>
    
    <script>
    export default {
      props: {
        todo: Object,
        index: Number
      },
      data () {
        return {
          isShow: false,
          bgColor: 'white'
        }
      },
      methods: {
        deleteItem () {
          const index = this.index
          const todo = this.todo
          if (window.confirm(`删除${todo.title}`)) {
            this.$store.dispatch('deleteTodo', index)
          }
        },
        handleEnter (isEnter) {
          if (isEnter) {
            this.isShow = true
            this.bgColor = 'grey'
          } else {
            this.isShow = false
            this.bgColor = 'white'
          }
        }
      }
    }
    
    </script>
    
    <style>
      /*item*/
      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>
    View Code

    components/TodoList.vue

    <template>
          <ul class="todo-main">
            <TodoItem v-for="(todo,index) in todos" :todo="todo" :key="index" :index="index"></TodoItem>
          </ul>
    </template>
    
    <script>
    import {mapState} from 'vuex'
    import TodoItem from './TodoItem.vue'
    import storeageUtil from '../util/storageUtil'
    export default {
      components: {
        TodoItem
      },
      computed: {
        ...mapState(['todos'])
      },
      watch: {
        todos: {
          deep: true,
          handler: storeageUtil.saveTodos
        }
      }
    }
    
    </script>
    
    <style>
      .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>
    View Code
  • 相关阅读:
    hihoCoder#1128 二分·二分查找
    hihoCoder#1127 二分图三·二分图最小点覆盖和最大独立集
    hihoCoder#1122 二分图二•二分图最大匹配之匈牙利算法
    hihoCoder#1105 题外话·堆
    Ajax详细剖析
    web框架之--Tornado
    web框架之--先来个介绍
    前端之--Jquery-玩穿它!
    前端之--DOM详解应用
    前端之--JavaScript作用域--超细讲解
  • 原文地址:https://www.cnblogs.com/infaaf/p/9691630.html
Copyright © 2020-2023  润新知