1、vuex定义
vuex是vue的全局状态的管理工具
vuex数据更新,其引用组件都会响应式的更新
2、Vue
中的单项数据流
与单向数据流对应的就是双向数据流:双向数据流在Vue
中也叫做‘双向绑定’,其实现主要是依靠MVVM
框架,在Vue
中主要由三个部分组成:View
、ViewModel
、Model
。其中View
可以简单的理解为视图层,Model
可以简单的理解为数据层,其中View与Model之间是不能直接通信的,必须得依靠ViewModel中间件来完成。通过ViewModel
就可以实现数据双向绑定,也就是View
与Model
之间的同步是自动的,Model
数据改变了View
视图上的数据也会跟着改变,而不必手动去更新。
3.什么情况下该使用Vuex?
Vuex
可以帮助我们管理共享状态,并附带了更多的概念和框架。这需要对短期和长期效益进行权衡。 如果您不打算开发大型单页应用,使用 Vuex
可能是繁琐冗余的。确实是如此——如果您的应用够简单,您最好不要使用 Vuex
。一个简单的 store 模式就足够您所需了。但是,如果您需要构建一个中大型单页应用,您很可能会考虑如何更好地在组件外部管理状态,Vuex
将会成为自然而然的选择
state: {},
getters: {},
mutations: {},
actions: {},
modules: {}
1.state
就是在这个里面定义的数据,vue的所有组件都可以使用,具体语法如下
state: {
user : {
name:'张三',
age:18
}
},
组件使用
this.$store.state.user.name // 张三
$store.state.user.age // 18
辅助函数
<script>
import { mapState } from "vuex";
export default {
name: "Home",
computed: {
...mapState(["user"])
}
}
</script>
导入了辅助函数之后就可以直接用
user.name // 张三
user.age // 18
2.getter
getters其实并没有过多的介绍,就相当于是vue中的计算属性computed
vuex
info(state) {
console.log('getters')
return `我的名字叫做${state.user.name} 我的年纪${state.user.age}`
}
组件
<h3>简介: {{ $store.getters.info }}</h3>
辅助函数
<script>
import { mapGetters } from "vuex";
export default {
name: "Home",
computed: {
...mapGetters(["info"])
}
}
</script>
导入了辅助函数之后就可以直接用
<h3>简介(mapGetters): {{ info }}</h3>
3.mutations
语法: this.$store.commit('mutation名', 载荷实参 )
这个就厉害了,所有的state里面的数据,只能通过mutations来修改
组件
<p><button @click="doClick">改变数据</button></p>
doClick() {
this.$store.commit("updated", {
name: "大帅哥",
age: 100,
});
},
vuex
mutations: {
// state 就是 state里面的数据 , payload就是载荷 通常就是一个对象
updated(state, payload) {
state.user = payload
},
}
4.actions
语法: this.$store.dispatch('actions的名字', 参数)
步骤:
- 组件提交actions异步更新
this.$store.dispatch('actions的名字', 参数)
- actions 发送异步请求,但是里面只能看不能改
- 提交给 mutations , context.commit('mutations函数名',要修改的数据)
- mutations 里面就可以直接修改数据了
工作流程 :
-
1.actions与mutations相同点 :都是修改state数据
-
2.actions与mutations不同点
- mutations:同步更新
- actions: 异步更新(例如你的数据来源于ajax)
-
- 注意点
- actions里面不能直接修改数据 ,
- 主要就是发送axios请求,以防代码冗余
- vuex中没有vue的实例,调用不了axios 的方法,我们要手动导入
组件
<button @click="doClick111">点我发送axios请求</button>
doClick111() {
this.$store.dispatch("getList");
}
vuex
//导入axios
import axios from "axios";
// 先定义一个空数组准备接收
state : {
list : []
}
// 这里我们注意 , vuex里面没有this 所以我们要导入axios
actions: {
async getList(context) {
const { data: res } = await axios.get('/getBooks')
console.log(res);
context.commit('getBooks', res.data)
}
}
5.modules
modules主要就是,模块化的,这个大型项目用的很多,但是vue2也不支持很大型的项目,所以这个用的还是比较少,但是我这边还是给大家提一下
// 导入子模块
import user from './user'
modules: {
user
}
子模块 store/user.js
import Vue from "vue";
import Vuex from "vuex";
//导入axios
import axios from "axios";
Vue.use(Vuex);
export default {
namespaced: true,
state: {
list: [],
},
getters: {},
mutations: {
getBooks(state, payload) {
state.list = payload;
},
},
actions: {
async getList(context) {
const { data: res } = await axios.get("/getbooks");
console.log(res);
context.commit("getBooks", res.data);
},
},
modules: {},
}
二.映射
基本用法
假设Vuex的代码如下:
const store = new Vuex({
state:{
userInfo:{
id:110,
username:'laoxie'
}
},
getters:{
isLogin(state){
return !!state.userInfo.id
}
},
mutations:{
login(state,payload){
state.userInfo = payload
},
logout(state){
state.userInfo = {}
}
},
actions:{
login(ctx,payload){
ajax('/login',payload).then(data=>{
ctx.commit('login',data)
})
}
}
})
mapState
与mapGetter
映射的值都属于属性,所以一般用在computed选项中,mapMutations
与mapActions
映射的值都属于方法,所以一般用在methods中,它们的参数支持数组与对象用法,并返回一个对象
{
computed:{
// 把同名属性userInfo映射到computed中,以下两行代码等效
// userInfo(){return this.$store.state.userInfo}
...mapState(['userInfo']),
// 如需更改名字,则可使用对象形式(字符串或函数形式)
...mapState({user:'userInfo',currentUser:state=>state.userInfo})
// mapGetters采用对象参数时不支持函数写法
...mapGetters(['isLogin']),
...mapGetters({logined:'isLogin'}),
},
methods:{
// 以下两种写法等效于:logout(){this.$store.commit('logout')}
...mapMutations(['logout']),
...mapActions({
logout(commit,payload){
// commit固定为第一个参数
// payload为调用logout时传入的参数,不传则为undefined
commit('logout')
}
}),
// 以下两种写法等效于:login(user){this.$store.dispatch('login',user)}
...mapActions(['login']),
...mapActions({
login(dispatch,payload){
// dispatch固定为第一个参数
// payload为调用login时传入的参数,不传则为undefined
dispatch('login',payload)
}
})
}
}
高级用法
假设Vuex使用了模块化及命名空间,更能体会4个映射方法的优势,假设vuex代码如下:
const user = {
// 模块化并设置命名空间
namespaced:true,
state:{
userInfo:{
id:110,
username:'laoxie'
}
},
getters:{
isLogin(state){
return !!state.userInfo.id
}
},
mutations:{
login(state,payload){
state.userInfo = payload
},
logout(state){
state.userInfo = {}
}
},
actions:{
login(ctx,payload){
ajax('/login',payload).then(data=>{
ctx.commit('login',data)
})
}
}
}
const store = new Vuex({
modules:{
user
}
})
Vuex模块化后,默认只影响state
的获取,getters
、mutations
、actions
依然在全局状态下,设置了命名空间(namespaced:true
)后getters、mutations、actions的获取与操作需要带上命名空间,操作相对会比较繁琐,使用映射方法可以简化我们的代码,用法如下:
{
computed:{
// 以下两个用法效果一至
// 不用第一个参数用法如下
...mapState({userInfo:state=>state.user.userInfo}),
// 设置第一个参数为模块名称
...mapState('user',['userInfo']),
// 以下两个用法效果一至
...mapGetters(['user/isLogin']), // 不推荐,给实例写入`user/isLogin`属性
...mapGetters('user',['isLogin']), // 给实例写入`isLogin`属性
},
methods:{
// 以下写法等效于:logout(){this.$store.commit('user/logout')}
...mapActions('user',['logout']),
// 以下写法等效于:login(user){this.$store.dispatch('user/login',user)}
...mapActions('user',{
login(dispatch,payload){
// dispatch固定为第一个参数
// payload为调用login时传入的参数,不传则为undefined
dispatch('login',payload)
}
})
}
}
以上为mapState
、mapGetters
、mapMutations
、mapActions
4个映射方法的使用,结果模块化与命名空间更能发挥它们的优势