美文网首页前端Vue.js
vuex的详细使用方式(一)

vuex的详细使用方式(一)

作者: coderhzc | 来源:发表于2021-05-22 15:33 被阅读0次

    一.VueX的基本使用

    VueX 的详细文档说明:

    第一步:

    在编辑器 或者在 PowerShell中输入 命令下载安装:

      npm install vuex --save
    

    第二步:

    在一个模块化的打包系统中,必须显式地通过 Vue.use() 来安装 Vuex:
    单独的在src 文件夹中创建一个 store 文件夹,里面写一个index.js 文件

    import Vue from 'vue'
    import Vuex from 'vuex'
    
    Vue.use(Vuex)
    

    第三步:

    Vuex 之后,让我们来创建一个 store。创建过程直截了当——仅需要提供一个初始 state 对象和一些 mutation:

    这个操作都是在 store 文件夹的index.js中完成的

    
    /*
     * @Descripttion: your project
     * @version: 1.0
     * @Author: Mr.HZC
     * @Date: 2021-05-22 14:37:50
     * @LastEditors: Aidam_Bo
     * @LastEditTime: 2021-05-22 15:24:50
     */
    import Vue from 'vue'
    import Vuex from 'vuex'
    Vue.use(Vuex)
    const store = new Vuex.Store({
      state: {
        count: 100
      },
      mutations: {
        // 这个地方的方法是你在组件内定义的 commit 提交过来的一个方法
        // 第一个参数就是vuex中的 state数据
        // 第二个参数是你从子组件传递过来的采纳数
        // increment (state, val) {
        //  state.count += val
        // }
        
        // 对象的方式来接收commit提交过来的方法
         increment(state,playload) {
            state.count = playload.num
         }
      }
    })
    
    export default store;
    
    

    第四步:

    具体的使用方式如以下代码:
    在component 或者 view 中创建2个.vue 文件

    foo组件

    <!--
     * @Descripttion: your project
     * @version: 1.0
     * @Author: Mr.HZC
     * @Date: 2021-05-22 14:25:45
     * @LastEditors: Aidam_Bo
     * @LastEditTime: 2021-05-22 15:20:37
    -->
    <template>
      <div>
        <h2> foo组件 </h2>
        <p>{{ count }}</p>
        <button @click="increment">自增加1</button>
      </div>
    </template>
    
    <script>
    export default {
      data () {
        return {
        }
      },
      methods: {
        increment () {
          // 不要在组件中直接修改vuex中的数据,
          // 为什么呢? 因为无法被调试工具记录和检测到
          // this.$store.state.count++
    
          // 这个地方是你往vuex 中提交的一个方法; 
          // 第一个参数是你向vuex中提交的一个方法,
          // 第二个参数是你向vuex中提交的参数
          this.$store.commit('increment', 10);
    
          // 使用对象的方法来提交一个事件和参数
          this.$store.commit({
              type:'increment',// type:是vue中提供的类型
              num:10 // 自定义的 num 在index.js中使用的时候 就是 playload.num 来是使用
          })
        }
      },
      computed: {
        count () {
          return this.$store.state.count
        }
      }
    }
    </script>
    
    <style>
    </style>
    
    

    bar组件

    <!--
     * @Descripttion: your project
     * @version: 1.0
     * @Author: Mr.HZC
     * @Date: 2021-05-22 14:25:58
     * @LastEditors: Aidam_Bo
     * @LastEditTime: 2021-05-22 15:22:35
    -->
    <template>
      <div>
        <h1>bar 组件</h1>
        <!-- 利用计算属性获取vueX中的count -->
        <p>{{ count }}</p>
    
        <!-- 使用函数获取 -->
        <!-- <p>{{ counte() }}</p> -->
    
        <!-- 直接使用 -->
        <p>{{ $store.state.count }}</p>
        <button @click="increment">自增加1</button>
      </div>
    </template>
    
    <script>
    export default {
      data () {
        return {
        }
      },
      methods: {
        increment () {
          // 不要在组件中直接修改vuex中的数据,
          // 为什么呢? 因为无法被调试工具记录和检测到
          // this.$store.state.count++
    
          // 这个地方是你往vuex 中提交的一个方法; 
          // 第一个参数是你向vuex中提交的一个方法,
          // 第二个参数是你向vuex中提交的参数
          this.$store.commit('increment', 10)
    
        },
    
        //使用函数获取
        // counte () {
        //   return this.$store.state.count
        // }
      },
      computed: {
        count () {
          return this.$store.state.count
        }
      }
    }
    </script>
    
    <style>
    </style>
    

    在App.vue父组件引入上面注册的组件

    <!--
     * @Descripttion: your project
     * @version: 1.0
     * @Author: Mr.HZC
     * @Date: 2021-05-22 14:22:01
     * @LastEditors: Aidam_Bo
     * @LastEditTime: 2021-05-22 14:31:03
    -->
    <template>
      <div id="app">
        <h1>hello world</h1>
        <foo></foo>
        <bar></bar>
      </div>
    </template>
    
    <script>
    import Foo from './components/foo.vue'
    import Bar from './components/bar.vue'
    export default {
      name: 'App',
      components: {
        Foo,
        Bar
      }
    
    }
    </script>
    
    <style>
    </style>
    
    

    实际截图:

    image.png

    PS:

    state:用来存储共享的数据
    mutations:用来改变state中的数据

    二. VueX的state 和 mapState函数 https://vuex.vuejs.org/zh/guide/state.html

    mapState 辅助函数的基本使用:

    第一步:

    在当前需要的组件内引入mapState,比如你创建了一个aaa.vue
    import { mapState } from "vuex"

    具体代码如下:

    aaa.vue组件的使用:

    <!--
     * @Descripttion: your project
     * @version: 1.0
     * @Author: Mr.HZC
     * @Date: 2021-05-22 15:49:49
     * @LastEditors: Aidam_Bo
     * @LastEditTime: 2021-05-22 16:20:36
    -->
    <template>
      <div>
        <h1>aaa组件</h1>
        <p>{{ count }}</p>
        <p>{{ message }}</p>
        <button @click="increment">自增加1</button>
      </div>
    </template>
    
    <script>
    import { mapState } from "vuex"
    export default {
      data () {
        return {
    
        }
      },
      methods: {
        increment () {
          this.$store.commit('increment', 10)
        }
      },
      computed: {
       // 对象的写法: 
        ...mapState({
          count: 'count',
          message: "message",
          // 完整的写法:
          //  count: state=> state.count
          // message: state=> state.message
        })
    
      // 数组的写法:
      ...mapState(['count','name'])
    
      }
    }
    </script>
    
    <style>
    </style>
    

    bbb.vue组件的使用:

    <!--
     * @Descripttion: your project
     * @version: 1.0
     * @Author: Mr.HZC
     * @Date: 2021-05-22 15:50:35
     * @LastEditors: Aidam_Bo
     * @LastEditTime: 2021-05-22 16:25:08
    -->
    <template>
      <div>
        <h1>bbb组件</h1>
        <p>{{count}}</p>
        <p>{{message}}</p>
        <button @click="increment">自增加1</button>
      </div>
    </template>
    
    <script>
    import { mapState } from 'vuex'
    export default {
      data () {
        return {
    
        }
      },
    
      methods: {
        increment () {
          this.$store.commit('increment', 100)
        }
      },
      computed: {
        /**
         * mapState 这个方法的具体使用:也就是说当你在vueX的state中要是声明了很多的变量,
         * 而你有不想使用this.$store.state每次这样去获取的话,你可以使用...mapState这个函数去获取。
         * 类似于对象的结构赋值一样,这样你就会少些很多的多余的代码
         * 
         * 基本的使用: 
         * 如果你当前的页面需要使用的话,
         * import { mapState } from "vuex"
         * 
         * 然后在computed中去使用这个函数
         * 用法如下:
         *  
         * 
         * **/
        // 但是要记住哦: 在组件内部如果使用message的话,那和vuex 中的state不是一个东西哦 
        // 如果这个是写在上面的话,...mapState函数写在下面的话 就会覆盖上面的 message
        message () {
          return "hello"
        },
        ...mapState({
          message: "message",
          count: 'count'
        }),
    
        // 但是要记住哦: 在组件内部如果使用message的话,那和vuex 中的state不是一个东西哦
        // 如果这个是写在下面的话,...mapState函数写在上面的话 就会覆盖上面的 message
        // message () {
        //   return "hello"
        // }
      }
    }
    </script>
    
    <style>
    </style>
    

    实际代码截图如下:

    image.png

    getter的基本使用 和mapGetters辅助函数的使用:https://vuex.vuejs.org/zh/guide/getters.html

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

    当每次在各个页面去计算状态值或者去修改单价的话 那种太麻烦了,你只需要在当前的 vuex页面的getter计算属性中去计算完成

    然后去你需要的页面 的 computed计算属性或者方法中去 使用mapGetters辅助函数就可以了

    具体代码如下:

    store ==> index.js文件

    /*
     * @Descripttion: your project
     * @version: 1.0
     * @Author: Mr.HZC
     * @Date: 2021-05-22 14:37:50
     * @LastEditors: Aidam_Bo
     * @LastEditTime: 2021-05-22 18:03:22
     */
    import Vue from 'vue'
    import Vuex from 'vuex'
    Vue.use(Vuex)
    const store = new Vuex.Store({
      state: {
        count: 100,
        message: "我是胡振楚",
        todos: [
          { id: 1, text: "吃饭", done: true },
          { id: 2, text: "睡觉", done: false },
          { id: 3, text: "打豆豆", done: false },
          { id: 4, text: "写代码", done: false },
        ]
      },
      mutations: {
        // 这个地方的方法是你在组件内定义的 commit 提交过来的一个方法
        // 第一个参数就是vuex中的 state数据
        // 第二个参数是你从子组件传递过来的采纳数
        increment (state, val) {
          state.count += val
        }
      },
    
      getters: {
        remaining: state => {
          console.log(state);
          return state.todos.filter(item => item.done === false).length
        },
         getTodoById: state => {
          return id => {
            return state.todos.find(item => item.id === id)
          }
        }
      }
    })
    
    export default store;
    

    ccc.vue 页面

    <!--
     * @Descripttion: your project
     * @version: 1.0
     * @Author: Mr.HZC
     * @Date: 2021-05-22 15:49:49
     * @LastEditors: Aidam_Bo
     * @LastEditTime: 2021-05-22 18:22:24
    -->
    <template>
      <div>
        <h1>ccc组件</h1>
        <!-- 使用todos -->
        <ul>
          <li v-for="item in todos"
              :key="item.id">{{ item.text }}</li>
        </ul>
    
        <p>剩余任务的数量:{{ remaining }}</p>
    
         <!-- getters可以调用函数  -->
        <h3>获取id为2的 对象的text属性</h3>
        <p>获取id为2的 对象的text属性:{{ getTodoById(2).text }}</p>
      </div>
    </template>
    
    <script>
    import { mapGetters, mapState } from "vuex"
    export default {
      data () {
        return {
    
        }
      },
      methods: {
        increment () {
          this.$store.commit('increment', 10)
        }
      },
      computed: {
        ...mapState({
          count: 'count',
          message: "message",
          todos: 'todos',
          // 完整版写法:
          // count: state=> state.count
          // message: state=> state.message
          // todos: state=> state.todos
    
    
          // 计算属性的使用:
          // 计算剩下没有完成  
          // 这种,每个页面的使用很麻烦
          // remaining: state => {
          //   console.log(state);
          //   return state.todos.filter(item => item.done === false).length
          // }
        }),
    
        /**
          * mapGetters辅助函数的使用方式是:
          *    -- 采用键值对的方式去用的
          *    -- key(对应的你页面要绑定的显示的): value(是你在getters中写的计算属性)
          *
        **/
        ...mapGetters({ 
          remaining: "remaining",
           // getters可以返回一个函数来使用
          getTodoById: "getTodoById"
        }),
    
      }
    }
    </script>
    
    <style>
    </style>
    

    ddd.vue 页面

    <!--
     * @Descripttion: your project
     * @version: 1.0
     * @Author: Mr.HZC
     * @Date: 2021-05-22 15:50:35
     * @LastEditors: Aidam_Bo
     * @LastEditTime: 2021-05-22 18:23:11
    -->
    <template>
      <div>
        <h1>ddd组件</h1>
        <!-- 使用todos -->
        <ul>
          <li v-for="item in todos"
              :key="item.id">{{ item.text }}</li>
        </ul>
    
        <p>剩余任务的数量:{{ remaining }}</p>
      </div>
    </template>
    
    <script>
    import { mapGetters, mapState } from 'vuex'
    export default {
      data () {
        return {
    
        }
      },
    
      methods: {
        increment () {
          this.$store.commit('increment', 100)
        }
      },
      computed: {
        /**
         * Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。
         * 就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
         * 
         * mapGetters 辅助函数仅仅是将 store 中的 getter 映射到局部计算属性:
         * 
         *     * * **/
        ...mapState({
          message: "message",
          count: 'count',
          todos: 'todos',
    
          // 计算属性的使用:
          // 计算剩下没有完成
          // 这种,每个页面的使用很麻烦
          // remaining: state => {
          //   console.log(state);
          //   return state.todos.filter(item => item.done === false).length
          // }
        }),
    
        // mapGetters辅助函数的使用:
        ...mapGetters({
          remaining: "remaining"
        })
    
      }
    }
    </script>
    
    <style>
    </style>
    

    ps: mapGetters辅助函数的使用:

    实际代码截图如下:

    image.png

    Mutation的提交方式及参数传递

    更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:

    Mutation 需遵守 Vue 的响应规则
    既然 Vuex 的 store 中的状态是响应式的,那么当我们变更状态时,监视状态的 Vue 组件也会自动更新。这也意味着 Vuex 中的 mutation 也需要与使用 Vue 一样遵守一些注意事项:

    1.最好提前在你的 store 中初始化好所有所需属性。

    2.当需要在对象上添加新属性时,你应该

    -- 使用 Vue.set(obj, 'newProp', 123), 或者

    -- 以新对象替换老对象。例如,利用对象展开运算符 (opens new window)我们可以这样写:

    state.obj = { ...state.obj, newProp: 123 }
    

    在组件中提交 Mutation

    你可以在组件中使用 this.$store.commit('xxx') 提交 mutation,或者使用 mapMutations 辅助函数将组件中的 methods 映射为 store.commit 调用(需要在根节点注入 store)。
    在当前的组件中另外的一种mutations的提交

    import { mapMutations } from 'vuex'
    
    export default {
      // ...
      methods: {
        ...mapMutations([
          'increment', // 将 `this.increment()` 映射为 `this.$store.commit('increment')`
    
          // `mapMutations` 也支持载荷:
          'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.commit('incrementBy', amount)`
        ]),
        ...mapMutations({
          add: 'increment' // 将 `this.add()` 映射为 `this.$store.commit('increment')`
        })
      }
    }
    

    使用常量替代 Mutation 事件类型

    使用常量替代 mutation 事件类型在各种 Flux 实现中是很常见的模式。这样可以使 linter 之类的工具发挥作用,同时把这些常量放在单独的文件中可以让你的代码合作者对整个 app 包含的 mutation 一目了然:

    具体代码截图如下:

    image.png

    action 异步 actions 的基本使用:

    Action 提交的是 mutation,而不是直接变更状态。
    Action 可以包含任意异步操作。
    index.js 文件

    /*
     * @Descripttion: your project
     * @version: 1.0
     * @Author: Mr.HZC
     * @Date: 2021-05-22 14:37:50
     * @LastEditors: Aidam_Bo
     * @LastEditTime: 2021-05-22 20:21:19
     */
    import Vue from 'vue'
    import Vuex from 'vuex'
    
    // 导入INCREMENT常量
    import { SOME_MUTATION } from "./mutation-types"
    
    
    Vue.use(Vuex)
    const store = new Vuex.Store({
      state: {
        count: 100,
        message: "我是胡振楚",
        todos: [
          { id: 1, text: "吃饭", done: true },
          { id: 2, text: "睡觉", done: false },
          { id: 3, text: "打豆豆", done: false },
          { id: 4, text: "写代码", done: false },
        ]
      },
      mutations: {
        // 这个地方的方法是你在组件内定义的 commit 提交过来的一个方法
        // 第一个参数就是vuex中的 state数据
        // 第二个参数是你从子组件传递过来的采纳数
        increment (state, { num = 1 }) {
          state.count += num
        },
    
        // SOME_MUTATION 的具体使用:
        [SOME_MUTATION] (state) {
          state.message = "你好,世界!"
        }
      },
    
      getters: {
        remaining: state => {
          console.log(state);
          return state.todos.filter(item => item.done === false).length
        },
    
        getTodoById: state => {
          return id => {
            return state.todos.find(item => item.id === id)
          }
        }
      },
      actions: {
        increment ({ commit }, { num = 1 }) {
          setTimeout(function () {
            commit({
              type: "increment",
              num
            })
          }, 1000)
        }
      }
    })
    
    export default store;
    

    eee.vue

    <!--
     * @Descripttion: your project
     * @version: 1.0
     * @Author: Mr.HZC
     * @Date: 2021-05-22 19:28:41
     * @LastEditors: Aidam_Bo
     * @LastEditTime: 2021-05-22 20:13:08
    -->
    <template>
      <div>
        <h1>eee组件</h1>
        <p>{{ count }}</p>
        <button @click="asyncIncrement">异步actions的使用</button>
      </div>
    </template>
    
    <script>
    import { mapState } from 'vuex'
    export default {
      data () {
        return {
    
        }
      },
      methods: {
        asyncIncrement () {
          this.$store.dispatch('increment', 2)
        }
    
      },
    
      computed: {
        ...mapState({
          count: "count"
        })
      }
    }
    </script>
    
    <style>
    </style>
    

    实际代码截图如下:


    image.png

    相关文章

      网友评论

        本文标题:vuex的详细使用方式(一)

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