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>

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

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

工具部分

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) || ‘[]‘)
  }
}

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

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

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

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

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

src/store/state.js

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

}

组件部分

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 {
    width: 600px;
    margin: 0 auto;
    }
    .todo-container .todo-wrap {
      padding: 10px;
      border: 1px solid #ddd;
      border-radius: 5px;
    }
</style>

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>

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 {
    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.75), 0 0 8px rgba(82, 168, 236, 0.5);
  }
</style>

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>

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>

原文地址:https://www.cnblogs.com/infaaf/p/9691630.html

时间: 2024-10-16 21:37:10

vue part5.2 vuex todolist 改写的相关文章

学习vue必备技能vuex

首先我们先用vue-cli搭建项目,安装vuex,安装依赖(这里不一一讲解),然后在src下建立/vuex/store.js,里面代码截图 最简单的引入vue,引入vuex,定义两个对象,一个state(数据状态),一个mutations(改变数据方法),最后export,因为我们别的地方要用 ,比较简单的一个实例,也是比较经典的实例,点击加减改变state里面的值, 红色部分是比较麻烦一点的写法,但是比较容易理解,下面inport之后,我们直接在页面上显示和这个{{  }}类似, 然后comm

Vue状态管理vuex

转: https://www.cnblogs.com/xiaohuochai/p/7554127.html 前面的话 由于多个状态分散的跨越在许多组件和交互间各个角落,大型应用复杂度也经常逐渐增长.为了解决这个问题,Vue提供了vuex.本文将详细介绍Vue状态管理vuex 引入 当访问数据对象时,一个 Vue 实例只是简单的代理访问.所以,如果有一处需要被多个实例间共享的状态,可以简单地通过维护一份数据来实现共享 const sourceOfTruth = {} const vmA = new

Vue学习日记(四)——Vue状态管理vuex

前言 先说句前话,如果不是接触大型项目,不需要有多个子页面,不使用vuex也是完全可以的. 说实在话,我在阅读vuex文档的时候,也很难以去理解vuex,甚至觉得没有使用它我也可以.但是直到我在项目碰到下面这些问题: 当路由切换的时候,原本路由的数据太多,传递过去太麻烦. 有些数据是多个路由需要用到的,那我就需要从后台获取多次数据 当然,这些问题都可以解决,就是在实例化vue对象的时候,就将这些数据绑定在window对象上面.但是我们也不得不设想: 万一数据太多了,那么可阅读性是不是会下降 如果

vue part5 vuex

https://vuex.vuejs.org/zh-cn state --> view --> action -> state 多组件共享状态, 之前操作方式,由父组件传递到各个子组件. 当路由等加入后,会变得复杂. 引入viewx 解决共享问题. 安装 npm install --save vuex 代码1  :原vue实现计数器 app.uve <template> <div> <p>点击次数{{count}}, 奇偶数:{{eventOrOdd}

Vue入门之Vuex实战

引言 Vue组件化做的确实非常彻底,它独有的vue单文件组件也是做的非常有特色.组件化的同时带来的是:组件之间的数据共享和通信的难题. 尤其Vue组件设计的就是,父组件通过子组件的prop进行传递数据,而且数据传递是单向的.也就是说:父组件可以把数据传递给子组件,但是 反之则不同.如下图所示: 单向数据流动 单方向的数据流动带来了非常简洁和清晰的数据流,纯展示性或者独立性较强的模块的开发确实非常方便和省事. 但是复杂的页面逻辑,组件之间的数据共享处理就会需要通过事件总线的方式解决或者使用Vue的

Vue初体验——用Vue实现简易版TodoList

最近在学习Vue,断断续续看完了官方教程的基础部分,想练一下手熟悉一下基本用法,做了一个简易版的TodoList 效果: 代码: HTML: 1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <title>TodoList</title> 6 <meta charset="utf-8"> 7 <!-- 为了让 Bootstrap 开发的网站对移动设备友好,确保适当的绘制和触屏缩放

vue学习 之 vuex安装及使用

1.安装  vuex npm install vuex --save 2.为什么使用vuex vue 包括  data()状态:template(视图):methods(方法).一个简单的单项数据流概念 但是当我们的应用遇到多个组件共享状态时.单项数据流 容易 破坏. 3. 使用vuex 再main.js 中注入 vuex import Vuex from 'vuex' Vue.use(Vuex) 在src 下创建文件夹store:创建store.js import Vue from 'vue'

初识Vue,简单的todolist

vue开发源码:https://vuejs.org/js/vue.js todolist代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>vue入门</title> <script src="vue.js" type="text/javascript"

Vue学习之VueX

单向数据流概念 Vuex介绍 解决问题 多个视图依赖于同一状态(菜单导航) 来自不同视图的行为需要变更为同意状态(例如:评论弹幕) Vuex应运而生 为vue.js开发的状态管理模式 组件状态集中管理 组件状态改变遵循统一的规则 store.js { //组件的状态 state: { }, //改变状态的方法集 mutations: { }, actions: { } } 参考https://www.imooc.com/video/18564 原文地址:https://www.cnblogs.c