vuex的详细使用方式(一)
一.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.pngPS:
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.pnggetter的基本使用 和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.pngMutation的提交方式及参数传递
更改 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.pngaction 异步 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