Vuex基本概念

本文详细介绍了Vuex的基本概念,包括State、Getter、Mutation、Action和Module等内容,并提供了简单的Store示例及常见流程说明。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Vuex基本概念

  • State
  • Getter
  • Mutation
  • Action
  • Module

简单的Store

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

Vue.use(vuex);

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++;
    } 
  }
});

store.commit('increment');
console.log(store.state.count);// 1

常见流程

Vue Component --dispatch--> Action

Action --commit--> Mutations

Mutations --mutate--> State

State --render--> Vue Component

State

获取vuex中的状态方法

计算属性:computed中返回某个状态,要获取Vuex那个状态,要在computed中定义

由于在全局使用了Vue.use(Vuex),所有组件可以通过this.$store拿到Vuex的store

const Counter = {
  template: `<div>{{count}}</div>`,
  computed: {
    count () {
      return this.$store.state.count
    }
  }
}

由于computed的属性是函数,那么在返回状态之前,还有更多操作的空间。

mapState辅助函数

import {mapState} from 'vuex'

mapState辅助函数接收一个对象或者一个字符串数组,返回计算属性:computed

//这个可以单独放在一个文件中,重复使用
const vuexComputed = mapState({
  //使用函数一定要有返回值

  //箭头函数写法,第一参数是state
  count: state => state.count,
  
  //字符串形式 'count' 等同于 state => state.count
  countAlias: 'count',
  
  //可以使用'this'获取局部状态,使用常规函数,'this'会绑定为 computed的组件实例
  countPlusLocalState (state) {
    return state.count + this.localCount;
  }
});

然后将mapState生成的vuexComputed和Vue组件实例的computed合并

使用对象展开运算符...

{
  //...某个组件
  
  computed: {
    localComputed () {},
    //使用对象展开运算符将vuexComputed混入到外部对象中
    ...vuexComputed
  }
}

如果状态都只是单纯的显示,可以传一个字符串数组mapState

const vuexComputed = mapState(['count']);

完整的demo:

//main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import Vuex from 'vuex'
import axios from 'axios'

Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})

store.commit('increment')
console.log(store.state.count)

Vue.config.productionTip = false
Vue.prototype.$http = axios

/* eslint-disable no-new */
new Vue({
  el: '#app',
  store,
  router,
  components: { App },
  template: '<App/>'
})

main.js要使用Vue.use(Vuex)以及将store添加到全局new Vue({store})

下面的所有子组件才可以拿到store

<template>
  <div class="hello">
    <div>{{count}}</div>
    <div>{{countAlias}}</div>
    <div>{{countPlusLocalState}}</div>
  </div>
</template>
//Component HelloWorld
import {mapState} from 'vuex'

const vuexComputed = mapState({
  count: state => state.count,
  countAlias: 'count',
  countPlusLocalState (state) {
    return state.count + this.localCount
  }
})

export default {
  name: 'HelloWorld',
  data () {
    return {
      localCount: 2
    }
  },
  computed: {
    ...vuexComputed
  }
}

Getter

Getter计算属性:computed功能一样,只不过,它是store的,也会缓存计算的值。

组件中拿到getter

Getter会暴露store.getters对象。

const store = new Vuex.Store({
  state: {
    count: 0,
    arr: [1, 2, 3, 4, 5, 6]
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  getters: {
    get6: state => {
      return state.arr.filter(num => num === 6)
    }
  }
})
{
  //...某个组件
  computed: {
    get6 () {
      return this.$store.getters.get6
    }
  }
}

在定义getter时,有两个参数传入stategetters

getters: {
  get6: state => state.arr.filter(num => num === 6),
  getNum: (state, getters) => {
    return getters.get6
  }
}

定义getter方法

//要使用函数要封装2层函数以上,在组件中拿到getTodoById时,默认执行第一层
getters: {
  getTodoById: state => id => state.todos.find(todo => todo.id === id)
}

store.getters.getTodoById(2)

mapGetters
功能:将store中的getter映射到局部的计算属性computed

mapState类似,支持传入对象或者字符串数组,不过只能获取,不能重写,或者定义

//store
{
  state: {
    arr: [1, 2, 3, 4, 5, 6, 7, 8]
  },
  getters: {
    get6: state => {
      return state.arr.find(num => num === 6)
    },
    getNum: state => num => state.arr.find(n => n === num) || '错误num'
  }
}
<template>
  <div class='helloworld'>
    <div>{{get6}}</div>
    <div>{{getNum(4)}}</div>
  </div>
</template>
const vuexGetter = mapGetters(['get6', 'getNum']);

//如果想定义别名使用对象的方式
//const vuexGetter = mapGetters({getSix: 'get6', getNumber: 'getNum'})

export default {
  name: 'HelloWorld',
  data () {
  },
  computed: {
    ...vuexGetter
  }
}

Mutation

修改Vuexstore中的状态的唯一方式是commit mutation

每个mutation都有一个字符串的事件类型(type)和一个回调函数(handler)

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // 变更状态
      state.count++
    }
  }
})
//type: increment
store.commit('increment')

Payload

mutations: {
  increment (state, n) {
    state.count += n
  }
}
store.commit('increment', 10)

store.commit可以支持多参数模式,或者一个对象模式

store.commit({
  type: 'increment',
  amount: 10
})

其中一个对象模式redux很像

而且事件类型type也可以使用常量来替代

// mutation-types.js
export const SOME_MUTATION = 'SOME_MUTATION';

// store.js
import Vuex from 'vuex';
import { SOME_MUTATION } from './mutation-types';

const store = new Vuex.Store({
  state: { ... },
  mutations: {
    // 我们可以使用 ES2015 风格的计算属性命名功能来使用一个常量作为函数名
    [SOME_MUTATION] (state) {
      // mutate state
    }
  }
})

组件中提交mutation

在组件中可以通过this.$store.commit('xxx')提交mutation

还有就是使用mapMutations辅助函数,不过这次不是映射到计算属性,而是methods

使用方式和mapGetters一模一样

import { mapMutations } from 'vuex';

//对象的方式可以重新命名,字符串数组是直接引用
const vuexMutations = mapMutations(['increment']);

export default {

  methods: {
    ...vuexMutations
  }
}

Mutation 和 Reduce

Reduce的基本形式

(state, Action) => newState || state

转化为Mutation,那么

const Action = {
  type: 'increment',
  amount: 10
}

const initState = {
  count: 0
}

export default (state = initState, Action) => {
  switch(Action.type){
    'increment':
      return Object.assign({},state,{count: Action.amount + state.count})
    default:
      return state
  }  
}

redux中改变状态:

store.dispatch(Action) -> reduce(state, Action) -> newState -> render view

mutation中改变状态:

store.commit('increment', playload) -> mutations['increment'](state, playload) -> newState -> render view

Action

一般Action可以处理异步任务,而Mutation必须只能同步。

在异步流程中,先异步获得所需的数据,然后将返回的数据组合成Action

在生成Action之前,有个createAction函数

//Redux 思维的Action
const createAction = async (url) => {
  const resData = await asyncGetData(url)
  
  return {
    type: 'SOME_TYPE',
    resData  
  };
};

//Action 是对象
const Action = createAction('some url')

store.commit(Action)

Vuex中的ActionRedux是有区别的

Vuex中的Action充当着createAction的功能

commit应当只在action中使用,在commit之前还有dispatch

Redux中,dispatch分发的直接是action

Vuex中,dispatch分发的是createAction或者mutation,之后再commit action

Action 不同于 Mutation

  • Action提交的是mutation,而不是直接变更状态
  • Action可以包含任意异步操作
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})

Action函数接受一个与store实例具有相同方法和属性的context对象

其中context不是store实例

分发Action

store.dispatch('increment')

组件中分发Action
组件中使用this.$store.dispatch('xxx')

或者使用mapActions辅助函数将actions映射到methods

组合Action
dispatch函数在结束后返回一个Promise

actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  }
}

Module

可以将store分割成模块Module

每个模块拥有自己的State、Mutation、Action、Getter

然后将所有模块组合成一个,就形成了一个状态树。

//一般我们可以按页面或者功能模块来划分模块
//大型项目可以按一个大模块划分
//然后在大漠块中再按页面划分
//如果还要更细,页面也可以切割成多个模块

//页面A的状态
const pageA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

//页面B的状态
const pageAB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: pageA,
    b: pageAB
  }
})

store.state.a // -> pageA 的状态
store.state.b // -> pageAB 的状态

模块的局部状态

每个模块的state都是局部状态,模块中的gettermutation、传进来的state都是局部的

action可以通过context.state拿到局部的状态,context.rootState拿到全局的

不同于mutationgetter也可以拿到全局状态,getter的第三个参数rootState

命名空间

默认情况下,模块内部的action、mutation和getter是注册在全局命名空间的--多个模块对同一mutation或action作出响应

多个模块对同一mutation或action作出响应,类似一个事件拥有多个处理程序(观察者模式)

在模块中添加namespace: true可以避免添加到全局队列中

添加命名空间后的getter : (state, getters, rootState, rootGetters) => {}

添加命名空间后的action context : getters访问局部的 rootGetters访问全局的

如果添加了命名空间,但是还是想暴露某个actiongetter为全局,使用root:true

{
  actions: {
    someOtherAction ({dispatch}) {
      dispatch('someAction')
    }
  },
  modules: {
    foo: {
      namespaced: true,

      actions: {
        someAction: {
          root: true,
          handler (namespacedContext, payload) { ... } // -> 'someAction'
        }
      }
    }
  }
}

mapStatemapGettersmapActionsmapMutations绑定带命名空间的模块。

computed: {
  ...mapState('some/nested/module', {
    a: state => state.a,
    b: state => state.b
  })
},
methods: {
  ...mapActions('some/nested/module', [
    'foo',
    'bar'
  ])
}

还可以使用createNamespacedHelpers来绑定命名空间值,类似bind(context)

import { createNamespacedHelpers } from 'vuex';

const { mapState, mapActions } = createNamespacedHelpers('some/nested/module');

export default {
  computed: {
    // 在 `some/nested/module` 中查找
    ...mapState({
      a: state => state.a,
      b: state => state.b
    })
  },
  methods: {
    // 在 `some/nested/module` 中查找
    ...mapActions([
      'foo',
      'bar'
    ])
  }
}

模块动态注册

// 注册模块 `myModule`
store.registerModule('myModule', {
  // ...
})
// 注册嵌套模块 `nested/myModule`
store.registerModule(['nested', 'myModule'], {
  // ...
})

//卸载'myModule',只能卸载动态装载的模块
 store.unregisterModule('myModule')

应用

如果是小型应用,可以按页面来分模块

//pagea.js
export default {
  namespace:true,
  state: {},
  getters: {},
  mutations: {},
  actions: {}
}

//pageb.js
//pagec.js
//paged.js
//以上页面也是按pagea.js的方式

然后用一个文件引进所有模块,且全部暴露export

//modules.js
import pageA from './pagea.js'
import pageB from './pageb.js'
import pageC from './pagec.js'
import pageD from './paged.js'

export default {
  pageA,
  pageB,
  pageC,
  pageD
}

最后在main.js引入

//main.js
import modules from './modules/modules'

//将模块装进Store树中
const store = new Vuex.Store({
  //全局
  state: {},
  getters: {},
  mutations: {},
  actions: {},
  //模块
  modules
}) 
//在组件中可以
this.$store.state.pageA
this.$store.state.pageB
this.$store.state.pageC
this.$store.state.pageD

转载于:https://www.cnblogs.com/lantuoxie/p/8761742.html

基于数据挖掘的音乐推荐系统设计与实现 需要一个代码说明,不需要论文 采用python语言,django框架,mysql数据库开发 编程环境:pycharm,mysql8.0 系统分为前台+后台模式开发 网站前台: 用户注册, 登录 搜索音乐,音乐欣赏(可以在线进行播放) 用户登陆时选择相关感兴趣的音乐风格 音乐收藏 音乐推荐算法:(重点) 本课题需要大量用户行为(如播放记录、收藏列表)、音乐特征(如音频特征、歌曲元数据)等数据 (1)根据用户之间相似性或关联性,给一个用户推荐与其相似或有关联的其他用户所感兴趣的音乐; (2)根据音乐之间的相似性或关联性,给一个用户推荐与其感兴趣的音乐相似或有关联的其他音乐。 基于用户的推荐和基于物品的推荐 其中基于用户的推荐是基于用户的相似度找出相似相似用户,然后向目标用户推荐其相似用户喜欢的东西(和你类似的人也喜欢**东西); 而基于物品的推荐是基于物品的相似度找出相似的物品做推荐(喜欢该音乐的人还喜欢了**音乐); 管理员 管理员信息管理 注册用户管理,审核 音乐爬虫(爬虫方式爬取网站音乐数据) 音乐信息管理(上传歌曲MP3,以便前台播放) 音乐收藏管理 用户 用户资料修改 我的音乐收藏 完整前后端源码,部署后可正常运行! 环境说明 开发语言:python后端 python版本:3.7 数据库:mysql 5.7+ 数据库工具:Navicat11+ 开发软件:pycharm
MPU6050是一款广泛应用在无人机、机器人和运动设备中的六轴姿态传感器,它集成了三轴陀螺仪和三轴加速度计。这款传感器能够实时监测并提供设备的角速度和线性加速度数据,对于理解物体的动态运动状态至关重要。在Arduino平台上,通过特定的库文件可以方便地与MPU6050进行通信,获取并解析传感器数据。 `MPU6050.cpp`和`MPU6050.h`是Arduino库的关键组成部分。`MPU6050.h`是头文件,包含了定义传感器接口和函数声明。它定义了类`MPU6050`,该类包含了初始化传感器、读取数据等方法。例如,`begin()`函数用于设置传感器的工作模式和I2C地址,`getAcceleration()`和`getGyroscope()`则分别用于获取加速度和角速度数据。 在Arduino项目中,首先需要包含`MPU6050.h`头文件,然后创建`MPU6050`对象,并调用`begin()`函数初始化传感器。之后,可以通过循环调用`getAcceleration()`和`getGyroscope()`来不断更新传感器读数。为了处理这些原始数据,通常还需要进行校准和滤波,以消除噪声和漂移。 I2C通信协议是MPU6050与Arduino交互的基础,它是一种低引脚数的串行通信协议,允许多个设备共享一对数据线。Arduino板上的Wire库提供了I2C通信的底层支持,使得用户无需深入了解通信细节,就能方便地与MPU6050交互。 MPU6050传感器的数据包括加速度(X、Y、Z轴)和角速度(同样为X、Y、Z轴)。加速度数据可以用来计算物体的静态位置和动态运动,而角速度数据则能反映物体转动的速度。结合这两个数据,可以进一步计算出物体的姿态(如角度和角速度变化)。 在嵌入式开发领域,特别是使用STM32微控制器时,也可以找到类似的库来驱动MPU6050。STM32通常具有更强大的处理能力和更多的GPIO口,可以实现更复杂的控制算法。然而,基本的传感器操作流程和数据处理原理与Arduino平台相似。 在实际应用中,除了基本的传感器读取,还可能涉及到温度补偿、低功耗模式设置、DMP(数字运动处理器)功能的利用等高级特性。DMP可以帮助处理传感器数据,实现更高级的运动估计,减轻主控制器的计算负担。 MPU6050是一个强大的六轴传感器,广泛应用于各种需要实时运动追踪的项目中。通过 Arduino 或 STM32 的库文件,开发者可以轻松地与传感器交互,获取并处理数据,实现各种创新应用。博客和其他开源资源是学习和解决问题的重要途径,通过这些资源,开发者可以获得关于MPU6050的详细信息和实践指南
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值