1. Why Vuex?
In componentized development of Vue, data can be passed between parent and child components, but there are still two problems:
- If you want to get data from an ancestor component (the component above the parent) in a child component, you must pass it layer by layer
- If two sibling components want to pass data, they must first pass the data to the parent component, and then the parent component can pass the data to the sibling component. If the two components are not in the same parent component, they also need to be passed to the ancestor component.
These two issues illustrate how cumbersome it is for sibling components to pass and share data without Vuex.
With Vuex, the common parts of a component can be extracted, independent of each component, and any component in the application can retrieve and modify the common data stored by Vuex.
2. How to use Vuex?
Four steps: Import Vuex, create Vuex object, save Store, use Vuex
2.1 introduced Vuex
In the official website to download Vuex:vuex.vuejs.org/zh/installa…
<script src="./lib/vue.js"></script> <! -- 1. Import Vuex --> <! <script SRC ="./lib/vuex-3.6.2.js"></script>Copy the code
2.2 Creating a Vuex Object
Import Vue from 'Vue' import Vuex from 'Vuex' vue.use (Vuex) // Ignore the above code if you have already imported a Vuex file via script const store = new Vuex.Store({state: {count: 0}, // Notes: when you implement the methods defined in mutations, the system automatically passes a state parameter to those methods. { increment (state) { state.count++ } } })Copy the code
- State: Used specifically to hold shared data, as opposed to data in the component
// In the component you can pass "this.$store.state ". State = console.log(this.$store.state.count); / / 0Copy the code
- Mutations: defined in VUEX, the function is used to operate the data saved in VUEX. In VUEX, it is not recommended that components directly modify the data in VUEX, and it is more beneficial to maintain the code by calling the function defined in VUEX.
Use "this. code.store.mit (" function name ")" to call the vuex function add() {this. code.store.mit ("increment"); }Copy the code
2.3 Adding a Store Key
By adding stroe to the ancestor component (the outermost component), components defined in the ancestor component can use VUex
* mutations: const store = new vuex. store ({return state = new vuex. store ({return state = new vuex. store), /* mutations: { increment(state) { state.count++ } } */ }); Vue.component("grandfather", { template: "#grandfather", // 3. {"father": {"father": {"father": {"father": {"father": {"father": {"father": {"father": { { template: "#father", components: { "son1": { template: "#son1", } } } } })Copy the code
2.4 use Vuex
You can retrieve data in Vuex directly using specified fields
<template id="grandfather"> <div> <h1>{{this.$store.state.msg}}</h1> <father></father> </div> </template> <! Vuex --> <template id="father"> <div> <! {{this.$store.state. MSG}}</h2> <son1></son1> </div> </template> <! - child components using vuex - > < template id = "son1" > < div > < h3 > {{this. $store. State. MSG}} < / h3 > < / div > < / template >Copy the code
3. The getters properties
Vuex’s getters are relative to calculated properties in the component
Open mutations = new vuex. store ({// state: for saving the shared data state: {MSG: "deep sea fish"}, // mutations: for saving the shared data method {}, getters: {format(state) {console.log("getters method was executed "); Return state. MSG + 'MSG '; }}});Copy the code
<template id="father">
<div>
{{this.$store.state.msg}}
{{this.$store.getters.format}}
{{this.$store.getters.format}}
{{this.$store.getters.format}}
</div>
</template>
Copy the code
Output result:
I’ll write it here for now. The rest of the Vuex will be updated as you learn.
4. The application
In real application development, there might be many pieces of data or state stored in vuEX, and if we store every piece of data in state, we have to create the mutations method for each piece of data, and we have to create actions events for each method, Events that return values in state must also be defined in getters.
We can create separate files for state, mutations, actions and getters, expose them in the file using Export Default, and then import them one by one in index.js, which can achieve very convenient management. The following examples are:
Music Online Project
In this project, Vuex is used to manage the display and hide status of play pages, mini-play components, and playlist pages within the mini-components. Because these pages and components can be used anywhere in the project, vuex is the best choice for global management.
Vuex defined in
index.js
import Vue from 'vue' import Vuex from 'vuex' import state from './state' import mutations from './mutations' import actions from './actions' import getters from './getters' Vue.use(Vuex) export default new Vuex.Store({ // state: Mutations: a method for saving the globally shared data state, // mutations: a method for saving the globally shared data state, // mutations: a method for saving the globally shared data, // actions: a method for saving the methods that trigger mutations: actions, modules: { }, getters })Copy the code
state.js
export default {
isFullScreen: false,
isShowMiniPlayer: false
}
Copy the code
mutations.js
- Here, we can see that a retro-type is introduced. The reason is that if a string is used directly, an error will not be reported when filling in, and if a public variable is defined, an error will be reported when the variable name is wrong.
import { SET_FULL_SCREEN, SET_MINI_PLAYER } from './mutations-type'
export default {
/* eslint-disable */
/* changeFullScreen (state, flag) {
state.isFullScreen = flag
} */
[SET_FULL_SCREEN] (state, flag) {
state.isFullScreen = flag
},
[SET_MINI_PLAYER] (state, flag) {
state.isShowMiniPlayer = flag
}
}
Copy the code
mutations-type
export const SET_FULL_SCREEN = 'SET_FULL_SCREEN'
export const SET_MINI_PLAYER = 'SET_MINI_PLAYER'
Copy the code
actions
import { SET_FULL_SCREEN, SET_MINI_PLAYER } from './mutations-type'
export default {
setFullScreen ({ commit }, flag) {
commit(SET_FULL_SCREEN, flag)
},
setMiniPlayer ({ commit }, flag) {
commit(SET_MINI_PLAYER, flag)
}
}
Copy the code
getters
export default {
isFullScreen (state) {
return state.isFullScreen
},
isShowMiniPlayer (state) {
return state.isShowMiniPlayer
}
}
Copy the code
Play page
* PART of the CSS code is not displayed
<template> <transition v-on:enter="enter" @leave="leave"> <! Here you use the data defined in VUEX, defined in computed for the component you want to use after defining the fetch method in getters... MapGetters (['getters ']), can pass this. <div class="player-waepper"> <div class="player-waepper"> <PlayHeader></PlayHeader> <PlayerMiddle></PlayerMiddle> <PlayerBottom></PlayerBottom> </div> <div class="player-bg"> <img src="https://dfzximg01.dftoutiao.com/news/20210614/20210614134446_5350398987762e5ff84917e9f52af0c9_4.png" alt=""> </div> </div> </transition> </template> <script> import PlayHeader from './PlayHeader' import PlayerMiddle from './PlayerMiddle' import PlayerBottom from './PlayerBottom' import {mapGetters} from 'vuex' // vuex is imported here Velocity from 'velocity-animate' import 'velocity-animate/velocity.ui' export default { name: 'NormalPlayer', components: { PlayHeader, PlayerMiddle, PlayerBottom }, computed: { ... MapGetters (['isFullScreen' // because you don't call vuex methods, just get attributes, just define them in computed... { enter (el, done) { Velocity(el, 'transition.shrinkIn', { duration: 500 }, () => { done() }) }, leave (el, done) { Velocity(el, 'transition.shrinkOut', { duration: 500 }, () => { done() }) } } } </script>Copy the code
Song list page
<template> <ul class="detail-bottom"> <li class="bottom-top"> <div class="bottom-icon"></div> <div Class ="bottom-title"> </div> </li> <! -- When a song in the playlist is clicked, the data state managed in VUEX is changed. <li v-for="value in playlist" :key="value. Id "class="item" @click="selectMusic"> <h3>{{value. Name}}</h3> < p > {{value. Al. Name}} - {{value. Ar [0]. Name}} < / p > < / li > < / ul > < / template > < script > / / because of the need to change the state of data, MapActions import {mapActions} from 'vuex' export default {name: 'DetailBottom', props: {playlist: {type: Array, default: () => [], required: true}}, methods: { Method name call... MapActions (['setFullScreen', // map 'this.setfullscreen (true)' to 'this.$store.dispatch('setFullScreen', true)` 'setMiniPlayer' ]), selectMusic () { // this.$store.dispatch('setFullScreen', This.setfullscreen (true) this.setminiPlayer (false)}}} </script>Copy the code
Mini Player Components
The mini-player component needs both to get its own state of display and to listen for click events to control whether the big play page is displayed. In this case, mapActions and mapGetters need to be brought in from vuex.
<template> <transition @enter="enter" @leave="leave"> <div class="mini-player" v-show="this.isShowMiniPlayer"> <div class="player-warpper"> <div class="player-left" @click="showNormal"> <img src="https://p1.music.126.net/8y8KJC1eCSO_vUKf2MyZwA==/109951165796899183.jpg" alt="" > <div class="player-title"> < h3 > actors < / h3 > < p > memory < / p > < / div > < / div > < div class = "player - right" > < div class = "play" > < / div > < div class = "list" @click.stop="showList"></div> </div> </div> </div> </transition> </template> <script> import { mapActions, mapGetters } from 'vuex' import Velocity from 'velocity-animate' import 'velocity-animate/velocity.ui' export default { name: 'MiniPlayer', methods: { ... mapActions([ 'setFullScreen', 'setMiniPlayer' ]), showNormal () { this.setMiniPlayer(false) this.setFullScreen(true) }, showList () { this.$emit('showList') }, enter (el, done) { Velocity(el, 'transition.bounceUpIn', { duration: 500 }, () => { done() }) }, leave (el, done) { Velocity(el, 'transition.bounceDownOut', { duration: 500 }, () => { done() }) } }, computed: { ... mapGetters([ 'isShowMiniPlayer' ]) } } </script>Copy the code
Memory:
- MapActions are defined in methods after being introduced
. mapActions([])
- MapGetters were introduced and defined in computed
. mapGetters([])