赞
踩
https://vuex.vuejs.org/zh/
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化
Vuex是采用集中式管理组件依赖的共享数据的一个工具,可以解决不同组件数据共享问题
结论:
下载
yarn add vuex@3.5.1
src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({})
export default store
main.js引入
import store from './store/index'
new Vue({
router,
store,
render: (h) => h(App),
}).$mount('#app')
state 放置所有公共状态的属性,如果你有一个公共状态数据,你只需要定义在state对象中
// 初始化vuex对象
const store = new Vuex.Store({
state: {
// 管理数据
count: 0,
},
})
如何在组件中获取count?
Good.vue
组件中可以使用this.$store 获取到vuex中的store对象实例,可通过state属性获取count
<div>state的数据{{ $store.state.count }}</div>
<script>
export default {
created() {
console.log(this.$store.state.count)
},
}
</script>
mapState是辅助函数,帮助我们把store中的数据映射到组件的计算属性中,属于一种方便用法
List.vue
第一步:导入mapState
第二步:采用数组形式引入state属性
第三部:利用展开运算法将导出的状态映射给计算属性
<template> <div> list {{ count }} </div> </template> <script> //导入mapState import { mapState } from 'vuex' export default { //采用数组形式引入state属性 //利用展开运算法将导出的状态映射给计算属性 computed: { ...mapState(['count']), // 类似于 // count() { // return this.$store.state.count // }, }, } </script>
state数据的修改只能通过mutatons,并且mutations必须是同步更新,目的是形成数据快照
数据快照:一次mutation的执行,立刻得到一种视图状态,因为是立刻,所以必须是同步
const store = new Vuex.Store({
state: {
// 管理数据
count: 70,
},
// d定义mutations
mutations: {
}
})
mutations是一个对象,对象中存放修改state的方法
mutations: {
// 方法里的参数 第一个参数是当前store的state属性
// 第二个参数payload 运输参数 调用mutations的时候 可以传递参数
addCount(state) {
state.count += 1
},
addCountN(state, n) {
state.count += n
},
},
如何在组件中调用mutations?
Good.vue
<template> <div> state的数据{{ $store.state.count }} <hr /> <button @click="addCount">+1</button> </div> </template> <script> export default { created() { console.log(this.$store.state.count) }, methods: { addCount() { // 调用store中的mutations 提交给mutations // commit('mutations方法名',参数) this.$store.commit('addCount') }, }, } </script>
带参数的传递
<button @click="addCountN(9)">+n</button>
methods: {
addCountN(n) {
this.$store.commit('addCountN', n)
},
},
mapMutations和mapState很像,把位于mutations中的方法提取出来,可以将它导入到methods中
<template> <div> list {{ count }} <button @click="addCount">+1</button> <button @click="addCountN(8)">+n</button> </div> </template> <script> import { mapState, mapMutations } from 'vuex' export default { computed: { ...mapState(['count']), // 类似于 // count() { // return this.$store.state.count // }, }, methods: { // 把位于mutations中的方法提取出来,可以将它导入到methods中 ...mapMutations(['addCount', 'addCountN']), }, } </script>
state是存放数据的,mutations是同步更新数据,actions是负责进行异步操作
actions: {
// 获取异步的数据 context 表示当前的store实例
// 可以通过context.state 获取状态
// 也可以通过context.commit 来提交mutations
// 也可以context.dispatch调用其它的action
getAsyncCount(context) {
setTimeout(() => {
// 1秒后,要去修改state
context.commit('addCount')
}, 1000)
},
},
addAsyncCount() {
this.$store.dispatch('getAsyncCount')
},
actions
actions: {
getAsyncCountN(context, n) {
setTimeout(() => {
// 1秒后,要去修改state
context.commit('addCountN', n)
}, 1000)
},
},
调用
<button @click="addAsyncCountN(6)">+nAsync</button>
addAsyncCountN(m) {
this.$store.dispatch('getAsyncCountN', m)
},
actions也有辅助函数,可以将action导入到组件中
<template> <div> list {{ count }} <button @click="getAsyncCount">+1Async</button> <button @click="getAsyncCountN(6)">+nAsync</button> </div> </template> <script> import { mapState, mapActions } from 'vuex' export default { computed: { ...mapState(['count']), // 类似于 // count() { // return this.$store.state.count // }, }, methods: { ...mapActions(['getAsyncCount', 'getAsyncCountN']), }, } </script>
除了state之外,有时还需要从state中派生出一些状态,这些状态是依赖state的,会用到getters
state中定义了list,是1~10的数组
state: {
list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
},
组件中需要显示大于5的数据,正常的方式,是需要list在组件中进行再一步的处理,但是getters可以帮助我们实现它
getters: {
// getters函数第一个参数是state
// 必须要有返回值
filterList: (state) => state.list.fiter((item) => item > 5),
},
<ul>
<li v-for="(item, index) in $store.getters.filterList">
{{ item }}
</li>
</ul>
<template> <div> list {{ count }} <ul> <li v-for="(item, index) in filterList" :key="index">{{ item }}</li> </ul> </div> </template> <script> import { mapGetters } from 'vuex' export default { computed: { ...mapGetters(['filterList']), } } </script>
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象,当应用变得非常复杂的时候,store对象就会变得相当臃肿。
我们把所有的状态都放在state中,项目变得越来越大的时候,vuex会变得越来越难以维护------Vuex模块化
const store = new Vuex.Store({
modules: {
countModule: {
state: {
count: 0,
},
},
arrModule: {
state: {
arr: [2, 4, 67, 23, 12, 34, 68, 76],
},
},
},
})
Good.vue组件中,分别显示count 和arr
<div>count:{{ $store.state.countModule.count }}</div>
<div>
<ul>
<li v-for="item in $store.state.arrModule.arr">
{{ item }}
</li>
</ul>
</div>
注意:获取子模块的状态,通过$store.state.模块名.属性名来获取
上面的获取有点麻烦,可以getters 来改变一下
//getters是根级别的getters
getters: {
count: (state) => state.countModule.count,
arr: (state) => state.arrModule.arr,
},
组件中通过mapGetters获取数据
<template> <div> <div>count:{{ count }}</div> <ul> <li v-for="(item, index) in arr" :key="index"> {{ item }} </li> </ul> </div> </template> <script> import { mapGetters } from 'vuex' export default { computed: { ...mapGetters(['count', 'arr']), }, } </script>
namespaced 命名空间
默认情况下,模块内部的action,mutation,getter 是注册在全局命名空间的,—这样使得多个模块对同一mutation或者action作出响应
我们想要保证内部模块的高封闭性,可以采用namespaced来进行设置
const store = new Vuex.Store({ modules: { countModule: { namespaced: true, //命名空间 state: { count: 0, }, action: {}, mutations: { addCount (state) { // 这里的state表示的是countModule的state state.count++ }, }, getters: {}, } })
方法一: 直接调用-带上模块的属性名路径
this.$store.commit('countModule/addCount')
方法二:辅助函数–带上模块的属性名路径
<button @click="add">+1</button>
methods: {
...mapMutations(['countModule/addCount', 'arrModule/delArr']),
add() {
this['countModule/addCount']()
}
},
父子组件通信,单项的,很多时候需要双向通信
父组件
<Good :msg.sync="test"></Good>
子组件
<template> <div> {{ msg }} <button @click="fn">更改msg</button> </div> </template> <script> export default { props: { msg: { default: '', }, }, methods: { fn() { this.$emit('update:msg', 'world') }, }, } </script>
子组件收到对象后可以随意改变对象的属性,但是不能改变对象本身
vue2.x中,v-model语法糖的简写
<List :msg="msg" @ccEvent="fn"/>
父组件App.vue
<template> <div> <List v-model="test"></List> </div> </template> <script> import List from './views/List.vue' export default { components: { List, }, data() { return { test: 'hello', } }, } </script>
子组件 List.vue
<template> <div> {{ '值为' + msg }} <button @click="fn">更改父组件的值</button> </div> </template> <script> export default { // model 有2个属性, // prop属性将msg作为该组件被使用时,v-model能取到的值 // event 就是自定义事件 是emit('ccEvent')的时候 参数的值就是父组件v-model收到的值 model: { prop: 'msg', event: 'ccEvent', }, props: { msg: '', }, methods: { fn() { this.$emit('ccEvent', this.msg + 2) }, }, } </script>
第二种
<List :value="msg" @input="fn"/>
父组件 App.vue
<List v-model="test"></List>
子组件 List.vue
<template> <div> {{ '值为' + value }} <button @click="fn">更改父组件的值</button> </div> </template> <script> export default { props: { value: { //必须使用value default: '', }, }, methods: { fn() { // 这里必须是input发送数据, // 发送数据会被父级v-model="test" 接收到, // 再被value=test传回来 this.$emit('input', this.value + 2) }, }, } </script>
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。