Web前端之vuex基础
作者:互联网
什么是Vuex
Vuex是一个专门为Vue.js应用程序开发的一个状态管理模式,它采用了集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化
什么是状态管理模式
new Vue({
// state
data () {
return {
count: 0
}
},
// view
template: `
<div>{{ count }}</div>
`,
// actions
methods: {
increment () {
this.count++
}
}
})
状态自管理应用包含以下几个部分:
- state,驱动应用的数据源
- view,以声明方式将 state 映射到视图
- actions,响应在 view 上的用户输入导致的状态变化
单向数据流:
当遇到多个组件共享时,单向数据流的简洁性很容易被破坏
- 多个视图依赖于同一状态
- 来自不同视图的行为需要变更同一状态
使用Vuex管理数据的好处:
- 能够在 vuex 中集中管理共享的数据,便于开发和后期进行维护
- 能够高效的实现组件之间的数据共享,提高开发效率
- 存储在 vuex 中的数据是响应式的,当数据发生改变时,页面中的数据也会同步更新
Vuex使用
安装或引入
可以通过CDN节点引入(不推荐)
<script src="https://cdn.jsdelivr.net/npm/es6-promise@4/dist/es6-promise.auto.js"></script>
也可以使用npm命令进行安装(推荐)
npm install vuex -S
当然,如果在用Vue CLI 脚手架进行创建项目时,如果引用了Vuex咋不在需要上面的操作了
使用
使用时需要在新建js文件中引用,当然我们还需要在main.js中引入使用
当我们使用Vue CLI 脚手架创建项目后
我们在src目录下的views下面新建文件夹Store
在此文件夹内创建index.js文件
在index中编写如下编码
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
},
mutations: {
}
})
export default store
然后在main.js中引入调用并且创建实例
父传子
- count 变量定义在父组件 App.vue 中
- 两个子组件中都一个一个 prop,名为 count
- 父组件通过 :count 为子组件中的 prop count 传值
- 子组件单击按钮时,通过 $emit,向外广播,告诉父组件应该为 count 变量+1或者 -1
Add.vue
<template>
<div id="app">
<my-add :count="count" @handle-add="add"></my-add> <my-sub
:count="count"
@handle-sub="del"
></my-sub>
</div>
</template>
<script>
import c1 from './views/children'
import c2 from './views/children1'
export default {
data() {
return {
count: 0
}
},
components: {
'my-add': c1,
'my-sub': c2
},
methods: {
add() {
this.count++
},
del() {
this.count--
}
}
}
</script>
children.vue
<template>
<div class="main">
<h3>变量 count 的值为:{{ count }}</h3>
<button @click="add">+1</button>
</div>
</template>
<script>
export default {
props: ['count'],
methods: {
add() {
this.$emit('add')
}
}
}
</script>
children1.vue
<template>
<div class="main">
<h3>变量 count 的值为:{{ count }}</h3>
<button @click="sub">-1</button>
</div>
</template>
<script>
export default {
props: ['count'],
methods: {
sub() {
this.$emit('del')
}
}
}
</script>
加加减减的写法
index.js文件
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
add(state) {
state.count++
},
del(state) {
state.count--
}
}
})
export default store
修改组件
<template>
<div class="main">
<h3>变量 count 的值为:{{ $store.state.count }}</h3>
<button @click="add">+1</button>
<button @click="del">-1</button>
</div>
</template>
<script>
export default {
methods: {
add() {
this.$store.commit('add')
},
del() {
this.$store.commit('del')
}
}
}
</script>
效果:
核心
states
单一状态树
State提供唯一的公共数据源,所有共享的数据都要统一放到Store中的State中存储
vuex 中的 state 相当于组件中的 data
State中的数据与组件 data 中的数据一样,也是响应式的
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
name: '张三',
age: 20,
sex: '男'
}
})
export default store
组件使用state中的值
<template>
<div class="home">{{ $store.state }}</div>
</template>
<script>
export default {
}
</script>
计算属性
上面原样使用不方便使用所以使用计算属性来便于使用
<template>
<div class="home">
<p>{{ name }}</p>
<p>{{ age }}</p>
<p>{{ sex }}</p>
</div>
</template>
<script>
export default {
computed: {
name() {
return this.$store.state.name
},
age() {
return this.$store.state.age
},
sex() {
return this.$store.state.sex
}
}
}
</script>
但上面那样使用代码量太多
我们可以使用辅助函数:mapState
<template>
<div class="home">
<p>{{ name }}</p>
<p>{{ age }}</p>
<p>{{ sex }}</p>
</div>
</template>
<script>
// 在vuex中引出mapState辅助函数
import { mapState } from 'vuex'
export default {
computed: mapState({
name: state => state.name,
age: state => state.age,
sex: state => state.sex
})
}
</script>
- computed 的值是一个对象,所以 mapState 函数的返回值一定是个对象
- name,age,sex都是计算属性的名称
- 使用箭头函数时,可以省略 this.$store,而是直接使用 state
再次简洁一步
<template>
<div class="home">
<p>{{ name }}</p>
<p>{{ age }}</p>
<p>{{ sex }}</p>
</div>
</template>
<script>
// 在vuex中引出mapState辅助函数
import { mapState } from 'vuex'
export default {
computed: mapState({
name: 'name',
age: 'age',
sex: 'sex'
})
}
</script>
最简洁方法:
映射的计算属性的名称与 state 的子节点名称相同时,我们可以给 mapState 传一个字符串数组
<template>
<div class="home">
<p>{{ name }}</p>
<p>{{ age }}</p>
<p>{{ sex }}</p>
</div>
</template>
<script>
// 在vuex中引出mapState辅助函数
import { mapState } from 'vuex'
export default {
computed: mapState(['name', 'age', 'sex'])
}
</script>
- 这时候我们的计算属性就不能叫 name、age、sex了,而是与 state 中的属性同名
- mapState 中不是一个对象了,而是一个数组,数组的元素名称就是你想要使用的 state 中的属性名称
展开运算符
使用辅助函数后,mapState 函数的返回值是一个对象
<template>
<div class="home">
<p>{{ name }}</p>
<p>{{ age }}</p>
<p>{{ sex }}</p>
</div>
</template>
<script>
// 在vuex中引出mapState辅助函数
import { mapState } from 'vuex'
export default {
computed: mapState(['name', 'age', 'sex']),
created() {
const res = mapState(['name', 'age', 'sex'])
console.log(res)
}
}
</script>
输出结果
所以利用展开运算符可以更改上面的编码
<template>
<div class="home">
<p>{{ name }}</p>
<p>{{ age }}</p>
<p>{{ sex }}</p>
</div>
</template>
<script>
// 在vuex中引出mapState辅助函数
import { mapState } from 'vuex'
export default {
computed: { ...mapState(['name', 'age', 'sex']) }
}
</script>
但是我感觉用在这里,那简直的画蛇添足、多此一举了
不过展开运算符用在其他地方还是很有必要的
Getter数据获取器
在Store文件夹下index.js添加
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
teacher: [
{
name: '张三',
age: 20,
sex: '男'
},
{
name: '李四',
age: 25,
sex: '女'
}
]
},
getters: {
// 定义gettter,统计所有完成的事项
doneTodos: state => {
return state.teacher.filter(t => t.sex)
}
}
})
export default store
组件中
<template>
<div class="home">
{{ $store.getters.doneTodos }}
</div>
</template>
<script>
export default {
}
</script>
也可使用 mapGetters 和 mapState 辅助函数
<template>
<div class="home">
<p>{{ doneTodos }}</p>
<p>{{ teacher }}</p>
</div>
</template>
<script>
// 在vuex中引出mapState辅助函数
import { mapState, mapGetters } from 'vuex'
export default {
computed: {
...mapState(['teacher']),
...mapGetters(['doneTodos'])
}
}
</script>
Mutation
更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)
这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数:
任何时候想添加新值,且不能直接添加,只有通过mutation才可
Store 下的 index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
teacher: [
{
name: '张三',
age: 20,
sex: '男'
},
{
name: '李四',
age: 25,
sex: '女'
}
]
},
getters: {
// 定义gettter,统计所有完成的事项
doneTodos: state => {
return state.teacher.filter(t => t.sex)
}
},
mutations: {
add(state) {
state.teacher.push({
name: '王五',
age: 19,
sex: '女'
})
}
}
})
export default store
组件
<template>
<div class="home">
<p>{{ doneTodos }}</p>
<p>{{ teacher }}</p>
<button @click="add">添加</button>
</div>
</template>
<script>
// 在vuex中引出mapState辅助函数
import { mapState, mapGetters } from 'vuex'
export default {
computed: {
...mapState(['teacher']),
...mapGetters(['doneTodos'])
},
methods: {
add() {
this.$store.commit('add')
}
}
}
</script>
提交载荷
传入额外的参数,即 mutation 的 载荷(payload)
index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
teacher: [
{
name: '张三',
age: 20,
sex: '男'
},
{
name: '李四',
age: 25,
sex: '女'
}
]
},
getters: {
// 定义gettter,统计所有完成的事项
doneTodos: state => {
return state.teacher.filter(t => t.sex)
}
},
mutations: {
add(state, teacher) {
state.teacher.push(teacher)
}
}
})
export default store
组件中使用
<template>
<div class="home">
<p>{{ doneTodos }}</p>
<p>{{ teacher }}</p>
<button @click="add">添加</button>
</div>
</template>
<script>
// 在vuex中引出mapState辅助函数
import { mapState, mapGetters } from 'vuex'
export default {
computed: {
...mapState(['teacher']),
...mapGetters(['doneTodos'])
},
methods: {
add() {
this.$store.commit('add', {
name: '王五',
age: 19,
sex: '女'
})
}
}
}
</script>
大多数情况下,载荷应该是一个对象,可以包含多个字段并且记录的 mutation 会更易读Mutation 必须是同步函数:不要在其中执行ajax 等异步操作
mapMutations辅助函数减少代码
组件中作如下修改
<template>
<div class="home">
<p>{{ doneTodos }}</p>
<p>{{ teacher }}</p>
<button @click="addI">添加</button>
</div>
</template>
<script>
// 在vuex中引出辅助函数
import { mapState, mapGetters, mapMutations } from 'vuex'
export default {
computed: {
...mapState(['teacher']),
...mapGetters(['doneTodos'])
},
methods: {
...mapMutations(['add']),
addI() {
this.add({ name: '王五', age: 19, sex: '女' })
}
}
}
</script>
Action
Action 类似于 mutation,不同在于:
- Action 提交的是 mutation,而不是直接变更状态
- Action 可以包含任意异步操作
js文件中
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
teacher: [
{
name: '张三',
age: 20,
sex: '男'
},
{
name: '李四',
age: 25,
sex: '女'
}
]
},
getters: {
// 定义gettter,统计所有完成的事项
doneTodos: state => {
return state.teacher.filter(t => t.sex)
}
},
mutations: {
add(state, teacher) {
state.teacher.push(teacher)
}
},
actions: {
addS(state, teacher) {
setTimeout(() => {
state.commit('add', teacher)
}, 2000)
}
}
})
export default store
组件中
<template>
<div class="home">
<p>{{ doneTodos }}</p>
<p>{{ teacher }}</p>
<button @click="addI">添加</button>
</div>
</template>
<script>
// 在vuex中引出辅助函数
import { mapState, mapGetters, mapMutations } from 'vuex'
export default {
computed: {
...mapState(['teacher']),
...mapGetters(['doneTodos'])
},
methods: {
...mapMutations(['add']),
addI() {
// this.add({ name: '王五', age: 19, sex: '女' })
this.$store.dispatch('addS', { name: '王五', age: 19, sex: '女' })
}
}
}
</script>
mapActions 辅助函数映射使用
组件中
<template>
<div class="home">
<p>{{ doneTodos }}</p>
<p>{{ teacher }}</p>
<button @click="addI">添加</button>
</div>
</template>
<script>
// 在vuex中引出辅助函数
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'
export default {
computed: {
...mapState(['teacher']),
...mapGetters(['doneTodos'])
},
methods: {
...mapMutations(['add']),
...mapActions(['addS']),
addI() {
// this.add({ name: '王五', age: 19, sex: '女' })
this.addS({ name: '王五', age: 19, sex: '女' })
}
}
}
</script>
methods: {
...mapMutations(['add']),
addI() {
// this.add({ name: '王五', age: 19, sex: '女' })
this.$store.dispatch('addS', { name: '王五', age: 19, sex: '女' })
}
}
}
</script>
mapActions 辅助函数映射使用
组件中
<template>
<div class="home">
<p>{{ doneTodos }}</p>
<p>{{ teacher }}</p>
<button @click="addI">添加</button>
</div>
</template>
<script>
// 在vuex中引出辅助函数
import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'
export default {
computed: {
...mapState(['teacher']),
...mapGetters(['doneTodos'])
},
methods: {
...mapMutations(['add']),
...mapActions(['addS']),
addI() {
// this.add({ name: '王五', age: 19, sex: '女' })
this.addS({ name: '王五', age: 19, sex: '女' })
}
}
}
</script>
标签:Web,name,前端,sex,mapState,state,vuex,age 来源: https://blog.csdn.net/blue_698/article/details/115310175