前端Vue.js

vuex的详细使用方式(一)

2021-05-22  本文已影响0人  coderhzc

一.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
上一篇下一篇

猜你喜欢

热点阅读