Vuex实战讲解(全),玩转Vue必备知识__Vue.js__前端
发布于 2 年前 作者 banyungong 1082 次浏览 来自 分享
粉丝福利 : 关注VUE中文社区公众号,回复视频领取粉丝福利

theme: cyanosis

Vuex概况

store核心概念

1.- State:  包含了store中存储的各个状态。

2.- Getters:  类似于 Vue 中的计算属性,根据其他 getter 或 state 计算返回值。

3.- Mutation: 一组方法,是改变store中状态的执行者,只能是同步操作。

4.- Action:  一组方法,其中可以包含异步操作。

5.- Moudule:  Module是store分割的模块,每个模块拥有自己的state、getters、mutations、actions。

vuex辅助函数

在Vuex中获取数据的辅助函数有两个mapState、mapGetters,

操作Mutation和acitonhas函数mapMutations、mapActions

前两个用在computed(计算属性中)

后两个用在methods(方法中)

如何使用

多个组件共享同一个状态(数据)

1.安装vuex

新建store文件夹===>index.js

main.js中,导入store对象,并且放在new Vue中 就可以通过this.$store的方式获取到这个store对象

2.使用vuex中的count(state中定义的共享状态)

this.$store.state.count

3.不能直接修改store中的状态,直接修改devtools监听不到数据的修改

4.mutations 负责同步修改状态

Vuex的store修改状态唯一的方式:提交mutations–>(this.$store.commit(‘add’))

Getters Store中的计算属性

     // 计算数字的平方
    quadratic(state) {
      // 第一个参数,状态state
      return state.count * state.count
    }

2.筛选数据

  filterInfo(state) {
        return state.info.filter(res =>{
          return res.age>18
        })
  }
  • 获取数据
 info:this.$store.getters.filterInfo

3.如果想要获取符合条件的个数

  • {{$store.getters.filterInfo.length}}

4.如果不想年龄晒选写死,想自己输入年龄,只需要在getters里写一个方法

// 筛选数据
    filterInfo(state, age) {
      //要返回一个方法才可以传值
      //age返回的不是一个确定的值,而是一个函数
      // 1.
      // return function(age){
      //   return state.info.filter(res =>{
      //     return res.age>age
      //   })
      // }
      // 2.
      return (age) => {//return后才可以传递参数
        return state.info.filter(res => res.age > age)
      }

5.getters中的两个参数

// 第一个state,拿数据,第二个参数geters:也就是说可以从getters中调用上面平方根的方法
testGettes(state,getters){
  return getters.quadratic
}

vuex辅助函数

辅助函数

mapState, 用于将state中的数据映射到组件的计算属性中

		<!-- 第一种 -->
		
		<!-- 
		    组件中的计算属性名称,和vuex状态名称不一致的时候,可以使用对象写法
		 -->
		computed:mapState({ 
			cnum:"count",
		})
		<!-- 第二种 -->
		<!-- 
			字符串数组写法,
			组件中计算属性名,和vuex中状态名一致的时候
		 -->
		 computed:mapState([
			"count",
		 ])
		 <!-- 第三种 -->
		 <!-- 
			当组件有自己的计算属性的时候,我们可以使用结构写法,将辅助函数合并到计算属性中
		 -->
		 
		 computed:{
			...mapState({
				cnum:"count",
			 })
		 }

mapGetters 用于将getter中的计算属性映射到组件的计算属性中用法同mapState

		computed:{
			// 对象展开符,解构mapGetters
			...mapGetters({
				// 将store中的getters的filterInfo,映射到组件上的info计算属性上
				info:"filterInfo"
			}),
			
			...mapGetters([ //字符串数组
				"getInfoLength"
			])
		}
		
	mapMutations : 用于将mutations映射到methods中
	...mapMutations([
		"add"
	]),
	// 对象写法
	...mapMutations({
		// 同步,通过commit触发mutations
		myadd:"add",
		// 方法名:mutation函数名
		addtwo:"addParms"
	}),

	mapActions :于将actions映射到methods中
	...mapActions({
		// 方法名:mutation函数名
		myasync:"asyncAdd"
	})

Vuex中的核心 — modules

当项目比较大的时候,如果只有一个模块来维护数据,那么这个模块会非常的大,对于维护性来说,不是特别高,所以vuex中,提供模块功能,我们可以通过modules将vuex处理为多个模块

const myCount={
	state:{
		user:{
		  name:'admin',
		  pass:'12345'
		},
		count:10
	},
	getters:{
		
	},
	mutations:{
		// 模块的同步中是没有第三参数,(根状态)
		cAdd(state,paylaod){
			console.log(this)
			state.count++
		}
	},
	actions:{
		
	}
}

export default new Vuex.Store({
  state:{
	  num:2
  },
  modules: { // 模块选项
	 // 引用myuser模块
	  u:myUser,
	  c:myCount, 
	  cat
	
  }
})

使用模块的属性

$store.state.模块名称.属性名
$store.getters.模块名称.属性名

$store.commit('方法名称')//同步提交
$store.dispatch('方法名称') //异步提交

实战解析

上面概念说完了,该实战练习了,动起来!

State,Mutations

store下的index.js

import Vue from 'vue'
import Vuex from 'vuex'
// 安装插件
Vue.use(Vuex)

export default new Vuex.Store({
  state: {//存储状态
    // 自定义共享状态
    count:0,
    stu:[
      {id:1001,name:123},
      {id:1003,name:'符鼠'},
      {id:1004,name:'追梦'},
    ],
    user:{
      name:'随便',
      sex:'随机'
    }
  },
  // vuex中的store状态更新的唯一方式是提交Mutation
  mutations: {//写方法,通过mutations修改、页面的插件才能监听到
    add(state){//方法的第一个参数就是state,也就是state的对象
      // this是store对象
      state.count++
    },
  //state(store中的state),(Payload:提交方法携带的参数)
    addTen(state,ten){//点击加10
      state.count += ten
    },
    addTwo(state,obj){//点击加2,加obj才能接收对象
      state.count += obj.two
    },
    // 向stu数组中添加一条数据
    addStu(state,payload){
      state.stu.push(payload)//向数组中添加数据
    },
    updUser(state,age){//给stu对象添加新属性
      // state.user.age='18'不能写等号
      // state.user = {...state.user,'age':12}
      Vue.set(state.user,'age',123)
    }
  },  
  actions: {},
  modules: {}
})

Aone组件

<template>
  <div class="hello">
    <h1>aone组件</h1>
    <h2>{{$store.state.count}}</h2>
    <li>{{$store.state.stu}}</li>

    <button @click="addTen">+10</button>
    <button @click="addStu">添加成员</button>
  </div>
</template>
<script>
export default {
  name: 'aone',
  props: {
    msg: String,
    count:Number
  },
  data() {
    return {
      stu:{id:1005,name:'测试'}
    }
  },
  methods: {
    addTen(){
      // 触发mutations函数,指定额外参数,字符串方式提交
      this.$store.commit('addTen',10)  
    },
    addStu(){
      this.$store.commit('addStu',this.stu)
    }
  },
}
</script>

hello组件

<template>
  <div class="hello">
    <h1>helloworld组件</h1>

    <h2>{{$store.state.count}}</h2>
    <h2>{{$store.state.user}}</h2>
    <button @click="addTwo">点击加2</button>
    <button @click="updUser">修改</button>
  </div>
</template>
<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String,
    count:Number
  },
  methods: {
    addTwo(){
      // 触发mutations函数,指定额外参数,对象形式提交
      this.$store.commit({
        type:'addTwo',
        two:2
      })  
    },
    updUser(){
      // 触发mutations函数,指定额外参数
      this.$store.commit({
        type:'updUser' })
    }
  },
}
</script>

Actions,Getters

store下的index.js

import Vue from 'vue'
import Vuex from 'vuex'
// 安装插件
Vue.use(Vuex)
// 实例化vuex并导出
export default new Vuex.Store({
  state: {
    count: 0,
    info: [
      {
        di: 1, name: '开发者1', age: 21
      },
      {
        di: 2, name: '开发者2', age: 22
      },
      {
        di: 3, name: '开发者3', age: 23
      },
    ]
  },
  // 只能通过mutations更改数据
  mutations: {//如果mutation是一个异步函数,那么devtools不能跟踪数据变化
    // mutations负责同步修改状态
    increment(state, payload) {
      //   setTimeout(()=>{
      state.count += payload
      //   },2000)
    }
  },
  // 专写异步actions
  actions: {//context上下文对象
    asyncIcrement(context, payload) {
      setTimeout(() => {
        context.commit('increment', payload)
      }, 2000)
    }
  },
  getters: {//store的计算属性
    // 计算数字的平方
    quadratic(state) {
      // 第一个参数,状态state
      return state.count * state.count
    },
    // 筛选数据
    filterInfo(state, age) {
      //要返回一个方法才可以传值
      //age返回的不是一个确定的值,而是一个函数
      // return function(age){
      //   return state.info.filter(res =>{
      //     return res.age>age
      //   })
      // }

      return (age) => {//return后才可以传递参数
        return state.info.filter(res => res.age > age)
      }

    },
    testGettes(state,getters){
      // 调用上面平方根的方法
      return getters.quadratic
    }

  },
  modules: {

  }
})

myvux组件

<template>
  <div id="main">
    <h2>这是myvue组件</h2>
    <h3>{{$store.state.count}}</h3>
    <button @click="add">+1</button>
    <button @click="asyAdd">异步+1</button>
    <h2>获取年龄小于22的开发</h2>
  </div>
</template>
<script>
export default {
  methods: {
    add(){
      this.$store.commit('increment',5)
    },
    asyAdd(){
      // 触发actions异步并传参
      this.$store.dispatch('asyncIcrement',10)
    }
  },
}
</script>

myhome组件

<template>
  <div id="home">
    <h2>这是home组件</h2>
    <h3>{{$store.state.count}}</h3>

    <h3>平方:{{$store.getters.quadratic}}</h3>
    <!-- 通过getters来筛选数据 -->
    <div>
      <h3>获取大于22的</h3> 
      <li v-for="itme in info">
        {{itme}}
      </li>
        <!-- {{$store.getters.filterInfo.length}} -->
        //调用上面函数
        <h5>{{$store.getters.testGettes}}</h5>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      info:this.$store.getters.filterInfo(22)
    }
  },
}
</script>

辅助函数及Modules

store下的index.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
  state: {
    count:0,
    user:{
      name:'admin',
      pass:'123'
    },
    info: [
      {
        di: 1, name: '开发者1', age: 21
      },
      {
        di: 2, name: '开发者2', age: 22
      },
    ]
  },
  getters:{
    filterInfo(state){
      // 过滤大于20的数据
      return state.info.filter(info=>info.age>22)
    },
    getInfoLeng(state,getter){
      return getter.filterInfo.length
    }
  },
  mutations: {
    add(state){
      this.count ++
    },
    addParms(state,num){
      this.count += num
    }
  },
  actions: {
    //异步
    asyncAdd(context){
      setTimeout(()=>{
        context.commit('add')
      },2000)
    }
  },
  modules: {
  }
})

Mystate组件(mapstate对应state)

<template>
  <div id="mystate">
    <!-- 使用vuex中的count -->
    <p>数字:{{ $store.state.count }}</p>
    <!-- <p>数字data:{{num}}</p> -->
    <!-- <p>计算属性中的数字:{{cnum}}</p> -->
    <!-- vuex中的数据 -->
    <!-- <p>mapstate:{{count}}</p>
    <p>mapstate:{{user}}</p> -->

    <p>cuser:{{ cuser }}</p>
    <p>cuser:{{ csuser }}</p>
    <p>cnum:{{ cnum }}</p>

    <p>组件自己的计算属性:{{ cPrice }}</p>
  </div>
</template>

<script>
import {mapState} from 'vuex'
// console.log(mapState);
 export default {
  data() {
    return {
      // 在data中定义不是响应式
      num:this.$store.state.count,
      price:10
    }
  },
  // 计算属性
  // computed:{
  //   cnum(){
  //     return this.$store.state.count
  //   }
  // }
  // 通过mapState辅助函数,帮我们自动生成计算属性
  // computed:mapState([//字符串数组写法
  // // 属性名和vuex状态名相同可以使用数组的形式写
  //   'count',//将vuex中状态count映射到计算属性中
  //   'user'
  // ])

  // 以对象形式使用
  // computed:mapState({
  //   cuser(state){
  //     // 通过计算属性的第一个函数,是vuex中的状态state,所以可以通过state直接获取数据
  //     return state.user//this.$store.user
  //   },
  //   // 简写方式
  //   csuser:state => state.user,
  //   // 等价于tate => state.count
  //   cnum:'count'
  // })

  computed:{
    //组件自己的计算属性
    cPrice(){
      return '$'+this.price
    },
    //通过mapState映射过来的计算属性
    ...mapState({
    cuser(state){
      // 通过计算属性的第一个函数,是vuex中的状态state,所以可以通过state直接获取数据
      return state.user//this.$store.user
    },
    // 简写方式
    csuser:state => state.user,
    // 等价于tate => state.count
    cnum:'count'
  })
  }
}
</script>

Mygetter组件(mapgetters对应getters)

<template>
  <div id="mygetter">
    <h3>mapgetter用法</h3>
    <p>直接使用getters:{{$store.getters.filterInfo}}</p>
    <p>mapgetters:{{info}}</p>
    <p>获取长度(info):{{getInfoLeng}}</p>
  </div>
</template>
<script>
// 获取辅助函数
import { mapGetters, mapState } from "vuex";
// console.log(mapState);
export default {
  computed: {
    // 对象展开符解构mapgetters
    ...mapGetters({//对象写法
      // 将store中的getters的filterInfo映射到组件上的info计算属性上
      info:'filterInfo'
    }),
    ...mapGetters([//字符串数组写法
      'getInfoLeng'
    ])
  },
};
</script>

mymutations组件(mapmutations对应mutations)

<template>
  <div id="mymutations">
    <h3>使用mapmutions和mapactions</h3>
    <button @click="add">触发add</button>
    <button @click="myadd">触发myadd</button>
    <!-- 传参 -->
    <button @click="addtwo(3)">+3</button>
    <button @click="myasync">触发异步</button>
  </div>
</template>

<script>
// 获取辅助函数
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex';
export default {
  // 计算属性
  computed:{ 
  },
  // 放方法
  methods: {
    // 为了触发mutation函数 定义的方法没必要这么写
    // clickAdd(){
    //   this.$store.commit('add')
    // }

    //触发异步
    myasync(){
      this.$store.dispantch('asyncAdd')
    },

    // 字符串数组的用法
    ...mapMutations([
      'add'
    ]),
    // 对象写法
    ...mapMutations({
      // 同步方法通过commit触发mutauions
      myadd:'add',
      // 方法名:mutation函数名
      addtwo:'addParms'
    }),
    //异步
    ...mapActions({
      myasync:'asyncAdd'
    })
  },
}
</script>

Modules模块的使用

<script>
//vuex文件
import Vue from 'vue'
import Vuex from 'vuex'
import myUser from './myuser'
import cat from './cat'

Vue.use(Vuex)

// const myUser={
 
// } 
export default new Vuex.Store({
  modules: {//模块选项
    // 引入
    u:myUser,
    cat
  }
})
</script>
-----------------------------------------------------------下面是展示页面
<template>
  <div class="modules">
    <!-- 多了一层u -->
    <h4>user信息:{{$store.state.u.user}}</h4>
    <h4>cat信息:{{$store.state.cat.mycat}}</h4>
  </div>
</template>

结尾

如果对您有帮助,希望能给个👍评论收藏三连!

想跟博主交朋友的可以关注下🌹,有问题评论留言。

博主为人老实,无偿解答问题哦❤

版权声明:著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 作者: 前端老实人 原文链接:https://juejin.im/post/7012099159691886628

回到顶部