目录
1.简介
为了方便实现组件之间的数据共享,Vuex是他们团队借鉴了redux,用来实现vue组件全局状态(数据)管理的一种机制.

2.特点(面试)
能够在vuex中集中管理共享的数据,易于开发和后期维护
能够高效地实现组件之间的数据共享, 提高开发效率
存储在 vuex中的数据都是响应式的,能够实时保持数据与页面的同步
一般情况下,只有组件之间共享的数据,才有必要存储到vuex中;
对于组件中的私有数据,依旧存储在组件自身的data中即可.
3.使用场景
如果你实在不知道开发中什么数据才应该保存到Vuex中,那你就先不用Vuex,需要的时候自然就会想到它
Vuex的官网:
安装:
npm i vuex --save
导入:
import Vuex from "vuex"
Vue.use(Vuex)
创建仓库:
const store=new Vuex.Store({
state:{msg:"我就是所有共享的数据"}
})
把仓库挂载到vm对象:
- new Vue({
-
- render(h){return h(app)},
-
- router,
-
- store//挂载以后 所有的组件就可以直接从store中获取全局数据
-
- }).$mount( "#app")
vue create init
选更多选项
选择Babel、router、vuex、scss、linter
选择2.x
回车
scss
回车
取消lint on save
回车
1.创建state状态
状态就是那个存数据的对象
const store=new Vuex.store({ state:{msg:"我就是所有共享的数据"} })
2.组件中访问数据
this.$store.state.msg
this.$store.state.msg =“修改” ==>官方不建议使用此方法去修改,应该用官方提供的 mutation
main.js
- import Vue from 'vue'
- import App from './App.vue'
- import router from './router'
- import store from './store'
- Vue.config.productionTip = false
- new Vue({
- router,
- store,//让整个vue项目仓库生效
- render: h => h(App)
- }).$mount('#app')
router下的index.js
- import Vue from 'vue'
- import VueRouter from 'vue-router'
- Vue.use(VueRouter)
- const routes = [{
- path: '/',
- name: 'home',
- component: () => import("../views/home/index.vue")
- },
- {
- path: '/home',
- name: 'home2',
- component: () => import("../views/home/index.vue")
- },
- {
- path: '/login',
- name: 'login',
- component: () => import("../views/login/index.vue")
- },
- {
- path: '/car',
- name: 'car',
- component: () => import("../views/car/index.vue")
- },
- {
- path: '/news',
- name: 'news',
- component: () => import("../views/news/index.vue"),
- beforeEnter(to,from,next){
- console.log("beforeEnter",1111)
- next()
- }
- },
- {
- path: '/*',
- name: 'err',
- component: () => import("../views/err/index.vue")
- }
- ]
- const router = new VueRouter({
- mode: 'history',
- base: process.env.BASE_URL,
- routes
- })
- export default router
store下的index.js
- import Vue from 'vue'
- import Vuex from 'vuex'
- Vue.use(Vuex)//让组件的原型链中 有仓库的工具代码
- export default new Vuex.Store({
- state: {
- msg:"仓库中的数据",
- arr:[{price:18,count:2,id:123},{price:15,count:2,id:124},{price:12,count:2,id:127}]
- },
- getters: {
- total(state){
- //笔试题: 字符串去前后空格 数组去重 求总价
- return state.arr.reduce(function(n1,n2){return n1+n2.price*n2.count},0)
- }
- },
- mutations: {
- change1(state,agr2){
- console.log(agr2,6666)
- state.msg=agr2.a
- },
- change3(state,arg){
- state.arr[0].count =arg.n
- // mutations中修改仓库数据 只能在同步代码中实现 不要再异步函数中实现 否则会出现不刷新页面的情况
- }
- },
- actions: {
- },
- modules: {
- }
- })
home下面的components下的Box2.vue
- <div>
- box2组件---{{$store.state.msg}}
- <button @click="change1">box2的按钮修改msg(直接改 不推荐)button>
- <button @click="change2">box2的按钮修改msg(提交mutation)button>
- <button @click="change3">box2的按钮修改数量(提交mutation)button>
- div>
- <script>
- export default {
- methods:{
- change1(){
- // this.$store.state.msg="box2修改了仓库数据"//官方说的 不要这样直接去修改数据
- },
- change2(){
- //提交载荷
- //第1种. this.$store.commit("change1","hello,box2修改了数据")
- //第2种. this.$store.commit("change1",{a:"hello,box2修改了数据"})
- //也是2种的另外一种写法,
- this.$store.commit({type:"change1",a:"hello,box2修改了数据"})
- },
- change3(){
- this.$store.commit({type:"change3",n:10})
- // this.$store.state.arr[0].count=200
- }
- }
- }
- script>
-
- <style>
- style>
getter就就像是store的计算属性,它会传入state对象供我们操作
- const store = new Vuex.Store({
- state: {
- arr: [
- { id: 1, text: '...', birth: "1997-02-03" },
- { id: 2, text: '...', birth: "2019-10-03" }
- ]
- },
- getters: {
- bigMans(state) {
- return state.arr.filter((man)=>{
- let manY=new Date(man.birth).getFullYear()
- let nowY=new Date().getFullYear()
- return (nowY-manY)>=18
- })
- }
- }
- })
2.使用
this.$store.getters.bigMans
mutation中修改仓库数据,只能在同步代码中实现,不要在异步函数中实现,否则会出现不刷新页面的情况
修改状态的唯一方式就是提交mutations,而且是同步的
如果要异步的修改数据,就可以使用actions异步的提交mutations
组件中希望更改 Vuex 的 store 中的状态(数据)的唯一方法是提交 mutation
不要用赋值表达式直接在组件中给store设置新数据
这样设计的原因是,只有通过mutation来更新数据,它才会去帮我们通知所有使用数据的组件更新数据 刷新UI
- const store = new Vuex.Store({
- state: {
- count: 1
- },
- mutations: {
- //默认传第一个参数传state
- increment (state,obj) {
- // 变更状态
- state.count=obj.n
- }
- }
- })
2.1 第一种方式:直接触发并传值(提交载荷)
this.$store.commit('increment',{n:100})
increment是触发的函数名
2.2 第二种方式:可以以一个对象的形式传入
传入对象时,当相于把整个对象作为了第二个参数传入mutations
//第一种 this.$store.commit("increment",{a:"修改"} //第二种: this.$store.commit({ type: 'increment', n:100 })
注意:一条重要的原则就是要记住 mutation 必须是同步处理
下面是错误的方式:
mutations: { increment (state,obj) { //如果fnAsync函数是一个异步业务函数,就会导致更新失败 fnAsync(() => { state.count=obj.n }) } }
Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作。如果要异步的修改数据,就可以使用actions异步的提交mutations
- const store = new Vuex.Store({
- state: {
- count: 0
- },
- mutations: {
- increment (state,obj) {
- state.count=obj.n
- }
- },
- actions: {
- //默认第一个参数传一个跟store一样的对象
- increment (context,obj) {
- //假设fnAsync是一个异步业务函数
- fnAsync(() => {
- context.commit('increment',obj)
- })
- }
- }
- })
1.直接分发
this.$store.dispatch('increment',{n:100})
2.以对象形式分发
this.$store.dispatch({ type: 'increment', n:100 })
可用于业务分块开发:
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter
- //分块设计:
- const moduleA = {
- namespaced: true,//局部命名空间(让state的中变量与其他模块中的同名变量不冲突)
- state: { msg:1 },
- mutations: { change(state,n){state.msg=n} },
- actions: { change(context,n){context.commit("change",n)} },
- getters: { x(state){return state.msg} }
- }
-
- const moduleB = {
- namespaced: true,//局部命名空间
- state: { msg:1 },
- mutations: { change(state,n){state.msg=n} },
- actions: { change(context,n){context.commit("change",n)} },
- getters: { x(state){return state.msg} }
- }
-
- const store = new Vuex.Store({
- modules: {
- a: moduleA,
- b: moduleB
- }
- })
-
- //组件中的使用:
- this.$store.state.a.msg // -> moduleA 的状态
- this.$store.state.b.msg // -> moduleB 的状态
- this.$store.commit("a/change",100)-> moduleA 的mutations
- this.$store.commit("b/change",200)-> moduleB 的mutations
- this.$store.getters["a/x"]-> moduleA 的getters
- this.$store.getters["b/x"]-> moduleB 的getters
- this.$store.dispatch("a/change",100)-> moduleA 的actions
- this.$store.dispatch("b/change",200)-> moduleB 的actions
store下的index.js
- import Vue from 'vue'
- import Vuex from 'vuex'
- import Model1 from "./Model1.js"
- import Model2 from "./Model2.js"
- import Model3 from "./Model3.js"
- import Model4 from "./Model4.js"
- Vue.use(Vuex) //让组件的原型链中 有仓库的工具代码
-
- export default new Vuex.Store({
- state: {
- },
- getters: {
- },
- mutations: {
- },
- actions: {
- },
- modules: {
- Model1,
- Model2:Model2,
- Model3,
- Model4
- }
- })
store下的Model1.js
- export default {
- namespaced: true,//局部命名空间(让state的中变量与其他模块中的同名变量不冲突)
- state: {
- x:"张三的公共数据"
- },
- getters: {
- getx(){
- return x+"6666"
- }
- },
- mutations: {
- setxsync(state,obj){
- state.x=obj.x
- }
- },
- actions: {
- setxasync(ctx,obj){
- setTimeout(()=>{
- ctx.commit("setxsync",obj)
- },1000)
- }
- }
- }
可以拓展:
mapState,mapGetters,mapMutation,mapAction和使用常量替代 Mutation 事件类型,
使用常量替代 mutation 事件类型在各种 Flux 实现中是很常见的模式。
同时把这些常量放在单独的文件中可以让你的代码合作者对整个 app 包含的 mutation 一目了然
用不用常量取决于你——在需要多人协作的大型项目中,这会很有帮助。但如果你不喜欢,你完全可以不这样做。
下列关于 Vuex 的描述,不正确的是哪项?
A. Vuex 通过 Vue 实现响应式状态,因此只能用于 Vue
B. Vuex 是一个状态管理模式
C. Vuex 主要用于多视图间状态全局共享与管理
D. 在 Vuex 中改变状态,可以通过 mutations 和 actions选C,多视图