vuex 官网: ‘专为 Vue.js 应用程序开发的状态管理模式’。多个视图引用/修改同一状态时,依靠组件间数据的传递很麻烦,vuex将这些公用的状态数据统一进行管理。
vuex的应用场景:想用的时候用,一般中大型项目。
当vue组件从store中读取状态时,若store中的状态发生变化,相应的引入此状态的组件也会相应的的高效更新。改变store状态(state)中唯一的方法就是通过mutation commit数据。
state: 视图公用的数据,(被多个视图引用、修改)
getters: 公用数据不符合你想要的格式,在这里加工处理。
mutations: 提供更改数据的方法 store.commit() mutations的属性方法都必须是同步的
actions: 更改公用数据的方法,但是actions更改数据仍然需要通过mutations 中store.commit()更改数据。都是更改数据mutations就好了,何必再多actions这一步呢。actions存在的意义是: 异步处理,在actions中进行异步处理,再同步提交给mutations,同步更改时间。
modules :modules可以分出多个store模块。每个模块拥有自己的state、getters、mutations、actions.
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
banner: 'https://w.wallhaven.cc/full/28/wallhaven-281d5y.png',
themes: [
{
themeId: '000001',
themeName: '咒术回战',
themeBanner: 'https://images7.alphacoders.com/114/thumb-1920-1144724.png'
},
{
themeId: '000002',
themeName: '一拳超人',
themeBanner: 'https://images3.alphacoders.com/104/thumb-1920-1046030.jpg'
},
{
themeId: '000003',
themeName: '火影忍者',
themeBanner: 'https://images5.alphacoders.com/532/thumb-1920-532559.jpg'
},
{
themeId: '000004',
themeName: '鬼灭之刃',
themeBanner: 'https://images3.alphacoders.com/105/thumb-1920-1053268.jpg'
}]
},
getters: {
themesNew(state) {
state.themes.map(item=>{
item.themeName += item.themeId
return item
})
return state.themes
}
},
mutations: {
changeBanner(state, value){
state.banner = value
}
},
actions: {
changeBannerActions({commit}, value) {
// 模仿异步操作
setTimeout(()=> {
// 提交到mutations, 让mutations更新数据
commit('changeBanner', value)
}, 3000)
}
}
})
export default store;
main.js 全局引用就不写了。
<template>
<div class="site-page">
<div class="banner" :style="{backgroundImage: 'url(' + banner +')'}">
</div>
<div class="left-side">
<p class="site-name">Anime Theme</p>
<ul>
<li v-for="item in themesNew" @click="changeBanner" :data-themebanner="item.themeBanner">{{ item.themeName }}</li>
</ul>
</div>
</div>
</template>
<script>
import store from "@/store/store";
export default {
name: 'login',
data() {
return {
}
},
computed: {
// 获取state数据
banner() {
return this.$store.state.banner
},
// 获取getters数据
themesNew() {
return this.$store.getters.themesNew
}
},
methods: {
changeBanner(e) {
const { themebanner } = e.currentTarget.dataset
// 调用actions,提交数据
this.$store.dispatch('changeBannerActions', themebanner)
}
}
}
</script>
<style lang="less">
.site-page {
.banner {
width: 100vw;
height: 100vh;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.left-side {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
width: 240px;
background: rgba(0,0,0,.5);
z-index: 1;
.site-name {
font-family: Futura;
margin-top: 108px;
font-size: 28px;
font-weight: 600;
color: #fff;
letter-spacing: 2px;
user-select: none;
}
ul {
/*border: 1px solid #fff;*/
margin: 36px auto;
width: 100%;
list-style: none;
li {
/*border-bottom: 1px solid darkslateblue;*/
margin: 5px auto;
width: 80%;
height: 48px;
font-size: 18px;
line-height: 48px;
color: #fff;
user-select: none;
cursor: pointer;
letter-spacing: 1px;
}
li:hover {
transform: scale(1.2);
transition: transform .5s;
}
}
}
}
</style>
通过辅助函数也可以简写:
<template>
<div class="site-page">
<div class="banner" :style="{backgroundImage: 'url(' + banner +')'}">
</div>
<div class="left-side">
<p class="site-name">Anime Theme</p>
<ul>
<!-- 这里注意actions的参数,直接写括号里传参 -->
<li v-for="item in themesNew" @click="changeBannerActions(item.themeBanner)" :data-themebanner="item.themeBanner">{{ item.themeName }}</li>
</ul>
</div>
</div>
</template>
<script>
import { mapState, mapGetters, mapActions} from 'vuex'
export default {
name: 'login',
data() {
return {
}
},
computed: {
/* ...扩展运算符,展开mapState和mapGetters对象作为属性放入computed对象中 */
...mapState(['banner']),
...mapGetters(['themesNew'])
// banner() {
// return this.$store.state.banner
// },
// themesNew() {
// return this.$store.getters.themesNew
// }
},
methods: {
...mapActions(['changeBannerActions'])
// changeBanner(e) {
// const { themebanner } = e.currentTarget.dataset
//
// this.$store.dispatch('changeBannerActions', themebanner)
// }
}
}
</script>
<style lang="less">
.site-page {
.banner {
width: 100vw;
height: 100vh;
background-size: cover;
background-position: center;
background-repeat: no-repeat;
}
.left-side {
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
width: 240px;
background: rgba(0,0,0,.5);
z-index: 1;
.site-name {
font-family: Futura;
margin-top: 108px;
font-size: 28px;
font-weight: 600;
color: #fff;
letter-spacing: 2px;
user-select: none;
}
ul {
/*border: 1px solid #fff;*/
margin: 36px auto;
width: 100%;
list-style: none;
li {
/*border-bottom: 1px solid darkslateblue;*/
margin: 5px auto;
width: 80%;
height: 48px;
font-size: 18px;
line-height: 48px;
color: #fff;
user-select: none;
cursor: pointer;
letter-spacing: 1px;
}
li:hover {
transform: scale(1.2);
transition: transform .5s;
}
}
}
}
</style>