vue全家桶之---vuex的保姆级教程

vuex的学习目录

  • Vuex的概述
    • 组件之间共享数据的方式
    • Vuex是什么
    • 使用vuex统一管理状态的好处
  • Vuex的基本使用
    • 安装vuex包
    • 导入vuex包
    • 创建一个store对象
    • 将 store 对象挂载到vue实例对象中
    • 手把手教学创建一个vue项目并手动添加vuex
  • Vuex的核心概念
    • 核心概念的概述
    • State
    • Mutation
    • Action
    • Getter
    • Module
  • 基于Vuex的案例
    • 简易案例 count计数

Vuex的概述

组件之间共享数据的方式

父向子传值: v-bind 属性绑定

子向父传值: v-on 事件绑定

兄弟组件之间共享数据 EventBus

    $on 接收数据的那个组件

    $emit 发送数据的那个组件

Vuex是什么

Vuex是实现组件全局状态(数据)管理的一种机制,可以方便的实现组件之间数据的共享

为什么要使用vuex?

我们先来看看如果没有vuex,不同组件之间想要进行数据传递的过程:
vue全家桶之---vuex的保姆级教程_第1张图片

当组件A想要和组件B进行数据共享的时候,需要经过多条路径去和B进行数据同步

如果有vuex,不同组件之间想要进行数据传递的过程:

vue全家桶之---vuex的保姆级教程_第2张图片

有了vuex当“中间商”后,我们就能让组件和组件之间的数据传递变得简单起来

使用vuex统一管理状态的好处

1、 能够在vuex中集中管理共享的数据,易于开发和后期的维护
2、 能够高效的在组件间实现数据共享,提高开发效率
3、 存储在vuex中的数据都是响应式的,能够实时保持数据与页面的同步

什么情况下的数据适合储存到vuex中呢?

一般情况下,只有组件之间需要共享的数据才有必要存到vuex中,对于组件中的某些私有数据依旧存储在组件自身的data中就行了。

Vuex的基本使用

安装vuex包

终端输入命令:npm install vuex --save

导入vuex包

import Vuex from ‘vuex’

Vue.use(Vuex)

创建一个store对象

const store = new Vuex.Store({

       // state 中存放的就是全局共享的数据

       state: {count:0}

})

将 store 对象挂载到vue实例对象中

new Vue({

       el:’#app’,

       render: h => h(app),

       router,

       // 将创建的共享数据对象,挂载到vue实例中

       // 所有的组件就可以直接从store中获取全局数据了

       store

})

手把手教学创建一个vue项目并手动添加vuex

在cmd中输入vue create projectname

会出现如下选项

vue全家桶之---vuex的保姆级教程_第3张图片

我这里选择的是 [vue2]

  • 其实可以选择第三个选项手动添加

    需要选择如下依赖:babel、vuex、linter、use config files
    这四项,其他的根据项目需求自行添加
    (博主演示如何将vuex通过自己写配置文件的方式将vuex添加进去)
    

然后就会进入安装页面,静待安装,出现如下界面时表示安装完成:
vue全家桶之---vuex的保姆级教程_第4张图片

我们现在打开这个项目来看看它的目录结构:

vue全家桶之---vuex的保姆级教程_第5张图片

这里它告诉我们需要安装依赖然后启动项目,但是我们不急,先来分析一下目录结构
vue全家桶之---vuex的保姆级教程_第6张图片

我们按照前面的步骤来一步一步把vuex加入我们新建的项目中。

第一步先 npm install
vue全家桶之---vuex的保姆级教程_第7张图片

安装完成后输入 npm install vuex --save

在这里插入图片描述

(这里如果出现安装失败–报错timeout可以参考我的另一篇博客)

安装完成后,先写store对象:
vue全家桶之---vuex的保姆级教程_第8张图片

这里的store.js的创建目录是与main.js平级的,然后state里面是通过key-value的方法来储存全局可访问的变量的。

然后就将store挂载到入口文件main.js中
vue全家桶之---vuex的保姆级教程_第9张图片

将store挂载到注册的vue实例对象中 就能在后面的开发过程中使用到vuex了

Vuex的核心概念

核心概念的概述

  • State
  • Mutation
  • Action
  • Getter
  • Module

State

State提供唯一的公共数据源,所有共享的数据都要统一放到Store的State中进行储存。

示例:

const store = new.Vuex.Store({
       state:{ count : 0 }
})

这里的count就是全局共享的数据

组件访问state的第一种方式:this.$store.state.全局数据名称

组件访问state中数据的第二种方式:

  //从vuex中按需导入 mapState 函数

   import { mapState } from 'Vuex'

通过刚才导入的mapState函数,将当前组件所需要的全局数据,映射为当前组件的computed计算属性:

  // 将全局数据,映射为当前组件的计算属性

   computed:{
          ...mapState(['count'])
   }

Mutation

用于变更Store中的数据

1、 在vuex中,它推荐我们使用Mutation进行数据修改,而不建议我们直接使用methods来修改State里的数据。(其实就是不可以使用methods方法来改啦)
2、 通过这种方式操作起来虽然繁琐一点,但是可以集中监控所有的数据变化,(方便后期项目的上线和维护);

// 定义mutation

const store = new Vuex.Store({
	state : {
       count : 0
	},

	mutations : {
       add(state) {
       // 变更状态
       state.count++
		}
	}
})
// 触发mutation

methods : {
	handle1(){
	// 触发mutation 的第一种方式
	this.$store.commit(‘add’)
	}
}

如何在调用Mutation的时候去传递参数
可以触发mutations时传递参数:

// 定义 mutation
const store = new Vuex.Store({
    state:{
        count:0
	},
    mutations:{
        addN(state, step) {
            // 变更状态
            state.count += step
            }
    },
})

 
// 触发mutation

methods : {
	handle2() {
       // 在调用commit函数,触发mutations时携带参数
       this.$store.commit(‘addN’, 3)
	}
}

触发mutation的第二种方式

// 从vuex中按需导入 mapMutations 函数

import { mapMutations } from ‘vuex’

通过刚刚导入的mapMutations函数,将需要的mutations函数映射为当前组件的methods方法。

methods : {
       …mapMutations([‘add’,’addN’])
}

Action

Action用于处理异步任务
如果通过异步操作变更数据,必须通过Action,而不能使用Mutation,但是在Action中还是要通过触发Mutation的方式间接变更数据。

// 定义Action
conset store = New Vuex.Store({
	// 省略其他代码
	mutations:{
		add(state) {
		state.count++
		}
	},
	actions:{
		addAsync(context) {  // 这里的context 我们就可以认为是实例出来的vue对象
		// 在actions中不能直接修改state里的数据
		// 如果需要修改state里的数据,必须通过context.commit()触发某个mutation才行
			setTimeout(()=>{
			context.commit(‘add’)
			}, 1000)
		}
	}
})

//触发Action
methods : {
	handle() {
		// 触发 actions的第一种方式
		this.$store.dispatch(‘addAsync’)
	}
}

- 在实例中的使用方法和mutations类似
方法 2
<script>
import {mapActions} from 'vuex'

// 省略一部分
methods:{
	...mapActions(['addAsync']),
	function_name(){
		this.addAsync()
	}
}
</script>

触发actions异步任务时携带参数

// 定义Action
conset store = New Vuex.Store({
	// 省略其他代码
	mutations:{
		addN(state, step) {
		state.count += step
		}
	},
	actions:{
		addAsync(context, step) {  // 这里的context 我们就可以认为是实例出来的vue对象
		// 在actions中不能直接修改state里的数据
		// 如果需要修改state里的数据,必须通过context.commit()触发某个mutation才行
			setTimeout(()=>{
			context.commit('addN', step)
			}, 1000)
		}
	}
})

//触发Action
methods : {
	handle() {
		// 触发 actions的第一种方式
		this.$store.dispatch('addAsync', 5)
	}
}

Getter

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

  • Getter可以对Store中已有的数据加工处理之后形成新的数据,类似于vue的计算属性;
  • Store中数据发生变化,Getter的数据也会同步发生变化。

如何使用Getter

// 定义Getter
const store = new Vuex.Store({
	state:{
		count : 0
	},
	getters : {
		showNum: state => {
			return '当前count最新值为:' + state.count
		}
	}
})

// 使用getter的第一种方式
this.$store.getters.名称
// getter 的第二种使用方式
import { mapGetters } from 'Vuex'

computed:{
	...mapGetters(['showNum']) // 就可以在代码中直接使用了
}

Module

由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。

为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割
具体的使用这里比较容易理解,可以参考官方文档.进行学习。

基于Vuex的案例

简易案例 count计数

这个案例是用来熟悉Vuex的各项核心概念的
第一版:使用State 、 Mutations 、 Action 和 Getter
直接上代码图 + 贴代码
整体demo示意图:
vue全家桶之---vuex的保姆级教程_第10张图片
vue全家桶之---vuex的保姆级教程_第11张图片
demo代码汇总:

add.vue:state 和 mutation 的第一种使用方法

<template>
  <div>
    <p>当前最新的count值为:{{this.$store.state.count}}p>
    <p>{{this.$store.getters.showNum}}p>
    <button @click="add">+1button>
    <button @click="addN">+3button>
    <button @click="addAsync1">+1Asyncbutton>
    <button @click="addAsync2">+3Asyncbutton>
  div>
template>

<script>
export default {
  data(){
    return {}
  },
  methods:{
    add(){
      // 触发mutation 的第一种方式
      this.$store.commit('add')
    },
    addN(){
      this.$store.commit('addN', 3)
    },
    addAsync1(){
      this.$store.dispatch('addAsync')
    },
    addAsync2(){
      this.$store.dispatch('addNAsync', 3)
    }
  }
}
script>

<style scoped>

style>

subt.vue :state 和 mutation 的第二种使用方法

<template>
  <div>
    <p>当前最新的count值为:{{ count }}p>
    <p> {{ showNum }} p>
    <button @click="sub">-1button>
    <button @click="subN">-3button>
    <button @click="subAsync1">-1Asyncbutton>
    <button @click="subAsync2">-3Asyncbutton>
  div>
template>

<script>
import { mapState,mapMutations,mapActions, mapGetters } from 'vuex'

export default {
  name: "subt",
  data(){
    return {}
  },
  methods:{
    ...mapMutations(['minus', 'minusN']),
    sub(){
      this.minus()
    },
    subN(){
      this.minusN(3)
    },
    ...mapActions(['subAsync', 'subNAsync']),
    //映射过来其实就是可以直接调用的函数可以直接作为调用函数
    subAsync1() {
      this.subAsync()
    },
    subAsync2() {
      this.subNAsync(3)
    }

  },
  computed:{
    ...mapState(['count']),// 这三个点代表是展开计算符
    ...mapGetters(['showNum'])
  }
}
script>

<style scoped>

style>

store.js (这里是vuex的配置文件)

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


Vue.use(Vuex)
export default new Vuex.Store({
    state:{
        count:0
    },
    mutations:{
        add(state) {
            // 不要再mutations 函数中执行异步操作 比如:
            // setTimeout(() => {
            //     state.count++
            // },1000)
            // 变更状态
            state.count++
        },
        addN(state, step) {
            state.count += step
        },
        minus(state) {
            state.count--
        },
        minusN(state, step) {
            state.count -= step
        }
    },
    actions:{
        addAsync(context) {
            setTimeout(()=>{
                context.commit('add')
            }, 1000)
        },
        addNAsync(context,step){
            setTimeout(()=>{
                context.commit('addN', step)
            }, 1000)
        },
        subAsync(context) {
            setTimeout(()=>{
                context.commit('minus')
            }, 1000)
        },
        subNAsync(context,step){
            setTimeout(()=>{
                context.commit('minusN', step)
            }, 1000)
        }
    },
    getters:{
        showNum(state) {
            return '当前count最新值为:' + state.count
        }
    }
})

App.vue

<template>
  <div id="app">
    <my-add>my-add>
    <p>----------------------------p>
    <my-subt>my-subt>
  div>
template>

<script>
import add from './components/add.vue'
import subt from './components/subt.vue'

export default {
  name: 'App',
  components: {
    'my-add':add,
    'my-subt': subt
  }
}
script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
style>

你可能感兴趣的:(项目学习,vue.js,vue-cli3,javascript,node.js)