学习前先看这个需求,我先在有两个组件,一个是外面的主页,一个是里面的p1,p1里有个文本框,需求是在文本框里修改用户姓名,修改完后希望修改后的姓名显示到主页那里,欢迎xxx:
这个需求如何实现呢,用以前的办法就不好实现了,以前的办法是你这个文本框是属于p1组件的,只能和p1组件里的data()返回的数据对象进行绑定,没办法直接被主页这个组件访问到。
根据这个需求,我们就需要学习一个新的技术了——vuex。
这个问题本质上是一个数据共享的问题,我们可以给这两个组件找一个可以数据共享的地方,一个组件往里存数据,另一个从里面取数据。
有人可能说了,我们可以用上面刚刚学到的localStorage
和sessionStorage
,p1组件点击确定之后,可以将用户姓名存到比如说sessionStorage
里,再让主页从里面取出修改后的用户名不就可以啦?
vuex 可以在多个组件之间共享数据,并且共享的数据是【响应式】的,即数据的变更能及时渲染到模板。
与vuex相关的代码在src/store/index.js
里:
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
},
getters: {
},
mutations: {
},
actions: {
},
modules: {
}
})
首先需要定义 state 与 mutations 他们一个用来读取共享数据,一个用来修改共享数据
src/store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
// 这里我们就可与来定义共享数据
/*
读取数据,走 state, getters
修改数据,走 mutations, actions
*/
// 从state读取共享数据,在mutations修改共享数据
export default new Vuex.Store({
// 共享数据的位置
state: {
name: '',
},
getters: {
},
// 如果需要修改共享位置,不可以直接修改state里的内容,需要在mutations里添加方法
mutations: {
updateName(state, newName) {
state.name = newName;
},
},
actions: {
},
modules: {
}
})
修改共享数据
<template>
<div class="p">
p1
<el-input placeholder="请修改用户名" v-model="name"></el-input>
<el-button type="primary" v-on:click="updateName()">修改</el-button>
</div>
</template>
<script>
export default {
data() {
return {
name: ''
}
},
methods: {
updateName() {
// 修改共享数据
// mutations 方法不能直接调用,只能通过 `store.commit(mutation方法名, 参数)` 来间接调用
this.$store.commit('updateName', this.name);
},
}
}
</script>
<style scoped>
...
</style>
store.commit(mutation方法名, 参数)
来间接调用读取共享数据
<template>
<div class="container">
主页
<el-container>
<el-header>
<div class="t">欢迎您:{{this.$store.state.name}}</div>
</el-header>
<el-container>
<el-aside width="200px"></el-aside>
<el-main>
<!-- 占位 -->
<router-view></router-view>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
export default {
data() {
return {}
},
}
</script>
<style scoped>
...
</style>
作用:根据state里的属性,自动生成计算属性 name(){ return this.$store.state.name }
每次去写 $store.state.name
这样的代码显得非常繁琐,可以使用计算属性来简化代码:
<template>
。。。
<div class="t">欢迎您:{{name}}</div>
。。。
</template>
<script>
export default {
data() {
return {}
},
computed: {
name() {
return this.$store.state.name
},
}
}
</script>
<style scoped>
...
</style>
如果我们还有一个age数据需要共享,那么还需要在computed
里写一个age()
...
可以用 vuex 帮我们生成计算属性:
src/views/example16/ContainerView.vue
...
<script>
import { mapState } from "vuex"
console.log(mapState(['name', 'age']))
....
可以看到mapState为我们已经生成了对应计算属性了,那么就不需要在computed
里写计算属性了:
<template>
<div class="container">
主页
。。。
<div class="t">欢迎您:{{name}}{{age}}</div>
。。。
</template>
<script>
import { mapState } from "vuex"
export default {
data() {
return {}
},
// computed: {
// name() {
// return this.$store.state.name;
// },
// age() {
// return this.$store.state.age;
// }
// }
computed: mapState(['name', 'age']),
// 等价的写法:... 展开运算符,相当于展开后又塞入了一个空对象里
// computed: {
// ...mapState(['name', 'age'])
// }
}
作用: 根据
mutatinos
里的属性方法,生成类似于这种形式的代码: updateName() { this.$store.commit('updateName', this.name); },
刚才我们使用了vuex给我们提供的mapState函数帮我们生成了计算属性,算是对我们读取共享数据的一种优化。
那我们来看修改共享数据,原本是我们自己写了个updataName方法来修改共享数据,那么可以可以也有优化呢?
答案是可以的,也可以让vuex帮我们生成好:
<script>
import { mapMutations } from 'vuex'
// mapMutations()
console.log(mapMutations(['updateName']))
<template>
<div class="p">
p1
<el-input placeholder="请修改用户名" v-model="name"></el-input>
<!-- 注意,这里的事件要绑定mapMutations生成的方法名,且需要传入一个参数(作为修改的值) -->
<el-button type="primary" v-on:click="updateName(name)">修改</el-button>
</div>
</template>
<script>
import { mapMutations } from 'vuex'
export default {
data() {
return {
name: ''
}
},
mounted: function () {
this.name = this.$store.state.name;
},
methods: {
// updateName() {
// // 修改共享数据
// // mutations 方法不能直接调用,只能通过 `store.commit(mutation方法名, 参数)` 来间接调用
// this.$store.commit('updateName', this.name);
// },
...mapMutations(['updateName'])
}
}
</script>
<style scoped>
.p {
background-color: rgb(165, 150, 242);
width: 80%;
height: auto;
margin: 50px;
}
</style>
mapMutations
返回的对象中包含的方法,就会调用 store.commit()
来执行 mutation
方法mutations
方法内不能包括修改不能立刻生效(
例如:
mutations:{
async updateServerUser(state){
const resp = await axios.get('/api/user');
const {name,age} = resp.data.data;
state.name= name;
state.age = age;
}
}
错误的用法,如果在mutations方法包含了异步操作,会造成开发工具的不准确
)的代码,否则会造成 Vuex 调试工具工作不准确,必须把这些代码写在 actions 方法中
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
/*
读取数据,走 state, getters
修改数据,走 mutations, actions
*/
import axios from '@/util/myaxios'
export default new Vuex.Store({
state: {
name: '',
age: 18
},
getters: {
},
mutations: {
updateName(state, name) {
state.name = name;
},
// 错误的用法,如果在mutations方法中包含了异步操作,会造成开发工具不准确
/* async updateServerName(state) {
const resp = await axios.get('/api/user');
const {name, age} = resp.data.data;
state.name = name;
state.age = age;
} */
updateServerName(state, user) {
const { name, age } = user;
state.name = name;
state.age = age;
}
},
// 拿到响应之后,再间接
actions: {
async updateServerName(context) {
const resp = await axios.get('/api/user');
// 通过commit来定执行那个mutaition
// 参数1:要执行的mutation的名字
// 参数2:数据
context.commit('updateServerName', resp.data.data)
}
},
modules: {
}
})
页面使用 actions
的方法可以这么写
<template>
<div class="p">
<el-button type="primary" size="mini"
@click="updateServerName()">从服务器获取数据,存入store</el-button>
</div>
</template>
<script>
import { mapActions } from 'vuex'
const options = {
methods: {
...mapActions(['updateServerName'])
}
}
export default options;
</script>
总结: 立刻生效的数据才可以使用mutation修改,不是立刻能获取到的数据,就需要使用actions中转一下,间接调用mutations。
vuex说白了就是在组件之间共享数据的,他共享的数据有一个特点,是响应式的;
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。