1. What is vuex?
Vuex is a state management model developed specifically for applications. It uses centralized storage to manage the state of all components of the application and ensures that the state changes in a predictable way with corresponding rules.
According to my own understanding, it is a public data management module. If the data volume in the application is relatively large, it can be applied. If it is not very large, it is recommended to use cache.
2. Use steps
Use the preparation to create a new store directory in the project and create a new file under this directory
1.Introduction
Since Vuex is built into uniapp, you only need to introduce specifications:
// Page path: store/import Vue from 'vue' import Vuex from 'vuex' (Vuex);//vue's plugin mechanism // Constructor optionsconst store = new ({ state:{//Storage status "username":"foo", "age":18 } }) export default store
// Page path:import Vue from 'vue' import App from './App' import store from './store' .$store = store = 'app' // Provide the store object to the "store" option, which injects the store instance into all child componentsconst app = new Vue({ store, ...App }) app.$mount()
Attribute, the main function is to store data
The first method: access through attributes, you need to inject store in the root node.
<!-- Page path:pages/index/ --> <template> <view> <text>username:{{username}}</text> </view> </template> <script> import store from '@/store/';// Need to introduce the store export default { data() { return {} }, computed: { username() { return } } } </script>
The second method: use it in the component and access the data in the state through this.$store.
<!-- Page path:pages/index/ --> <template> <view> <text>username:{{username}}</text> </view> </template> <script> export default { data() { return {} }, computed: { username() { return this.$ } } } </script>
Advanced method: obtain through mapState helper function. When a component needs to obtain multiple states, declaring these states as computed properties will be somewhat duplicated and redundant. To solve this problem, we can use mapState helper function to help us generate computed properties, so that you can press the key fewer times (to put it bluntly, it is the abbreviation, no need to declare one by one to avoid bloating)
<!-- Page path:pages/index/ --> <template> <view> <view>username:{{username}}</view> <view>age:{{age}}</view> </view> </template> <script> import { mapState } from 'vuex'//Introduce mapState export default { data() { return {} }, computed: mapState({ // Get data from state Arrow function can make the code more concise (that is, the abbreviation) username: state => , age: state => , }) } </script>
3. Getter attribute, the main function is to calculate and filter data
It can be considered as a calculation property of the store, and the processing of state is derived data.Just like the computed compute attributes, the value returned by getter is cached according to its dependencies and will be recalculated only when its dependencies change. (Focus on the application of responsive data)
Getter functions can be shared across multiple components, which can also improve operational efficiency.
// Page path: store/import Vue from 'vue' import Vuex from 'vuex' (Vuex); const store = new ({ state: { todos: [{ id: 1, text: 'I'm Content One', done: true }, { id: 2, text: 'I'm Content 2', done: false } ] }, getters: { doneTodos: state => { return (todo => ) } } }) export default store
The Getter property receives the passed parameters, mainly: state, if defined in the module, it is the local state of the module. getters, equivalent to .
// Page path: store/import Vue from 'vue' import Vuex from 'vuex' (Vuex); const store = new ({ state: { todos: [{ id: 1, text: 'I'm Content One', done: true }, { id: 2, text: 'I'm Content 2', done: false } ] }, getters: { doneTodos: state => { return (todo => ) }, doneTodosCount: (state, getters) => { //state: You can access data //getters: Accessing other functions is equivalent to return }, getTodoById: (state) => (id) => { return (todo => === id) } } }) export default store
Apply Getter attribute method 1: Access through attributes, Getter will be exposed as an object, and you can access these values in the form of attributes.
<!-- Page path:pages/index/ --> <template> <view> <view v-for="(item,index) in todos"> <view>{{}}</view> <view>{{}}</view> <view>{{}}</view> </view> </view> </template> <script> import store from '@/store/'// Need to introduce the store export default { computed: { todos() { return } } } </script>
Apply Getter property method two: access through this.$store.
<!-- Page path:pages/index/ --> <template> <view> <view v-for="(item,index) in todos"> <view>{{}}</view> <view>{{}}</view> <view>{{}}</view> </view> </view> </template> <script> export default { computed: { todos() { return this.$ } } } </script>
Applying Getter attribute method three: You can also pass parameters to getter by letting getter return a function. Very useful when you query arrays in the store.Note that when a getter is accessed through a method, it will be called every time without cached results. (One call, one request, no dependency)
<!-- Page path:pages/index/ --> <template> <view> <view v-for="(item,index) in todos"> <view>{{item}}</view> </view> </view> </template> <script> export default { computed: { todos() { return this.$(2) } } } </script>
Advanced application of Getter property method (abbreviated): accessed through mapGetters helper function.
<!-- Page path:pages/index/ --> <template> <view> <view>{{doneTodosCount}}</view> </view> </template> <script> import {mapGetters} from 'vuex' //Introduce mapGetters export default { computed: { // Use the object expansion operator to mix getter into the computed object ...mapGetters([ 'doneTodos', 'doneTodosCount', // ... ]) } } </script>
4. Mutation attribute, the only place where store data changes in Vuex (data must be synchronized)
In a common understanding, mutations contain a collection of methods to change data, and all methods of processing data logic are placed in mutations to separate data and views. Mutations in Vuex are very similar to events: each mutation has a string of event type (type) and a callback function (handler). This callback function is where we actually make the state change, and it will accept state as the first parameter:
// Page path: store/import Vue from 'vue' import Vuex from 'vuex' (Vuex); const store = new ({ state: { count: 1 }, mutations: { add(state) { // Change status += 2 } } }) export default store
You cannot call a mutation handler directly. This option is more like event registration: "When a mutation of type add is triggered, call this function". To wake up a mutation handler, you need to call the method with the corresponding type.
Note: Call mutation (requires in the root node to inject store).
<!-- Page path:pages/index/ --> <template> <view> <view>quantity:{{count}}</view> <button @click="addCount">Increase</button> </view> </template> <script> import store from '@/store/' export default { computed: { count() { return this.$ } }, methods: { addCount() { ('add') } } } </script>
Functions in mutation receive parameters: You can pass additional parameters to mutation, i.e. the payload of mutation:
// Page path: store/import Vue from 'vue' import Vuex from 'vuex' (Vuex); const store = new ({ state: { count: 1 }, mutations: { //Pass the value add(state, n) { += n } //Pass object type add(state, payload) { += } } }) export default store
<!-- Page path:pages/index/ --> <template> <view> <view>quantity:{{count }}</view> <button @click="addCount">Increase</button> </view> </template> <script> import store from '@/store/' export default { computed: { count() { return this.$ } }, methods: { //Pass the value addCount() { ('add', 5)//Accumulate 5 each time } //Pass the object addCount () {//Submit the load and type separately ('add', { amount: 10 }) } } } </script>
Apply Getter property method two: access through this.$store.
<!-- Page path:pages/index/ --> <template> <view> <view v-for="(item,index) in todos"> <view>{{}}</view> <view>{{}}</view> <view>{{}}</view> </view> </view> </template> <script> export default { computed: { todos() { return this.$ } } } </script>
Advanced application of mutation attribute method (abbreviated): accessed through mapMutations helper function.
<!-- Page path:pages/index/ --> <template> <view> <view>quantity:{{count}}</view> <button @click="add">Increase</button> </view> </template> <script> import { mapMutations } from 'vuex'//Introduce mapMutations export default { computed: { count() { return this.$ } }, methods: { ...mapMutations(['add'])//The object expansion operator is directly received by the add } } </script>
5. Action properties:
action submits a mutation, which changes state through mutation instead of directly changing the state. action can contain any asynchronous operations.
// Page path: store/// Page path: store/import Vue from 'vue' import Vuex from 'vuex' (Vuex); const store = new ({ state: { count: 1 }, mutations:{ add(state) { // Change status += 2 } }, actions:{ addCountAction (context) { ('add') } } }) export default store
The action function accepts a context object with the same method and properties as the store instance, so you can call submit a mutation, or get state and getters via and .
actions triggered by the method:
<!-- Page path:pages/index/ --> <template> <view> <view>quantity:{{count}}</view> <button @click="add">Increase</button> </view> </template> <script> import store from '@/store/'; export default { computed: { count() { return this.$ } }, methods: { add () { ('addCountAction') } } } </script>
actions support distribution in load form:
// Page path: store/import Vue from 'vue' import Vuex from 'vuex' (Vuex); const store = new ({ state: { count: 1 }, mutations:{ add(state, payload) { += } }, actions:{ addCountAction (context , payload) { ('add',payload) } } }) export default store
<!-- Page path:pages/index/ --> <template> <view> <view>quantity:{{count }}</view> <button @click="add">Increase</button> </view> </template> <script> import store from '@/store/'; export default { computed: { count() { return this.$ } }, methods: { add () { // Distribute in load form ('addCountAction', {amount: 10}) } add () { // Distribute in object form ({ type: 'addCountAction', amount: 5 }) } } } </script>
Asynchronous actions:
// Page path: store///Call the mutations method to change the data (synchronous, asynchronous) actions:{ //Async call actionA({ commit }) { return new Promise((resolve, reject) => { setTimeout(() => { commit('add',5) resolve() }, 2000) }) } actionB ({ dispatch, commit }) { return dispatch('actionA').then(() => {commit('someOtherMutation') }) async actionA ({ commit }) {commit('gotData', await getData()) }, async actionB ({ dispatch, commit }) { await dispatch('actionA') // Wait for actionA to complete commit('gotOtherData', await getOtherData()) } } }
Advanced (abbreviation): accessed through mapActions helper function.
<!-- Page path:pages/index/ --> <template> <view> <view>quantity:{{count }}</view> <button @click="addCountAction">Increase</button> </view> </template> <script> import { mapActions } from 'vuex' export default { computed: { count() { return this.$ } }, methods: { ...mapActions([ 'addCountAction', // Map `()` to `this.$('addCountAction')` ]) } } </script>
6. Module structure.
Because of the use of a single state tree, all states of the application are concentrated in a larger object. When the application becomes very complex, the store object can become quite bloated. To solve the above problem, Vuex allows us to split the store into modules. Each module has its own state, mutation, action, getter, and even nested submodules - splitting the same way from top to bottom:
1. Create a new modules folder under the store folder, and create a new module module for vuex below and use it to store vuex.
├── components # Component folder
└── myButton
└── # myButton component
├── pages
└── index
└── # index page
├── static
├── store
# Where we assemble the module and export the store
└── modules # Module folder
├── # Module moduleA
└── # Module moduleB
├──
├──
├──
├──
└──
2. Introduce store in the file.
// Page path: import Vue from 'vue' import App from './App' import store from './store' .$store = store // Provide the store object to the "store" option, which injects the store instance into all child components const app = new Vue({ store, ...App }) app.$mount()
3. In the project root directory, create a new store folder and create a new file below as a module entrance to introduce each submodule.
// Page path: store/ import Vue from 'vue' import Vuex from 'vuex' import moduleA from '@/store/modules/moduleA' import moduleB from '@/store/modules/moduleB' (Vuex) export default new ({ modules:{ moduleA,moduleB } })
4. Submodule moduleA page content.
// Submodule moduleA path: store/modules/export default { state: { text:"I am the value under moduleA" }, getters: { }, mutations: { }, actions: { } }
5. Submodule moduleB page content.
// Submodule moduleB path: store/modules/export default { state: { timestamp: 1608820295//Initial timestamp }, getters: { timeString(state) {//Time after the timestamp conversion var date = new Date(); var year = (); var mon = ()+1; var day = (); var hours = (); var minu = (); var sec = (); var trMon = mon<10 ? '0'+mon : mon var trDay = day<10 ? '0'+day : day return year+'-'+trMon+'-'+trDay+" "+hours+":"+minu+":"+sec; } }, mutations: { updateTime(state){//Update the current time stamp = () } }, actions: { } }
6. Refer to the component myButton in the page and read the initial data in state through mapState.
<!-- Page path:pages/index/ --> <template> <view class="content"> <view>{{text}}</view> <view>Timestamp:{{timestamp}}</view> <view>Current time:{{timeString}}</view> <myButton></myButton> </view> </template> <script> import {mapState,mapGetters} from 'vuex' export default { computed: { ...mapState({ text: state => , timestamp: state => }), ...mapGetters([ 'timeString' ]) } } </script>
7. In the component myButton, refresh the current time through the mutations operation.
<!-- Component path:components/myButton/ --> <template> <view> <button type="default" @click="updateTime">Refresh the current time</button> </view> </template> <script> import {mapMutations} from 'vuex' export default { data() { return {} }, methods: { ...mapMutations(['updateTime']) } } </script>
Summarize
vue is a one-way data stream. Children components cannot directly modify the data of the parent component. They are implemented through vuex state management: extract the shared state of the component and manage it in a global singleton mode. In this mode, our component tree forms a huge "view", and no matter where it is in the tree, any component can get state or trigger behavior!
The overall structure of vuex is not complicated, and the knowledge specifications are relatively cumbersome. Just try it a few more times by yourself.
This is the article about the use of vuex applications in Uniapp. For more related vuex applications in Uniapp, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!