Vuex
开始
Vuex的核心是Store(仓库),Store它就相当于一个容器,包含应用中大部分的状态
使用
npm 使用
npm install vuex@next --save
步骤
1、下载以后去定义一个简单的 JS
import {createStore} from "vuex";
//创建新的store实列
export const store=createStore({
//类似Vue的data
state(){
return{
count:0,
redcount:0,
}
},
//相当于Vue里面的methods
mutations:{
add(state){
state.count++
},
reduce(state){
state.count--
state.redcount=state.count
}
}
})
2、需要把我们定义的 JS 选择Vue的全局注册也可以局部注册也可以
全局注册的话我们到哪里都可以直接调用
局部注册的话使用起来就不是那么方便 但是它可以减少Vue的负载吧!!(不是很明确)
本人使用全局注册
import { createApp } from 'vue'
import App from './App.vue'
//注册过来的Vuex核心
import {store} from "@/Store/Store";
let app=createApp(App);
//注册vuex到Vue上
app.use(store);
app.mount('#app');
3、到使用的组件中调用
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
<h1 @click="AAA">打印Vuex的值{{AA}}</h1>
<h1 @click="BBB">减小Count</h1>
<h2>Store状态值:{{StoreCount}}</h2>
<h2>mapState控制的Store{{redCount}}</h2>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
},
data(){
return{
AA:'点击变化'
}
},
computed:{
//调用我前面JS定义的count
StoreCount(){
return this.$store.state.count
},
redCount(){
//调用我前面JS定义的redcount
return this.$store.state.redcount
}
},
methods:{
AAA(){
//调用我们定义的Vuex里面mutations下面的add方法来控制count的值
this.$store.commit('add');
this.AA= this.$store.state.count;
console.log(this.$store.state.count,'Vuex设置的状态值');
},
BBB(){
this.$store.commit('reduce');
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
注意如果我们定义的状态太多我们一个一个的去通过computed一个个的生成感觉代码就太多重复和冗余所以就注意到Vuex提供的mapState
Getter
getter和Vue的computed 十分相似 那么getter就相当于store做计算属性
用法
普通属性访问
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sgjdN2QR-1681094380670)(…/其他/testimg/image-20230407145614226.png)]
mapGetters访问
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tCDx4aco-1681094380672)(…/其他/testimg/image-20230407145730411.png)]
Store.js
import {createStore} from "vuex";
//创建新的store实列
export const store=createStore({
//类似Vue的data
state(){
return{
count:9,
redcount:5,
}
},
getters:{
allcoured(state){
return state.count + state.redcount
},
gettersTwo(state){
return state.count+'是getterTwo缓存!'
}
},
//相当于Vue里面的methods
mutations:{
add(state){
state.count++
},
reduce(state){
state.count--
state.redcount=state.count
}
}
})
组件Vue
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h1>获取Vuex getters里面的AllCoRe{{allcoured}}</h1>
<h1>普通获取 getters {{gettertwo}}</h1>
</div>
</template>
<script>
import {mapGetters } from 'vuex'
export default {
name: 'HelloWorld',
props: {
msg: String
},
data() {
return {
AA: '点击变化'
}
},
computed:{
//通过mapGetters辅助函数来实现 注意 不是mapState
...mapGetters(['allcoured']),
gettertwo(){
return this.$store.getters.gettersTwo
}
},
methods: {
AAA() {
//调用我们定义的Vuex里面mutations下面的add方法来控制count的值
this.$store.commit('add');
this.AA = this.$store.state.count;
console.log(this.$store.state.count, 'Vuex设置的状态值');
},
BBB() {
this.$store.commit('reduce');
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
使用效果
效果图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OdllonPj-1681094380673)(…/其他/testimg/image-20230407145815332.png)]
mapState
mapState它是一个辅助函数它可以帮助我们生成计算属性
用法
在需要的组件JS里面导入 mapState
import {mapState} from 'vuex'
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h1 @click="AAA">加大Count</h1>
<h1 @click="BBB">减小Count</h1>
<h2>count:{{count}}</h2>
<h2>redcount:{{redcount}}</h2>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: 'HelloWorld',
props: {
msg: String
},
data() {
return {
AA: '点击变化'
}
},
//使用的mapState帮我们生成计算属性但是它的值都是我们Vuex State里面我们定义好的值
computed: mapState({
count: state => state.count,
redcount:'redcount'
}),
methods: {
AAA() {
//调用我们定义的Vuex里面mutations下面的add方法来控制count的值
this.$store.commit('add');
this.AA = this.$store.state.count;
console.log(this.$store.state.count, 'Vuex设置的状态值');
},
BBB() {
this.$store.commit('reduce');
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
</style>
通过查看使用mapState的computed的前后对比
使用前:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jh4qaQ4E-1681094380674)(D:\notes\其他\testimg_`ZFZ0N0Q13V[X[N{FI$E0.png)]
使用后:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nbLnxmDO-1681094380675)(D:\notes\其他\testimg\image-20230404160111836.png)]
代码已经减少了许多
效果图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nK2rZJx4-1681094380676)(D:\notes\其他\testimg\image-20230404160225051.png)]
Mutation
Vuex里面的Mutation类似于Vue里面的methods方法
注意:Mutation里面的方法它们会接受State为第一个参数
用法:
//相当于Vue里面的methods
mutations:{
add(state){
state.count++
},
当我们需要调用 Vuex里面的mutations的时候调用方法和Vue不同
我们需要通过 store.commit(‘定义的名字【add】’)
我们还可以想store.commit(‘A’,‘B’)里面而外传入参数B 称之为 提交载荷
用法
import {createStore} from "vuex";
//创建新的store实列
export const store=createStore({
//类似Vue的data
state(){
return{
count:9,
}
},
//相当于Vue里面的methods
//传入载荷n
mutations:{
add(state,n){
state.count=state.count+n;
}
}
})
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h1>{{useVuexmutations}}</h1>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
},
data() {
return {
AA: '点击变化'
}
},
computed:{
// 使用Vuex的mutations
useVuexmutations(){
//调用Vuex mutations里面的add 并且给n赋值为10
this.$store.commit('add',10)
return this.$store.state.count
}
},
methods: {}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
效果
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lnUnTgZl-1681094380678)(…/其他/testimg/image-20230408153722700.png)]
js:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QNLMAOG5-1681094380678)(…/其他/testimg/image-20230408153845112.png)]
Vue:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wjWulCva-1681094380679)(…/其他/testimg/image-20230408154127303.png)]
注意:大多数情况下提交载荷是一个对象形式这种情况包含多个字段可以复杂处理
store.commit('add', {
n: 10
})
注意:触发Vuex mutations还有一种写法
store.commit({
type: 'add',
n: 10
})
type :就是我们在mutations里面定义的 名称
n : 是我们提交过去的提交载荷
多方法名
如果我们mutations的数量较多我们可以通过创建一个mutation-types.js文件来事先定义好它的名字
例如
mutations-types.js
//定义一个Vuex里面的mutations方法的 方法名为SOME_MUTATION
export const SOME_MUTATION='SOME_MUTATION';
Store.js
import {createStore} from "vuex";
//引入我们定义的mutations方法名的js文件
import {SOME_MUTATION} from "@/Store/mutation-types";
//创建新的store实列
export const store=createStore({
//类似Vue的data
state(){
return{
count:9,
}
},
//相当于Vue里面的methods
//传入载荷n
mutations:{
add(state,n){
state.count=state.count+n;
},
//使用我们定义的SOME_MUTATION来作为方法名
[SOME_MUTATION](state){
state.count=state.count+5
}
}
})
组件模板
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h1>{{useVuexmutations}}</h1>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
},
data() {
return {
AA: '点击变化'
}
},
computed:{
// 使用Vuex的mutations
useVuexmutations(){
//我们事先定义的方法名
this.$store.commit('SOME_MUTATION')
return this.$store.state.count
}
},
methods: {}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
效果图
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lbuLoBKe-1681094380680)(…/其他/testimg/image-20230408161215077.png)]
注意注意注意!!! Mutations必须是同步函数
mapMutations
用法
和之前的mapGetters和mapState大同小异
注意注意!!mapMutations它是在Vue methods里面触发的并不是在Vue的缓存computed直接调用
下面请看代码吧:
Store.js
import {createStore} from "vuex";
//引入我们定义的mutations方法名的js文件
import {SOME_MUTATION} from "@/Store/mutation-types";
//创建新的store实列
export const store=createStore({
//类似Vue的data
state(){
return{
count:9,
}
},
//相当于Vue里面的methods
//传入载荷n
mutations:{
add(state,n){
state.count=state.count+n;
},
//使用我们定义的SOME_MUTATION来作为方法名
[SOME_MUTATION](state){
state.count=state.count+5
}
}
})
组件调用部分代码
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<h1>{{count}}</h1>
<!--点击触发mapMutations下定义的:add-->
<button @click="add">触发count+5</button>
</div>
</template>
<script>
import {mapMutations} from 'vuex'
import {mapState} from 'vuex'
export default {
name: 'HelloWorld',
props: {
msg: String
},
data() {
return {
AA: '点击变化'
}
},
computed:{
...mapState(['count'])
},
methods: {
//add 触发 mutations下的SOME_MUTATION 给count+5
...mapMutations({
add:'SOME_MUTATION'
}),
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>
自己之前在使用时候不够细心就一种写错 把mapMutations使用到缓存computed里面了
效果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mif85E6x-1681094380681)(…/其他/testimg/image-20230408163707955.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cAnVOIBF-1681094380682)(…/其他/testimg/image-20230408163720664.png)]
点击一下就触发了 给count加5
mapmutations有两种写法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dz6GaupC-1681094380682)(…/其他/testimg/image-20230408164336606.png)]
Action
Action类似于mutation
- Action提交的是mutation,而不是直接改变状态
- Action可以包含任意异步操作
注意注意:
Action函数接收一个与store实列具有相同方法和属性的context对象,所以可以调用context.commit提交一个mutation,或者通过context.state和context.getters来获取state和getters
问题 :属性和方法都是和stores一样问什么不是stores呢?
用法
触发使用store.dispatch(‘定义的actions方法名’)
Store.js
import {createStore} from "vuex";
//创建新的store实列
export const store=createStore({
//类似Vue的data
state(){
return{
count:9,
act:2
}
},
mutations:{
actinfo(state){
state.act=state.act+6
}
},
actions:{
vuexact(context){
console.log('执行了vuexact')
setInterval(function () {
console.log('两秒以后执行了setInterval')
context.commit('actinfo')
},2000)
}
}
})
组件
<template>
<div class="hello">
<h1>{{ getact }}</h1>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
msg: String
},
data() {
return {
AA: '点击变化'
}
},
computed:{
getact(){
//触发的方法$store.dispatch
this.$store.dispatch('vuexact')
return this.$store.state.act
}
}
}
</script>
<style scoped>
</style>
效果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nJITJfJ5-1681094380683)(…/其他/testimg/image-20230408173552086.png)]
个人理解:
Vuex里面的mutations它必定是同步的并且它是直接的去改变状态而当我们需要执行一些异步操作就需要用到actions它里面通过操作类似state的对象context去控制到state中的方法 也就是是actions它是一个外部的方法它包含了mutations里面的方法也就是(外部函数是可异步操作,内部函数的同步函数)
写法
使用解构cont
actions: {
vuexact ({ commit }) {
console.log('执行了vuexact')
setInterval(function () {
console.log('两秒以后执行了setInterval')
commit('actinfo')
},2000)
}
}
}
注意:Action也可以使用 载荷方式和mutation一样这里我们定义context,后再定义载荷参数名即可
用法
// 以载荷形式分发
store.dispatch('incrementAsync', {
amount: 10
})
// 以对象形式分发
store.dispatch({
type: 'incrementAsync',
amount: 10
})
mapActions
注意也是在vue 方法methods调用
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
// `mapActions` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
})
}
}
在action中使用Promise
commit('actinfo')
},2000)
}
}
}
注意:Action也可以使用 ==载荷方式==和mutation一样这里我们定义context,后再定义载荷参数名即可
用法
```js
// 以载荷形式分发
store.dispatch('incrementAsync', {
amount: 10
})
// 以对象形式分发
store.dispatch({
type: 'incrementAsync',
amount: 10
})
mapActions
注意也是在vue 方法methods调用
import { mapActions } from 'vuex'
export default {
// ...
methods: {
...mapActions([
'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`
// `mapActions` 也支持载荷:
'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
]),
...mapActions({
add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
})
}
}
在action中使用Promise