Loading

Vuex

【一】了解Vuex

【1】想象一个场景

如果你的项目里有很多页面(组件/视图),页面之间存在多级的嵌套关系,此时,这些页面假如都需要共享一个状态的时候,此时就会产生以下两个问题:

  • 多个视图依赖同一个状态
  • 来自不同视图的行为需要变更同一个状态

【2】解决方案

​ 对于第一个问题,假如是多级嵌套关系,你可以使用父子组件传参进行解决,虽有些麻烦,但好在可以解决;对于兄弟组件或者关系更复杂组件之间,就很难办了,虽然可以通过各种各样的办法解决,可实在很不优雅,而且等项目做大了,代码就会变成屎山,实在令人心烦。

​ 对于第二个问题,你可以通过父子组件直接引用,或者通过事件来变更或者同步状态的多份拷贝,这种模式很脆弱,往往使得代码难以维护,而且同样会让代码变成屎山。

【3】换一种思路

​ 把各个组件都需要依赖的同一个状态抽取出来,在全局使用单例模式进行管理

​ 在这种模式下,任何组件都可以直接访问到这个状态,当状态发生改变时,所有组件都发生更新

【4】vuex的诞生

​ 这就是 Vuex 背后的基本思想,借鉴了 Flux、Redux。与其他模式不同的是,Vuex 是专门为 Vue 设计的状态管理库,以利用 Vue.js 的细粒度数据响应机制来进行高效的状态更新。

【5】什么时候该用vuex

​ 这个问题因人而异,如果你不需要开发大型的单页应用,此时你完全没有必要使用vuex,比如你的页面就两三个,使用vuex后增加的文件比你现在的页面还要多,那就没这个必要了。

​ 假如你的项目达到了中大型应用的规模,此时您很可能会考虑如何更好地在组件外部管理状态,Vuex 将会成为自然而然的选择。

【二】安装Vuex

进入项目,在命令行输入安装指令

npm install vuex --save

然后配置 vuex,使其工作起来:在src路径下创建store文件夹,然后创建index.js文件,文件内容如下:

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

Vue.use(Vuex);

const store = new Vuex.Store({
  state: {
    // 定义一个name,以供全局使用
    name: '张三',
    // 定义一个number,以供全局使用
    number: 0,
    // 定义一个list,以供全局使用
    list: [
      { id: 1, name: '111' },
      { id: 2, name: '222' },
      { id: 3, name: '333' },
    ],
  },
});

export default store;


修改main.js

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

Vue.use(Vuex)

export default new Vuex.Store({
    state: {
        // 定义一个name,以供全局使用
        name: 'hqq'
    },
})

最后修改APP.vue

export default {
  name: 'HomeView',
  data() {
    return {}
  },
  methods: {},
  created() {
    console.log('全局', this.$store.state.name)
  },


}
</script>

此时,启动项目,打开控制台就会发现输出了在store里面定义的name值

  • 官方建议我们以上操作this.$store.state.XXX最好放在计算属性中,当然,我也建议你这么使用,这样可以让你的代码看起来更优雅一些,就像这样:
export default {
  name: 'HomeView',
  data() {
    return {}
  },
  methods: {},
  computed: {
    getName() {
      return this.$store.state.name
    }
  },
  created() {
    console.log('计算属性', this.getName)
  },


}
</script>

此时就可以得到在控制台得到一样的效果

【三】修饰器Getter

【1】场景

getter时一个读取操作的修饰利器,

假设一个场景,

  • 你已经将store的name全部都展示到页面上了,
  • 此时产品经理说把所有的name前面都加上hello
  • 这是如果没有别的办法就只能在每个页面上使用this.$store.state.name获取到值之后,进行遍历,前面追加"hello"。

这样做很不好,原因如下

  • 代码冗余
  • 如果下次有其他需求,要把hello改成hi,又要进行很大的修改

【2】使用

所以这时候getter就登场了,它可以从源头解决问题,它可以把state里的数据放到一个方法里面,得到返回值,如果有修改需求,只需要修改这个方法的返回值即可

首先,在store对象中增加getters属性

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

Vue.use(Vuex)

export default new Vuex.Store({
    state: {
        // 定义一个name,以供全局使用
        name: 'hqq'
    },
    getters: {
        getMessage(state) {
            // 获取修饰后的name,第一个参数为必要参数,得到的就是state对象
            return `大帅哥${state.name}`
        }
    }
})

在组件中使用

export default {
  name: 'HomeView',
  methods: {},
  created() {
    console.log(this.$store.getters.getMessage)
  },
}

【四】修改值Mutation

说到修改,大多数人会想到直接得到值然后=赋值修改

this.$store.state.XXX = XXX;

这样做确实可以达到效果,但是不好,vuex开放了专门的接口提供给我们修改

修改store/index.js

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

Vue.use(Vuex)

export default new Vuex.Store({
    state: {
        // 定义一个name,以供全局使用
        name: 'hqq'
    },
    getters: {
        getMessage(state) {
            // 获取修饰后的name,第一个参数为必要参数
            return `大帅哥${state.name}`
        }
    },
    // 改值用的
    mutations: {
        // 第一个参数是state对象,第二个参数放要修改的值
        setName(state, name) {
            state.name = name
        }
    },
})

修改APP.vue

export default {
  name: 'HomeView',
  created() {
    this.$store.commit('setName', 'green')
  },
}

【五】异步操作Actions

​ Actions存在的意义是假设你在修改state的时候有异步操作,vuex作者不希望你将异步操作放在Mutations中,所以就给你设置了一个区域,让你放异步操作,这就是Actions

修改store/index.js

const store = new Vuex.Store({
  state: {
    name: '张三',
    number: 0,
  },
  mutations: {
    setNumberIsWhat(state, payload) {
      state.number = payload.number;
    },
  },
  actions: {
    // 增加actions属性
    setNum(content) {
      // 增加setNum方法,默认第一个参数是content,其值是复制的一份store
      return new Promise(resolve => {
        // 我们模拟一个异步操作,1秒后修改number为888
        setTimeout(() => {
          content.commit('setNumberIsWhat', { number: 888 });
          resolve();
        }, 1000);
      });
    },
  },
});

修改App.vue

async mounted() {
  console.log(`旧值:${this.$store.state.number}`);
  await this.$store.dispatch('setNum');
  console.log(`新值:${this.$store.state.number}`);
},
posted @ 2024-05-04 19:33  HuangQiaoqi  阅读(3)  评论(0编辑  收藏  举报