美文网首页
Vue学习笔记-Vuex使用

Vue学习笔记-Vuex使用

作者: 31313_iOS | 来源:发表于2020-12-14 09:19 被阅读0次

    一、 安装

    npm install vuex --save
    

    或者

    yarn add vuex
    

    二、创建Vuex和注入到Vue实例对象

    Vuex 使用单一状态树(用一个对象就包含了全部的应用层级状态)。每个应用将仅仅包含一个 store 实例。

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    // 1.注册插件到Vue
    Vue.use(Vuex)
    
    // 2.创建对象
    const store = new Vuex.Store({
       state: { //状态
         //在这里创建共享数据 对象必须是纯粹的对象 (含有零个或多个的 key/value 对):
       },
       mutations: {//操作方法 同步操作
          
       },
       actions: {//操作方法 异步操作 可以存放网络请求
        
       },
       getters: { //计算属性,可以对state里面的数据进行一些操作 不可以接收外面的参数
    
       },
       modules: { //模块 对于多种状态的的模块导入
          //由于每个应用将仅仅包含一个 store 实例,所以在这里就可以进行导入不同状态模块导入
       }
    })
    // 3.导出对象
    export default store;
    

    在main.js的vue实例对象中注入store,这种方式允许你在组件中以this.$store的方式访问Property

    import Vue from 'vue'
    import App from './App.vue'
    import store from './store'
    
    Vue.config.productionTip = false
    
    new Vue({
      store,
      render: h => h(App),
    }).$mount('#app')
    
    

    三、使用

    1、State的使用

    State中定义一个name属性用于全局共享

    const store = new Vuex.Store({
       state: { //状态
          name: 'Passer'
       }
    })
    

    在组件里使用

    <template>
       <div>
          <h2>姓名: {{$store.state.name}}</h2>
       </div>
    </template>
    

    或者按照官方推荐的方式在组件的计算属性当中获取

    <template>
       <div>
          <h2>姓名: {{storeName}}</h2>
       </div>
    </template>
    
    <script>
    export default {
       computed: {
          storeName() {
             return this.$store.state.name
          }
       }
    }
    </script>
    
    

    2. Getters的使用

    • Getter 接受 state 作为其第一个参数;
    • Getter 也可以接受其他 getter 作为第二个参数;
    • Getter不没有办法直接传值,如果需要传值就需要方法方式访问;

    注意: getter 在通过属性访问时是作为 Vue 的响应式系统的一部分缓存其中的; 通过方法方式访问每次都会去进行调用,而不会缓存结果。

    假如现在需要在 视图展示name的时候前面加上:Hello,而且多处使用了这中格式

    方式一:通过获取this.$store.state.name,自己拼接上“ Hello,”,在每个使用到的地方都这样操作

    <script>
    export default {
       computed: {
          storeName() {
             return 'Hello,' + this.$store.state.name
          }
       }
    }
    </script>
    
    

    方式二: 通过Getters 定义一个计算属性showName ,通过属性的方式访问。

    getters: { //计算属性,可以对state里面的数据进行一些操作 不可以接收外面的参数
         showName(state) {
             return 'Hello,' + state.name
          },
       },
    

    现在使用的时候就从getters里面获取showName属性,$store.getters. showName

    <template>
       <div>
          <h2>姓名: {{$store.getters. showName}}</h2>
       </div>
    </template>
    

    方法方式访问Getters并传参

    getters: { //计算属性,方式访问Getters并传参,结果不会被缓存
         showName(state) =>(preStr)  => {
             return preStr + state.name
          },
       }
    

    使用

    <template>
       <div>
          <h2>姓名: {{$store.getters. showName('Hello,')}}</h2>
       </div>
    </template>
    

    3. Mutations的使用

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

    • mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)

    • 接收 state 作为第一个参数

    • Payload(载荷)作为它的第二个参数,Payload应该是一个对象,这样可以包含多个字段并且记录的 mutation 会更易读,也可以是单个值。

    • 字符串的 事件类型 (type) ,官方建议定义成字符串常量,在使用到的地方统一使用CHANGE_NAME来替换 changeName

    export const CHANGE_NAME = 'changeName'
    

    假如现在需要修改name的值,那我们可以这样做

    mutations: {//操作方法 同步操作
          //[CHANGE_NAME](state, payload) {} 统一定义了以后就可以使用 CHANGE_NAME
          changeName(state, payload) {
                // 单值方式传参来提交修改
                state.name = payload
              //对象的方式来提交修改
               state.name = payload.name
          }
    }
    

    我们在mutations里注册的是changeName事件类型 (type) ,所以使用如下

    <template>
       <div>
          <h1>姓名:{{$store.getters. showName('Hello,')}}</h1>
          <button @click="onChange">修改name</button>
       </div>
    </template>
    <script>
    export default {
       methods: {
          onChange() {
              //'newName'为我们要给共享name赋的值 有3种方式
              //1.单值方式传参提交
              this.$store.commit('changeName', 'newName')
    
               //2.传对象参数提交
              this.$store.commit('changeName', {name: 'newName'})
    
              //3.对象风格的提交方式
               this.$store.commit({ 
                  type: 'changeName',
                  name: 'newName'
              })
          }
       }
    }
    </script>
    

    4. Actions的使用

    • Action 提交的是 mutation,而不是直接变更状态。
    • Action 可以包含任意异步操作。
    • Action接受一个与 store 实例具有相同方法和属性的 context 对象

    我们这里还是现实修改名字的功能,通过actions来实现

    actions: {//操作方法 同步操作
     //context 与 store 实例具有相同方法和属性的
      achangeName(context, payload) {
        context.commit('changeName', payload)
      }
    }
    

    使用的地方就不是直接this.$store.commit,而是通过 this.$store.dispatch 方法触发

    <template>
       <div>
          <h1>姓名:{{$store.getters. showName('Hello,')}}</h1>
          <button @click="onChange">修改name</button>
       </div>
    </template>
    <script>
    export default {
       methods: {
          onChange() {
              //'newName'为我们要给共享name赋的值 有3种方式
              //1.单值方式传参提交
             this.$store.dispatch('achangeName', count)
    
               //2.传对象参数提交
              this.$store.dispatch('achangeName', {name: 'newName'})
    
              //3.对象风格的提交方式
               this.$store.dispatch({ 
                  type: 'achangeName',
                  name: 'newName'
              })
    
              //异步Promise的结合获取返回状态
               this.$store.dispatch({ 
                  type: 'achangeName',
                  name: 'newName'
              }).then(res => {
                console.log(res); //'3333'
              })
          }
       }
    }
    </script>
    

    当然因为上面的修改方式为同步修改,所以看起来还不如使用mutations来实现就好,但是假如我们的姓名是从服务器分发下来的,我们需要在触发action的时候异步获取姓名来修改,那么这个时候action就开始发挥作用力,它也是就是为这个而生的。
    异步操作时为了可以通知调用的地方状态,一般会与Promise结合使用!

    actions: {//操作方法
     //context 与 store 实例具有相同方法 和属性的
      achangeName(context, payload) {
        return new Promise((resolve) => {
            //setTimeout来模拟异步操作
           setTimeout(() => {
              context.commit('changeName', payload)
              resolve('3333')
           }, 2000)
         })
      }
    }
    

    5. Modules的使用

    由于使用单一状态树,应用的所有状态会集中到一个对象。store 对象就有可能变得相当臃肿,而
    Vuex 允许我们将 store 分割成模块(module)
    每个模块拥有自己的 statemutationactiongetter、甚至是嵌套子模块——从上至下进行同样方式的分割:
    如下就是分离的模块moduleA:

    const moduleA = {
       state: {...},
       mutations: {//操作方法 同步操作 ... },
       actions: {//操作方法 异步操作 可以存放网络请求 ... },
       getters: { //计算属性,可以对state里面的数据进行一些操作 不可以接收外面的参数 ...}
    }
    export default moduleA;
    

    引用到Store

    import moduleA from './moduleA'
    // 1.注册插件
    Vue.use(Vuex)
    // 2.创建对象
    const store = new Vuex.Store({
       modules: { //模块 对于多种状态的的模块导入
          moduleA
       }
    })
    // 3.导出对象
    export default store;
    

    moduleA模块:

    • 内部的 mutationgetter接收的第一个参数是模块的局部状态对象state
    • 内部的action局部状态就通过context.state来获取,根节点的状态则为 context.rootState
    const moduleA = {
       state: {...},
       actions: {//操作方法 异步操作 可以存放网络请求 ... 
             moduleAdd(context, count) {
                 context.state  -> 局部state,也就是moduleA定义的state
                 context.rootState  -> 根节点的state
                count  -> 接收的参数
            }
        }
    }
    
    

    未完,待续...

    相关文章

      网友评论

          本文标题:Vue学习笔记-Vuex使用

          本文链接:https://www.haomeiwen.com/subject/vypaiktx.html