Recently, I was writing the home page of deepincn, and I saw elementary os’ home page style was quite nice, so I planned to learn from it.
Originally intended to use Angular development, but see Vue3 has been very stable, so I plan to regain Vue3, using Vue3 to write the new home page.
In order to facilitate future data updates, you need to use centralized data management, Vue under the more famous and good is Vuex, and Vuex has also been adapted to Vue3, you can rest assured that the use of.
This article will briefly introduce Vuex, then talk about the basic syntax, I will write another article to specifically draw on a Vuex, through the implementation of a simple Vuex to understand the core.
One of the most important feature points of Vue is data-driven .
By data-driven, we mean that the view is generated by data-driven, and we don’t modify the view by directly manipulating the DOM, but by modifying the data. It greatly simplifies the amount of code compared to our traditional front-end development, such as using jQuery and other front-end libraries to directly modify the DOM.
Especially when the interaction is complex, only caring about data modification will make the logic of the code very clear, because the DOM becomes a data mapping, all our logic is to modify the data without touching the DOM, so the code is very easy to maintain.
Another important feature of Vue is componentization, each component is the smallest unit of functionality, each component has its own
methods. We update the view in
template by modifying the data in
data. It is very convenient to update the view in a single component, but in practice, when we have more than one component in our project, it is very difficult to maintain the same state when many components are integrated together, especially when the embedding is very deep, passing parameters becomes very troublesome (here I think of Deepin’s control center, there are very deep nesting inside the component, and the innermost component (to get the data, you need to pass it along the nesting layers, which is very troublesome).
To solve this problem, we need to introduce Vuex for state management, which is responsible for communication among components.
Problems solved by Vuex
- Multiple views depend on the same state.
- Actions from different views need to change the same state
First install Vuex in the project, Vuex4 is the version developed for Vue3 and we install it with the following command.
At the heart of every Vuex application is the store. The “store” is basically a container that contains most of the state in your application.
Vuex’s state store is responsive. When a Vue component reads state from the store, if the state in the store changes, the corresponding component will be updated accordingly and efficiently. 2. You can’t change the state in store directly. The only way to change the state in store is to explicitly commit mutation, which makes it easy to track every change in state and allows us to implement tools that help us better understand our application.
Now that Vuex is installed, we can start writing a simple store by creating a
In main.ts, register the store to the app instance of Vue.
The above is the simplest example of a store, is it a little confusing?
In store.ts we export the object returned using the createStore function, and in store we define two properties:
We define the state in state and the operation methods in mutations. The methods defined in mutations must be called by the
store.commit() method and cannot be accessed directly.
Now let’s use store in our component.
In the component example, the setup function is a composition API introduced in Vue3, so we won’t go into detail about the use of setup here.
In the example, setup provides the count variable to the view, here the assignment is deconstructed, when the template uses the count variable, it actually accesses the count in the store, why?
This is because Vuex’s state store is responsive.
In the example, the component provides a method to modify the count in the store, and the only way to change the state in Vuex’s store is to commit a mutation. mutations in Vuex are very similar to events: each mutation has a string event type and a callback function (handler ). This callback function is where we actually make the state change, and it accepts state as the first argument.
You can’t call a mutation handler directly. This option is more like an event registration: “Call this function when a mutation of type increment is triggered.” .
Vuex has a total of five core concepts: State, Getter, Mutation, Action and Module.
Vuex uses a single state tree that contains all the application-level state in a single object. It then exists as a “unique data source (SSOT)”. This also means that each application will contain only one instance of store. The single state tree allows us to directly locate any particular state fragment and easily get a snapshot of the entire current application state during debugging.
In the component, we can fetch the registered state via
this.$store.state, and whenever store.state.count changes, the computed property is retrieved and the associated DOM is triggered to be updated.
Vuex “injects” store instances from the root component into all child components via Vue’s plugin system. The child components can be accessed through this.$store.
template can be used directly with this.$store.state.[property] and this can be omitted.
Sometimes we need to derive some state from the state in the store, for example to filter and count lists.
If there are multiple components that need to use this property, we either have to copy the function or extract it to a shared function and import it in multiple places - either way is not ideal.
Vuex allows us to define a “getter” (think of it as a computed property of the store) in the store.
The getter accepts state as its first argument.
Getters are exposed as store.getters objects, and you can access these values as properties.
As mentioned above, the only way to change the state in Vuex’s store is to commit mutation.
The commit method is required to commit a call.
Multiple parameters can also be submitted, and the commit function will expand all parameters:
Action is similar to mutation, except that
- an Action commits a mutation instead of changing state directly.
- Action can contain any asynchronous operation.
The Action function accepts a context object with the same methods and properties as the store instance, so you can call context.commit to submit a mutation, or context.state and context.getters to get the state and getters.
Action is triggered by the store.dispatch method.
At first glance, it seems superfluous. Wouldn’t it be easier to just distribute the mutation? Action is not bound by this restriction! We can perform asynchronous operations inside the action.
Because of the use of a single state tree, all the state of the application is concentrated into one relatively large object. When the application becomes very complex, the store object can become quite bloated.
To solve this problem, Vuex allows us to split the store into modules. Each module has its own state, mutation, action, getter, and even nested submodules - split in the same way from top to bottom: the
For mutation and getter inside a module, the first argument received is the module’s local state object.
Similarly, for actions inside the module, the local state is exposed through context.state, and the root state is context.rootState.
By default, actions and mutations inside modules are still registered in the global namespace - this allows multiple modules to respond to the same action or mutation. getter is also registered in the global namespace by default, but this is not currently the case for functional purpose (just maintaining the status quo to avoid non-compatible changes). Care must be taken not to define two different getters in different, namespace-less modules, leading to errors.
If you want your module to be more encapsulated and reusable, you can make it namespaced by adding namespaced: true. When a module is registered, all its getters, actions and mutations are automatically namespaced according to the path of the module registration. Example.
Namespace-enabled getters and actions receive localized getters, dispatches, and commits; in other words, you don’t need to add additional spatial prefixes within the same module when using module assets. Changing the namespaced attribute does not require any changes to the code within the module.
Vuex4 still has some trouble using TypeScript, and Vue provides an InjectionKey interface, which is a generic type that extends Symbol. It can be used to synchronize the type of the inject value between the provider and the consumer.
Inject the dependency in main.ts.