一文完全上手vuex

大佬手摸手教你写vuex

https://zhuanlan.zhihu.com/p/464492572

1
Vuex是什么?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。什么情景下使用呢?多个视图公用状态的时候,紧靠父子传参是比较麻烦的,特别是嵌套的组件较多的时候。这样用vuex就很方便的把数据共享出来了。
总结一下
import { mapState, mapGetters, mapMutations, mapActions } from "vuex";
在页面中使用vuex一共有四个展开函数,可以分别把state、getters、mutattions,actions展开使在页面中更方便的调用,而不需要this.$store.xxx,直接在页面中xxx就行了
其中推荐把:
mapState、mapGeters写在计算属性computed中 ...mapState(['展开的属性一'],['展开的属性二']...) ...mapGetters(['展开的属性一'],['展开的属性二']...)
 mapMutations, mapActions 写在函数中 ...mapMutations(['展开的方法一'],['展开的方法二']...)
...mapActions (['展开的方法一'],['展开的方法二']...)
2
安装
npm install vuex --save
3
导入
在src文件夹下创建store文件夹,在里面创建一个index.js文件。



import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
4
创建状态管理对象store
state对象里面是定义的状态(数据)



export default new Vuex.Store({
  state: {
    //定义数据
    person: {
      name: "张三",
      age: 15,
    },
  }
});
5
注册到vue(main.js)
import Vue from "vue";
import App from "./App.vue";
import store from "./store";//引入我们前面导出的store对象
Vue.config.productionTip = false;
new Vue({
  store,//把store对象添加到vue实例上
  render: (h) => h(App),
}).$mount("#app");
6
如何使用(App.vue)



了解State



<template>
  <div id="app">
    <div>人名:{{ $store.state.person.name }}</div>
    <div>年龄:{{ $store.state.person.age }}</div>
  </div>
</template>
<script>
export default {
  name: "App",
  components: {},
  methods: {
  },
};
</script>
<style>
</style>
运行效果:









官方建议1:

官方建议我们以上操作this.$http://store.state.XXX最好放在计算属性中,当然,我也建议你这么使用,这样可以让你的代码看起来更优雅一些,就像这样:



<template>
  <div id="app">
    <div>人名:{{ getPerson.name }}</div>
    <div>年龄:{{ getPerson.age }}</div>
  </div>
</template>
<script>
export default {
  name: "App",
  components: {},
  methods: {},
  computed: {
    getPerson() {
      return this.$store.state.person;
    },
  },
};
</script>
<style>
</style>
和上面的运行效果是一样的。




官方建议2:

是不是每次都写this.$http://store.state.XXX让你感到厌烦,你实在不想写这个东西怎么办,当然有解决方案,就像下面这样:



<template>
  <div id="app">
    <div>人名:{{ person.name }}</div>
    <div>年龄:{{ person.age }}</div>
  </div>
</template>
<script>
import { mapState } from "vuex"; // 从vuex中导入mapState
export default {
  name: "App",
  components: {},
  methods: {},
  computed: {
    ...mapState(["person"])// 经过解构后,自动就添加到了计算属性中,此时就可以直接像访问计算属性一样访问它
  }
};
</script>
<style>
</style>
如果解构的时候,想改属性的名字,那么你可以这样写:



computed: {
    ...mapState({ personNew: "person" })//注意这里展开的是对象,不是数组
}
看到现在为止,你已经可以在任何组件中来操作状态了






了解Getter



接下来该Getter方法闪亮登场了,Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

简单来说就是可以对你的state数据进行修饰,比如上述例子中的人名已经渲染出来了,现在要求用符号把人名包裹起来。



import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
  state: {
    //定义数据
    person: {
      name: "张三",
      age: 15
    }
  },
  getters: {
    getName(state) {
      //该方法可以接收2个参数,1.state对象 2.getters对象
      return `【${state.person.name}】`;
    }
  }
});
在组件中使用



<template>
  <div id="app">
    <div>人名:{{ $store.getters.getName }}</div>
    <div>年龄:{{ person.age }}</div>
    <button @click="updatePerson">修改个人信息</button>
  </div>
</template>
<script>
import { mapState } from "vuex"; // 从vuex中导入mapState
export default {
  name: "App",
  components: {},
  methods: {}
  },
  mounted() {},
  computed: {
    ...mapState(["person"]) // 经过解构后,自动就添加到了计算属性中,此时就可以直接像访问计算属性一样访问它
  }
};
</script>
<style>
</style>
运行效果:









官方建议:

如果你觉得每次都要写 $http://store.getters.xxx比较麻烦,我们可以使用mapGetters去解构到计算属性中,此时就可以直接像访问计算属性一样访问它。



<template>
  <div id="app">
    <div>人名:{{ getName }}</div>
    <div>年龄:{{ person.age }}</div>
    <button @click="updatePerson">修改个人信息</button>
  </div>
</template>
<script>
import { mapState, mapGetters } from "vuex"; // 从vuex中导入mapState
export default {
  name: "App",
  components: {},
  methods: {},
  computed: {
    ...mapState(["person"]), // 经过解构后,自动就添加到了计算属性中,此时就可以直接像访问计算属性一样访问它
    ...mapGetters(["getName"])
  }
};
</script>
<style>
</style>
此时查看运行的效果是一样的,你也可以给这个属性换个名字。



...mapGetters({ aliasName: 'getName' }), // 赋别名的话,这里接收对象,而不是数组



Mutation



接下来介绍一下修改状态值的方法:Mutation

说到这里有人会想到this.$http://store.state.XXX = XXX;(切记:这是错误的写法)

1.更改 Vuex 的 store 中的状态的唯一方法是提交 mutation

2.mutations里面的函数必须是同步操作,不能是异步(后面会介绍如何用异步操作)

看例子我要点击按钮的时候,修改信息。



import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
  state: {
    //定义数据
    person: {
      name: "张三",
      age: 15
    }
  },
  getters: {
    getName(state) {
      //该方法可以接收2个参数,1.state对象 2.getters对象
      return `【${state.person.name}】`;
    }
  },
  mutations: {
    //定义修改状态的方法
    updatePerson(state, val) {
      //该方法可以接收2个参数,1.state对象 2.val传进来要更新的值
      state.person = val;
    }
  }
});
组件中调用



<template>
  <div id="app">
    <div>人名:{{ getName }}</div>
    <div>年龄:{{ person.age }}</div>
    <button @click="updatePerson">修改个人信息</button>
  </div>
</template>
<script>
import { mapState, mapGetters } from "vuex"; // 从vuex中导入mapState
export default {
  name: "App",
  components: {},
  methods: {
    updatePerson() {
      this.$store.commit("updatePerson", { name: "李四", age: 25 });
    }
  },
  mounted() {},
  computed: {
    ...mapState(["person"]), // 经过解构后,自动就添加到了计算属性中,此时就可以直接像访问计算属性一样访问它
    ...mapGetters(["getName"])
  }
};
</script>
<style>
</style>
运行效果:

点击修改个人信息按钮前:






点击修改个人信息按钮后:









官方建议:

是不是感觉写this.$store.commit('XXX')比较麻烦呢,我们可以使用mapMutations去解构到方法中,此时就可以直接像调用函数一样去使用它。



<template>
  <div id="app">
    <div>人名:{{ getName }}</div>
    <div>年龄:{{ person.age }}</div>
    <button @click="updatePerson({name: '李四', age: 25})">修改个人信息</button>
  </div>
</template>
<script>
import { mapState, mapGetters, mapMutations } from "vuex"; // 从vuex中导入mapState
export default {
  name: "App",
  components: {},
  methods: {
    ...mapMutations(["updatePerson"])
    // updatePerson() {
    // this.$store.commit("updatePerson", { name: "李四", age: 25 });
    // }
  },
  mounted() {},
  computed: {
    ...mapState(["person"]), // 经过解构后,自动就添加到了计算属性中,此时就可以直接像访问计算属性一样访问它
    ...mapGetters(["getName"])
  }
};
</script>
<style>
</style>
此时可以得到和之前一样的效果,当然你也可以给它换个名字。



methods:{
    ...mapMutations({ updatePersonNew: 'updatePerson' }), // 赋别名的话,这里接收对象,而不是数组
}



Action



接下来我们来了解下Action,可以存放异步操作。

Action类似于mutation,不同的是:

1.Action 提交的是 mutation,而不是直接变更状态。前面也提到过mutation是唯一可修改状态的方法。

2.Action可以包含任意异步操作



import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
  state: {
    //定义数据
    person: {
      name: "张三",
      age: 15
    }
  },
  getters: {
    getName(state) {
      //该方法可以接收2个参数,1.state对象 2.getters对象
      return `【${state.person.name}】`;
    }
  },
  mutations: {
    //定义修改状态的方法
    updatePerson(state, val) {
      //该方法可以接收2个参数,1.state对象 2.val传进来要更新的值
      state.person = val;
    },
    setName(state, name) {
      state.person.name = name;
    }
  },
  actions: {
    setN(content) {
      // 增加setN方法,默认第一个参数是content,其值是复制的一份store
      return new Promise(resolve => {
        // 我们模拟一个异步操作,1秒后修改人名为action王五
        setTimeout(() => {
          content.commit("setName", "action王五");
          resolve();
        }, 1000);
      });
    }
  }
});
组件中调用:



<template>
  <div id="app">
    <div>人名:{{ getName }}</div>
    <div>年龄:{{ person.age }}</div>
    <button @click="$store.dispatch('setN');">修改个人信息</button>
  </div>
</template>
<script>
import { mapState, mapGetters, mapMutations } from "vuex"; // 从vuex中导入mapState
export default {
  name: "App",
  components: {},
  methods: {
    ...mapMutations(["updatePerson"])
  },
  mounted() {},
  computed: {
    ...mapState(["person"]), // 经过解构后,自动就添加到了计算属性中,此时就可以直接像访问计算属性一样访问它
    ...mapGetters(["getName"])
  }
};
</script>
<style>
</style>
运行效果:点击按钮1秒后。






看到这里知道我要说什么了吧,哈哈哈...




官方建议1:

是不是感觉写$store.dispatch('xxx')比较麻烦呢,我们可以使用mapActions去解构到方法中,此时就可以直接像调用函数一样去使用它。



<template>
  <div id="app">
    <div>人名:{{ getName }}</div>
    <div>年龄:{{ person.age }}</div>
    <button @click="setN">修改个人信息</button>
  </div>
</template>
<script>
import { mapState, mapGetters, mapMutations, mapActions } from "vuex"; // 从vuex中导入mapState
export default {
  name: "App",
  components: {},
  methods: {
    ...mapMutations(["updatePerson"]),
    ...mapActions(["setN"])
  },
  mounted() {},
  computed: {
    ...mapState(["person"]), // 经过解构后,自动就添加到了计算属性中,此时就可以直接像访问计算属性一样访问它
    ...mapGetters(["getName"])
  }
};
</script>
<style>
</style>
运行效果是一样的,当然你也可以给它起一个别名。



...mapActions({ setName: 'setN' }), // 赋别名的话,这里接收对象,而不是数组



官方建议2:

actions里面方法的形参可以直接将commit解构出来,这样可以更方便的去使用。



actions: {
    setN({ commit }) {
      // 增加setN方法,默认第一个参数是content,其值是复制的一份store
      return new Promise(resolve => {
        // 我们模拟一个异步操作,1秒后修改人名为action王五
        setTimeout(() => {
          commit("setName", "action王五");
          resolve();
        }, 1000);
      });
    }
}
总结:看到这里你应该对vuex不陌生了吧,百看不如一练。如果感觉对你有帮助,快收藏起来吧。以上分享仅为自己的见解(不喜勿喷),若有误或者你有更好的方法,欢迎来评论指出


。

  

posted @ 2024-01-15 18:10  iwen1992  阅读(2)  评论(0编辑  收藏  举报