简介
非关系型组件的数据共享
- Vuex(状态共享框架)
Vuex 是采用集中式管理组件依赖的共享数据的一个工具,可以解决不同组件数据共享的问题
- state - 存储共享状态数据,可以在组件中引用
- mutations - 修改 state 必须通过 mutations ,只能执行同步代码,类似 ajax ,定时器之类的代码不能在 mutations 中执行
- actions - 执行异步操作,数据提交给 mutations 进行修改
- 组件 - 组件调用 action
步骤
- 创建项目
// vue 命令
vue create demo
- 选择模式
- 下载相关依赖
// 运行时依赖,命令二选一
// npm i vuex --save
npm i vuex -S
- 初始化及注册
// src/main.js
import Vue from 'vue'
import App from './App.vue'
import Vuex from 'vuex'
Vue.config.productionTip = false
Vue.use(Vuex)
const store = new Vuex.Store({})
new Vue({
render: h => h(App),
store // es6写法
}).$mount('#app')
Vuex - state
state 是存放所有公共状态的属性
定义
const store = new Vuex.Store({
// 实例化Vuex的构造参数 state mutations actions
state: {
// 存储的状态
count: 0
}
})
使用 - 原始形式
// src/App.vue
<template>
<div>
<!-- 原始形式应用 -->
<div>原始形式获取state状态:{{ $store.state.count }}</div>
</div>
</template>
<script>
export default {}
</script>
<style></style>
// 项目启动命令
npm run serve
【如果项目启动报错,看 package.json 中的命令配置】
效果
使用 - 计算属性
- 使用
// src/App.vue
<template>
<div>
<p>计算属性状态:{{ count }}</p>
</div>
</template>
<script>
export default {
computed: {
count () {
return this.$store.state.count
}
}
}
</script>
- 效果
使用 - 辅助函数( mapState )
mapStatus - 辅助函数,用于把 store 中的数据映射到组件的计算属性中,属于一种简便用法
- 步骤
// src/App.vue
<template>
<div>
<p>计算属性状态:{{ count }}</p>
</div>
</template>
<script>
import { mapState } from 'vuex' // 导入mapState
export default {
computed: {
// 利用延展运算符将导出的状态映射给计算属性
...mapState(['count']) // 采用数组形式引入state属性
}
}
</script>
- 效果
Vuex - mutations
state 数据的修改只能通过 mutations,并且 mutations 必须是同步更新,目的是形成 数据快照
数据快照 - 一次 mutation 的执行,立即得到一种视图状态,因为是立即,所有必须是同步定义 mutation
不能写异步代码,如果有异步的 ajax 请求,应放到 actions 中
使用 - 原始形式
组件内使用
步骤
// src/main.js
import Vue from 'vue'
import App from './App.vue'
import Vuex from 'vuex' // 引入
Vue.config.productionTip = false
Vue.use(Vuex) // 注册 Vuex 的功能
// 实例化一个Vuex
const store = new Vuex.Store({
// 实例化Vuex的构造参数 state mutations actions
state: {
// 存储的状态
count: 0
},
mutations: {
addCount (state) {
state.count += 1
},
}
})
// src\components\chila-a.vue
<template>
<button @click="test">+1</button>
</template>
<script>
export default {
methods: {
test () {
this.$store.commit("addCount")
}
}
}
</script>
// src\App.vue
<template>
<div>
<div>原始形式获取state状态:{{ $store.state.count }}</div>
<p>计算属性状态:{{ count }}</p>
<ChildA />
</div>
</template>
<script>
import { mapState } from 'vuex' // 导入mapState
import ChildA from './components/chila-a.vue'
export default {
components: {
ChildA,
},
computed: {
// 利用延展运算符将导出的状态映射给计算属性
...mapState(['count']) // 采用数组形式引入state属性
}
}
</script>
效果
使用 - 原始形式(传参)
代码
// src\main.js
import Vue from 'vue'
import App from './App.vue'
import Vuex from 'vuex' // 引入
Vue.config.productionTip = false
Vue.use(Vuex) // 注册 Vuex 的功能
// 实例化一个Vuex
const store = new Vuex.Store({
state: {
// 存储的状态
count: 0
},
// 修改state必须通过mutations
mutations: {
// 修改state的mutation方法
addCount (state, payload) {
state.count += payload
},
}
})
new Vue({
render: h => h(App),
store // es6写法
}).$mount('#app')
// src\components\chila-a.vue
<template>
<button @click="test">+10</button>
</template>
<script>
export default {
methods: {
test () {
this.$store.commit("addCount", 10)
}
}
}
</script>
效果
使用 - 辅助函数(mapMutations)
代码
// src\components\chila-a.vue
<template>
<div>
<button @click="test">+1(原始形式)</button>
<!-- vue 中方法的默认第一个参数,事件参数对象 -->
<button @click="addCount(100)">+100(辅助函数)</button>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
export default {
methods: {
// 原始方式调用
test () {
this.$store.commit("addCount", 1)
},
...mapMutations(['addCount']) // 此时组件方法中就会拥有一个对应的addCount方法
}
}
</script>
效果
【扩展】使用 $event 事件参数对象
代码
// src\components\chila-a.vue
<button @click="addCount($event)">+100(辅助函数)</button>
效果
Vuex - actions
state 是存放数据的,mutations 是同步更新数据,actions 则负责进行异步操作
定义
// src\main.js
import Vue from 'vue'
import App from './App.vue'
import Vuex from 'vuex' // 引入
Vue.config.productionTip = false
Vue.use(Vuex) // 注册 Vuex 的功能。 Vue.use的方法实际上是调用了 Vuex 中的一个 install 的方法
// 实例化一个Vuex
const store = new Vuex.Store({
state: {
// 存储的状态
count: 0
},
// 修改state必须通过mutations
mutations: {
// 修改state的mutation方法
addCount (state, payload) {
state.count += payload
},
},
// 异步操作
actions: {
// 方法
getAsyncCount (context) {
// 模拟异步请求
setTimeout(function () {
// 获取到一个值
context.commit("addCount", 123)
}, 1000)
},
}
})
new Vue({
render: h => h(App),
store // es6写法
}).$mount('#app')
使用 - 原始调用
步骤
// src\components\chila-a.vue
<template>
<div>
<button @click="test1">异步调用(原始形式)</button>
</div>
</template>
<script>
export default {
methods: {
test1 () {
// 原始形式
this.$store.dispatch('getAsyncCount')
},
}
}
</script>
效果
使用 - 原始调用(传参)
步骤
// src\main.js
actions: {
getAsyncCount (context, params) {
// 做异步的请求
setTimeout(function () {
// 获取到一个值
context.commit("addCount", params)
}, 1000)
},
}
// src\components\chila-a.vue
methods: {
test1 () {
this.$store.dispatch('getAsyncCount', 111)
},
}
效果
使用 - 辅助函数
将 action 导入数组中
步骤
// src\components\chila-a.vue
<template>
<div>
<button @click="getAsyncCount(222)">异步调用(辅助函数)</button>
</div>
</template>
<script>
import { mapActions } from 'vuex'
export default {
methods: {
test1 () {
// 原始形式
// commit 是提交 mutations
// dispatch 调用 action
// dispatch(action的名称)
this.$store.dispatch('getAsyncCount', 111)
},
...mapActions(['getAsyncCount']) // 引入异步的 action
}
}
</script>
效果
Vuex - getters
除了 state 之外,有时我们还需要从 state 中派生出一些状态,这些状态是依赖 state 的(需要再异一步进行处理),所以会用到 getters
定义
// src\main.js
const store = new Vuex.Store({
state: {
// 存储的状态
count: 0,
list: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
},
getters: {
// 放置的所有的Vuex的计算属性
// state:当前 store 中的 state
// filterList: function (state) {
// return state.list.filter(item => item > 5)
// },
filterList: state => state.list.filter(item => item > 5)
},
})
使用 - 原始形式
步骤
// src\components\chila-a.vue
<template>
<div>
<div>原始形式getters: {{ $store.getters.filterList }}</div>
</div>
</template>
效果
使用 - 辅助函数(mapGetters)
步骤
// Asrc\components\chila-a.vue
<template>
<div>
<div>原始形式getters: {{ $store.getters.filterList }}</div>
<div>辅助形式getters: {{ filterList }}</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
computed: {
// 将getters中的计算属性导入到组件的计算属性中
...mapGetters(['filterList'])
},
}
</script>
效果
Vuex - Module(模块化)
使用 - 简单应用
定义
// src\main.js
import Vue from 'vue'
import App from './App.vue'
import Vuex from 'vuex' // 引入
Vue.config.productionTip = false
Vue.use(Vuex) // 注册 Vuex 的功能
// 实例化一个Vuex
const store = new Vuex.Store({
modules: {
// 放置子模块的属性
user: {
state: {
token: '12345'
},
},
setting: {
state: {
name: 'Vuex实例'
},
}
}
})
new Vue({
render: h => h(App),
store // es6写法
}).$mount('#app')
步骤
$store.state.子模块.属性
// src\components\chila_b.vue
<template>
<div>
<!-- $store.state.子模块.属性 -->
<div>用户名称:{{ $store.state.user.token}}</div>
<div>应用名称: {{ $store.state.setting.name}}</div>
</div>
</template>
// src\App.vue
<template>
<div>
<ChildA/>
<child-b/>
</div>
</template>
<script>
import ChildA from './components/chila-a.vue'
import ChildB from './components/chila_b.vue'
export default {
components: {
ChildA,
ChildB,
},
}
</script>
效果
mapGetters 引用
这个 getters 是根级别的 getters
步骤
// src\main.js
const store = new Vuex.Store({
getters: {
token: state => state.user.token,
name: state => state.setting.name,
},
modules: {
// 放置子模块的属性
user: {
state: {
token: '12345'
},
},
setting: {
state: {
name: 'Vuex实例'
},
}
}
})
// src\components\chila_b.vue
<template>
<div>
<!-- 用户的token和应用名称name -->
<!-- $store.state.子模块.属性 -->
<div>用户名称:{{ $store.state.user.token}}</div>
<div>快捷访问: {{ token }}</div>
<div>应用名称: {{ $store.state.setting.name}}</div>
<div>快捷访问: {{ name }}</div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters(['token', 'name'])
}
}
</script>
效果
使用 - 命名空间(namespaced)
默认情况下,模块内部的 action、mutation 和 getter 是注册在 全局命名空间的 —— 这样可以使多个模块能对同一 mutation 或 action 做出响应。
如果想保证内部模块的高封递性,可以采用 namespaced 来进行设置。
命名空间 - 直接调用(带上模块的属性名路径)
步骤
// src\main.js
modules: {
// 放置子模块的属性
user: {
namespaced: true, // 给true就表示枷锁
state: {
token: '12345'
},
mutations: {
updateToken (state) {
state.token = '67890'
}
},
actions: {}
},
setting: {
state: {
name: 'Vuex实例'
},
}
}
// An highlighted block
<template>
<div>
<!-- 用户的token和应用名称name -->
<!-- $store.state.子模块.属性 -->
<div>用户名称:{{ $store.state.user.token}}</div>
<div>快捷访问: {{ token }}</div>
<div>应用名称: {{ $store.state.setting.name}}</div>
<div>快捷访问: {{ name }}</div>
<button @click="updateToken">更新子模块的token</button>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
computed: {
...mapGetters(['token', 'name'])
},
methods: {
updateToken() {
// 采用路径形式 - 直接调用
this.$store.commit('user/updateToken')
}
}
}
</script>
效果
命名空间 - 辅助函数(-带上模块的属性名路径)
步骤
// src\components\chila_b.vue
<template>
<div>
<!-- 用户的token和应用名称name -->
<!-- $store.state.子模块.属性 -->
<div>用户名称:{{ $store.state.user.token}}</div>
<div>快捷访问: {{ token }}</div>
<div>应用名称: {{ $store.state.setting.name}}</div>
<div>快捷访问: {{ name }}</div>
<button @click="updateToken">更新子模块的token</button>
<button @click="test">子模块的mutations辅助函数</button>
</div>
</template>
<script>
import { mapGetters, mapMutations } from 'vuex'
export default {
computed: {
...mapGetters(['token', 'name'])
},
methods: {
updateToken() {
// 采用路径形式 - 直接调用
this.$store.commit('user/updateToken')
},
...mapMutations(['user/updateToken']),
test() {
this['user/updateToken']()
}
}
}
</script>
效果
命名空间 - espacedHelpers(创建基于某个命名空间辅助函数)
步骤
// src\components\chila_b.vue
<template>
<div>
<!-- 用户的token和应用名称name -->
<!-- $store.state.子模块.属性 -->
<div>用户名称:{{ $store.state.user.token}}</div>
<div>快捷访问: {{ token }}</div>
<div>应用名称: {{ $store.state.setting.name}}</div>
<div>快捷访问: {{ name }}</div>
<button @click="updateToken">更新子模块的token</button>
</div>
</template>
<script>
import { mapGetters, createNamespacedHelpers } from 'vuex'
const { mapMutations } = createNamespacedHelpers('user')
export default {
computed: {
...mapGetters(['token', 'name'])
},
methods: {
...mapMutations(['updateToken']),
}
}
</script>