vuex入门到实战——实现一个todoList待办清单【学习记录】

文章目录

  • 前言
  • 一、Vuex是什么?
      • Vuex核心概念
      • 1. State
      • 2. Mutations
      • 3.Actions
      • 4.Getters
  • 二、todoList待办清单
    • 1.初始化项目-基于已有样式模版实现Todos基本布局
    • 2.使用axios获取数据
    • 3.添加列表事项
    • 4.删除列表事项
    • 5.选中标记已完成
    • 6.显示待完成条数
    • 7.切换tabs显示不同内容
    • 8.清除已完成
  • 总结


前言

本文将从Vuex的核心概念出发,通过讲解一个待办清单的小项目,帮助大家更好的理解Vuex。此文主要是根据近日学习的关于Vuex的内容,整理出的学习笔记,用来巩固与记录。欢迎大家交流与讨论!

主要参考视频为黑马程序员的“Vue全家桶-Vuex” 原视频地址
https://www.bilibili.com/video/BV1h7411N7bg?from=search&seid=5930582975536399924&spm_id_from=333.337.0.0
若有侵权,请邮箱联系[email protected] 联系,我会及时删除。敬礼!


一、Vuex是什么?

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式 +
库。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
参考教程:https://vuex.vuejs.org/zh/

那么什么是状态管理模式呢?在一般情况下,我们的vue应用在渲染数据时,是一个单项数据流的过程,驱动的数据源为状态,状态会以声明方式映射到视图,用户通过在视图上操作又会导致状态变化。如图所示:
vuex入门到实战——实现一个todoList待办清单【学习记录】_第1张图片

我们多个视图依赖同一状态(数据)、或不同的视图需要变更同一状态(数据)时,若没有一个统一的状态管理器,但是又需要实现数据共享时,过程就会变得麻烦。按照传统方式,我们是可以通过各个组件传参来达成数据共享,但若项目变大,传参的过程就会变得相当繁琐,且后期维护的成本也很高。
所以Vuex作为一个状态管理器,可以把不同组件的共享状态抽离出来,集中管理便于后期维护,并利用vuex的响应式的特点从而实现高效进行状态更新。

Vuex核心概念

在安装好vuex之后,将出现store文件夹,里面有index.js的文件,代码如下:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

下面将一一介绍Store的核心。

1. State

State为Vuex的公共状态,提供唯一的数据源,用来存储公共的数据。

  • 例如我们将要实现todoList的列表事项就可以作为公共数据放在state中。

代码如下:

 state: {
    // 所有的任务列表
    list: [],
  },

当我们要访问存放在State里面的数据可通过以下两种方式:

  • 组件访问State中数据的第一种方式:
    this.$stroe.state.全局数据名称
    
  • 组件访问State中数据的第二种方式:
    //1. 从vuex中按需导入 mapState 函数
    import { mapState } from 'vuex'
    
    //2. 通过 mapState 函数,将当前组件需要的全局数据映射为当前组件
    computed: {
    ...mapState(['list']),
    },
    

2. Mutations

Mutations用于变更Store中的数据。

  • 只能通过mutations变更Store数据,不可以直接操作Store中的数据。

假设要实现一个点击自增的功能,首先需要在Store中定义Mutations代码如下:

 export default new Vuex.Store({
  state: {
  	count: 0
  },
  mutations: {
    //加1
  	add(state){
  	  //变更状态
  	  state.count++
  	}
  	//携带参数,加n
  	addN(state,n){
  	  //变更状态
  	  state.count += n
  	}
  },
})

触发mutations需通过以下两种方式:

  • 触发mutations的第一种方式:
    methods: {
      handle() {
        this.$store.commit('add')
      }
    }
    //携带参数
    methods: {
      handle1() {
        this.$store.commit('addN',n)
      }
    }
    
  • 触发mutations的第二种方式:
    //1. 从vuex中按需导入 mapMutations 函数
    import { mapMutations } from 'vuex'
    
    //2. 将指定的 mutations 函数,映射为当前组件的methods方法
    methods: {
      ...mapMutations(['add']),
       handle(){
        this.add()
      },
      //携带参数
      handle1(){
        this.addN(5)
      }
    },
    

3.Actions

Actions用于处理异步任务

  • 如果通过异步操作变更数据,必须通过Actions,而不能使用Mutations
  • Actions中还是要通过触发Mutations方式变更数据

假设要实现一个延时添加的功能,在Store中定义actions代码如下:

 export default new Vuex.Store({
  state: {
  	count: 0
  },
  mutations: {
  	add(state){
  	  //变更状态
  	  state.count++
  	}
  },
  actions: {
  	 addAsync(context) {
      //异步动作,如延时添加
      setTimeout(() => {
        context.commit('add')
      }, 1000)
    }
  },
})

触发actions可通过以下两种方式:

  • 触发actions的第一种方式:
    methods: {
      handle() {
    	this.$store.dispatch('addAsync')
      }
    }
    
  • 触发actions的第二种方式:
    //1. 从vuex中按需导入 mapActions 函数
    import { mapAction } from 'vuex'
    
    //2. 将指定的 mutations 函数,映射为当前组件的methods方法
    methods: {
    ...mapActions(['addAsync']),
    },
    

4.Getters

Getters用于对Store中的数据进行加工处理形成新的数据。

  • Getter可以对Store中的数据进行加工处理形成新的数据,类似Vue的计算属性
  • Store中数据发生变化,Getters的数据也会发生变化

在Store中定义Getter代码如下:

 export default new Vuex.Store({
  state: {
  	count: 0
  },
   getters: {
    showNum(state) {
      return '当前最新的数量是【' + state.count + '】'
    },
    }
  },
})

使用getters可通过以下两种方式:

  • 使用getters的第一种方式:
    this.$store.getters.名称
    
  • 使用getters的第二种方式:
    //1. 从vuex中按需导入 mapActions 函数
    import { mapGetters } from 'vuex'
    
    //2. 将指定的 mutations 函数,映射为当前组件的methods方法
    computed: {
    ...mapGetters(['showNum']),
    },
    

(携带参数)

二、todoList待办清单

源码:https://gitee.com/wx_f6a2d8acc5/vuex-to-do-list.git

1.初始化项目-基于已有样式模版实现Todos基本布局

vuex入门到实战——实现一个todoList待办清单【学习记录】_第2张图片

我们的待办清单基本布局与功能点如上图所示

html代码如下:

<template>
  <div id="app">
    <a-input
      placeholder="请输入任务"
      class="my_ipt"
      :value="inputValue"
      @change="handleInputChange"
    />
    <a-button type="primary" @click="addItemToList">添加事项a-button>
    
    <a-list bordered :dataSource="list" class="dt_list">
      <a-list-item slot="renderItem" slot-scope="item">
        
        <a-checkbox
          :checked="item.done"
          @change="cbStatusChanged($event, item.id)"
          >{{ item.info }}a-checkbox
        >
        
        <a slot="actions" @click="removeItemById(item.id)">删除a>
      a-list-item>

      
      <div class="footer" slot="footer">
        <span>{{ unDoneLength }}条剩余span>
        <a-button-group>
          <a-button
            :type="viewKey === 'all' ? 'primary' : 'default'"
            @click="changeList('all')"
            >全部a-button
          >
          <a-button
            :type="viewKey === 'undone' ? 'primary' : 'default'"
            @click="changeList('undone')"
            >未完成a-button
          >
          <a-button
            :type="viewKey === 'done' ? 'primary' : 'default'"
            @click="changeList('done')"
            >已完成a-button
          >
        a-button-group>
        <a @click="clean">清除已完成a>
      div>
    a-list>
  div>
template>

下面将按功能点分别介绍实现思路

2.使用axios获取数据

前端模拟数据可把list列表数据单独存放在一个json文件里,利用axios获取

字段释义:

  • id 待办清单项id
  • info 待办清单项内容
  • done 是否已完成(true为已完成,false为未完成)

list.json 代码如下:

[
  {
    "id": 0,
    "info": "Racing car sprays burning fuel into crowd.",
    "done": false
  },
  {
    "id": 1,
    "info": "Japanese princess to wed commoner.",
    "done": false
  },
  {
    "id": 2,
    "info": "Australian walks 100km after outback crash.",
    "done": true
  },
  {
    "id": 3,
    "info": "Man charged over missing wedding girl.",
    "done": false
  },
  {
    "id": 4,
    "info": "Los Angeles bat∏tles huge wildfires.",
    "done": false
  }
]

在store/index.js 中,首先在state中定义数据

state: {
    // 所有的任务列表
    list: [],
  },

在页面初始化时获取数据

created() {
    // 1、App.vue 页面初始化时调用vuex中的action 异步获取数据
    this.$store.dispatch('getList')
  },

Actions异步获取本地数据

actions: {
    // 2、在action中 异步获取数据,并把数据提交给mutations中initList函数处理梳理
    getList(context) {
      axios.get('/list.json').then(({ data }) => {
        console.log(data)
        context.commit('initList', data)
      })
    },
    addAsync(context) {
      // 异步动作,如延时添加
      setTimeout(() => {
        context.commit('add')
      }, 1000)
    }
  },

Actions在mutation中对state数据进行赋值

mutations: {
    // 3、在mutation中对state数据进行赋值
    initList(state, list) {
      state.list = list
    },

App.vue 中Actions在mutation中对state数据进行赋值

// 4、使用store的计算属性,把store中存储的数据映射过来
  computed: {
    ...mapState(['list']),
  },

3.添加列表事项

实现思路:

  • 首先监听输入框内容,实时传给vuex
  • vuex中mutations设置函数,实时获取到文本框输入的内容
  • 点击添加,传给对应的mutations中的添加函数
  • 在vuex的mutations的添加函数中,把列表项(一个对象)添加到state存储的数据中

App.vue 代码如下:

methods: {
    // 监听文本
    handleInputChange(e) {
      console.log(e.target.value)
      this.$store.commit('setInputValue', e.target.value)
    },
    // 向列表中增加Item项
    addItemToList() {
      if (this.inputValue.trim().length <= 0) {
        return this.$message.warning('输入内容不能为空')
      } else {
        this.$store.commit('addItem')
      }
    },

store/index.js 代码如下:

state: {
    // 所有的任务列表
    list: [],
    // 文本框内容
    inputValue: '',
    //id
    nextId: 5,
  },
  mutations: {
    // 为store中的inputValue赋值
    setInputValue(state, val) {
      state.inputValue = val
    },
    addItem(state) {
      const obj = {
        id: state.nextId,
        info: state.inputValue.trim(),
        done: false
      }
      state.list.push(obj)
      state.nextId++
      state.inputValue = ''
    },
  },

4.删除列表事项

实现思路:

  • 首先获取到删除的id
  • 点击删除,把对应的id传给对应的mutations中的删除函数
  • 在vuex的mutations的删除函数中,筛选出对应id的对象,进行删除

App.vue 代码如下:

methods: {
    // 根据id进行删除
    removeItemById(id) {
      this.$store.commit('removeItem', id)
    },
  },

store/index.js 代码如下:

  mutations: {
    removeItem(state, id) {
      const i = state.list.findIndex((x) => x.id === id)
      if (i !== -1) {
        state.list.splice(i, 1)
      }
    },
  },

5.选中标记已完成

实现思路:

  • 利用组件的change属性,当列表选项选中状态改变时获取id以及当前选中状态
  • 传给对应的mutations函数
  • 在vuex的mutations的改变选中状态函数中,根据id找到列表项并更改选中状态

App.vue 代码如下:

   cbStatusChanged(e, id) {
      const param = {
        id: id,
        status: e.target.checked
      }
      this.$store.commit('changeStatus', param)
    },

store/index.js 代码如下:

  mutations: {
    changeStatus(state, param) {
      const i = state.list.findIndex((x) => x.id === param.id)
      state.list[i].done = param.status
    },
  },

6.显示待完成条数

实现思路:

  • 对已有list列表进行筛选
  • 筛选出状态等于false的列表项

store/index.js 代码如下:

 getters: {
    unDoneLength(state) {
      return state.list.filter((x) => x.done === false).length
    },
  },

7.切换tabs显示不同内容

实现思路:

  • 切换tabs时首先tabs对应按钮的选中状态会改变,另外列表内容也会改变
  • 给所有tabs(3个btn)绑定事件,当按钮点击时获取到当前选中的按钮内容,传给vuex
  • vuex中state记录当前选中的按钮内容(全部、已完成、未完成)viewKey
  • 根据viewKey的变化,同步更改所有按钮type值,并设置组件选中样式(当然也有更方便的组件,不需要我们自己写)
  • 根据viewKey的变化,更新列表的数据源,这里用Getters处理

App.vue 代码如下:

 changeList(key) {
      this.$store.commit('changeList', key)
    }

store/index.js 代码如下:

  mutations: {
    changeList(state, key) {
      state.viewKey = key
    }
  },

html代码如下:

    <a-button-group>
          <a-button
            :type="viewKey === 'all' ? 'primary' : 'default'"
            @click="changeList('all')"
            >全部a-button
          >
          <a-button
            :type="viewKey === 'undone' ? 'primary' : 'default'"
            @click="changeList('undone')"
            >未完成a-button
          >
          <a-button
            :type="viewKey === 'done' ? 'primary' : 'default'"
            @click="changeList('done')"
            >已完成a-button
          >
        a-button-group>

store/index.js 代码如下:

getters: {
    infoList(state) {
      if (state.viewKey === 'all') {
        return state.list
      }
      if (state.viewKey === 'undone') {
        return state.list.filter((x) => x.done === false)
      }
      if (state.viewKey === 'done') {
        return state.list.filter((x) => x.done === true)
      }
      return state.list
    }
  },

8.清除已完成

实现思路:

  • 点击删除,删选出未完成的列表项

App.vue 代码如下:

methods: {
     clean() {
      this.$store.commit('clean')
    },
  },

store/index.js 代码如下:

  mutations: {
   clean(state) {
      state.list = state.list.filter((x) => x.done === false)
    },
  },

总结

以上就是关于vuex的入门内容,本文仅仅简单介绍了vuex一些核心概念以及一个todoList待办清单的小例子!欢迎点赞评论收藏,一起学习一起进步!

你可能感兴趣的:(学习,vue.js,前端)