If you write on the resume “XX e-commerce system” implementation, in fact, the first intuition is that this person must be out of the training class. And our “project management” course is just to do a small e-commerce site. The development lasted about one month, including the buyer side, the seller side and the administrator side. Although the business logic was relatively common, the development still had some gains. The most important gain was the real practice and understanding of Vuex. So, the majority of this article is a summary of Vuex’s practice on the project and the pitfalls it stepped in, and the rest is a summary of some of the other key points of the project.

The bloated Vue component of the past

In the previous projects, after obtaining the back-end interface and requirements, the functions were implemented in the following ways:

  1. Separate Components and Pages, and try to make sure some Components can be reused.
  2. Abstract some reusable SCSS code and design generic style classes.
  3. Configure and encapsulate a layer of low-level methods based on an HTTP library, such as AXIos, and write specific API functions based on that method.
  4. The above encapsulated methods are called within pages and components, in function callbacks orPromisethethenMethod to update data or do more business processing.

Doesn’t seem to be a problem?

Step 1, step 2, and Step 3 are basically fine, but step 4 is the problem. The result is a Vue file that gets bigger and bigger. After a complex page, the Vue file will contain the following contents:

  • dataA large number of data fields in theControls whether to display elements.Rendering data.The variable used for "locking"And so on.
  • increatedormountedIt contains a lot ofrequestandThe callback processing.
  • intemplateComponent properties that are used in theprops.

The end result is that vue files become bloated.

The longer the file, the harder it is to read and the less maintainable it becomes.

No one likes to see a jumbled code file containing logic processing, interface processing, data processing.

Therefore, in order to solve the above problems, the introduction of Vuex is very necessary.

In fact, Vuex has been used before, but the purpose is only to “save a little data for global use”, without in-depth use of Action, Getters, Mutations, etc. This article about Vuex will not introduce its principles and benefits too much, mainly focus on the practice and use experience, Vuex introduction or get started please go to the official documentation.

Clean, decoupled, and accountable

What THE author has done is to basically put all the data requests and updates into Vuex, making Vuex the “data collection and distribution center” of the whole project, while vUE component only dispatches events and binds the data from Vuex.

Simple example

We take the product details page as an example, which contains the following functions:

  • The first time you enter the page, request the product data according to the ID in the URL parameter.
  • Update inventory and price according to the attributes of the item.
  • Add the shopping cart and update the red dot.
  • Place the order.
  • Collect merchandise.

As shown in the figure:

If we don’t use Vuex, the structure of the code might look like this:

<template>

<template>

<script>
export default {
    data() {
        detail: {
            name: ' '.shopId: ' '.id: ' '.pic: ' '.description: ' '.price: ' '.updateTime: ' '.categoryId: ' '.stock: 0.createTime: ' '.attributeList: {},
            collectId: 0,},// select * from 'MARK';
    },
    created(){
        this.$http.get('/product/:id')
          .then()
          // Requests to update other data on one end [MARK]
    },
    methods(){
        clickCart(){
            this.$http.get('xxx')
              .then('xxx')
            this.$emit('xxx'); // Communicate with the upper component to update the shopping cart red dot
        }
        // A bunch of user event firing methods, each with a bunch of HTTP requests and callback processing [MARK]
    },
    computed: {// Some data to judge the status based on the commodity data [MARK]}}</script>

<style>
<! -- Ignore the associated style code -->
<style>
Copy the code

If you follow the above method, although you can ensure that the logical processing of the page is kept in the vue file, it is very bloated, and if you want to add more functions or modify it later, it may need to read more code.

So, the parts of the above code examples that are marked by [MARK] will be the ones that Vuex can optimize. The final code looks like this:

The readability of the code has improved a lot:

  • There are no HTTP requests in this file, nor any request paths. (Request paths are generally static, and writing directly to the HTTP request path is equivalent to writing to the data source, which is very unfriendly for later changes to the data source)
  • Data does not contain any business data fields, only the fields of the control page are reserved
  • The code structure becomes simpler, only[Trigger event] - [Callback]Simple logic like that.

The data processing code is all encapsulated in Vuex:

In the Vuex layer, we not only request the data, but also make judgment and different logic processing on the returned data. At the same time, we set Getters to enable the page to make various binary judgments based on the data provided by Getters.

The Vuex layer brings the following benefits:

  • The same can be triggered on different pagesActionsIn this case, I only wrote it onceAdd to cartFunction, can be used in each page.
  • Actions can be used togetherBy means of combination, we can more easily implement complex business logic, such asUpdate the item data and update the cart data while adding the item to the cartThat takes three timesHTTPFor the business logic of the request, you only need to combine the three Actions, which can be used separately elsewhere.
  • Intuitive, at a glance, you can know what actions are in the commodity model, it is more convenient for New Guy to be familiar with the business logic, and it is also convenient for developers to check whether their code or functions are well considered. (BTW, it’s really hard to find logic in HTML)
  • Reduce communication between componentsA centralized oneThe data warehouseThe benefit is to reduce the operation of data layer by layer, according to the previous coding habits, I will use a lot of$emitandpropsInstead, you just need to trigger the corresponding event in the component to bind the corresponding data.

A new business writing experience

In terms of intuitive experience, using Vuex completely makes the coding clearer, because it takes two to three days to write an overall feature, and Vuex is very helpful for “intermittent programming”, which can quickly pick up the progress of the previous development.

After using Vuex, follow the following steps to develop:

4. Build the Store model of Vuex and define the required method. 5. Write the data and methods associated with the component and bind it to Vuex. 6. Write a callback after triggering the Dispatch.

The author considers several important principles of using Vuex

There are certain specifications for using Vuex, such as form processing, testing, project structure specifications have been displayed on the official website, and some of the following principles are just some of the author’s experience, not necessarily correct, helpful is the best.

[Do not process the page jump] : The page jump indispatchCallback to.

At first, my design was to be responsible for all jump logic and popover logic after the Action requested data. However, this coupled the view layer and the data layer, making the reusability of the Action I abstracted extremely poor. At the same time, the normal writing logic is to see the processing of the view layer in the VUE file.

[Single Responsibility Principle] :mutationandactionTry to keep to the one thing rule.

As mentioned in the previous principle, to improve the reusability of action, it is necessary to ensure that the action to be reused only has one function. For example, updating data A and updating data B should not be merged into one action directly. Instead, two actions should be defined separately and A more complex function should be realized through combination. It’s kind of like the idea of a reduced instruction set.

Such as:

actions:{
    updateA(){}, // A may be used separately elsewhere
    updateB(){},  // B may be used separately elsewhere
    updateAandB({dispatch}){
        dispatch("updateA");
        dispatch("updateB");
    }, // Trigger both A and B complex actions
}
Copy the code

【 Use Promise and AA】(Async & Await)

To give the Dispatch function promise-style ability to handle callbacks, make the return value of the action a Promise object, such as:

// store.js
actions:{
    updateA(){
        return Promise.resolve()
    }
}
Copy the code

Can be used within a component.

. created(){this.$store.dispatch('updateA')
        .then((a)= >{... })}...Copy the code

Vuex generally recommends asynchronous actions, so to make the code more elegant, write it as AA:

// store.js
actions:{
    async updateA(){
        const result = await ajax('/ * * / * *');
        if(result){
            return Promise.resolve()
        }
    }
}
Copy the code

So, the code in practice looks like this:

[Use Namespace], for your own good.

Generally, with VUex, states are divided according to the entity or page to form a module, and a module contains all the actions, states, mutations, and so on that it needs. For example, in e-commerce, there are generally commodities, orders and users. These entities can be divided into modules, as shown in the following figure:

The advantage of splitting is more independent and intuitive. The disadvantage is that if you do not use the namespace, it may cause conflicts of Actions and mutations, just as Vuex also provides the configuration of namespace, refer to the official documents.

The use of insufficient

Don’t use the namespace

Although summed up the principles, but this time did not use namespace, which is a relatively large deficiency, the solution is “manual namespace”, as shown in the figure:

Prefixing the method name of actions with the entity name to distinguish between different methods is a bad idea.

Parts of the code are still duplicated

This occurs in code after the asynchronous data is obtained. This code is often repeated as follows:

if (result.code){
    return Promise.resolve(data);
}
return Promise.reject(msg);
Copy the code

It’s not much, but it’s still possible to abstract this logic. Next time, we’re going to add an action in RootState to handle such back-end return data. Expect the following results:

actions: {
    parseResult({}, result){
      if (result.code){
        return Promise.resolve(data);
      }
        return Promise.reject(msg);
    },
    async getA({dispatch}){
        const result = await http.get('xx/xx');
        return dispatch('parseResult', result); // One line , it's clean}}Copy the code

Other harvest

Embrace Vue CLI 3

3.0 is basically very simple in configuration. We haven’t developed Vue project for a long time, remember the last Vue project, there is still a lot of xxx.congfig.js, but now, basically integrated into the CLI, through a vue.config.js can meet most of the development needs. The configuration of this project is as follows:

More intuitive than the previous configuration, please refer to: cli.vuejs.org/zh/, as for the plug-in mechanism, this development did not use, but when installing third-party packages can use vue add, there is a GUI can see which plug-ins installed.

willVue. Use and Vue. InstallThe places used are summarized topluginsdirectory

This project is a multi-page application with a total of 3 Vue instances, so it is expected to be able to inject third-party dependencies such as Axios, Qrcode, Lazyload and other tools or third-party components on demand. All of them are listed in the plugins directory, as shown below:

The advantage of this encapsulation is that I can import third-party dependencies on demand for each Vue instance with just one import, as shown below:

Start thinking about optimization

A large Web app can be packaged less than 500KB compressed, so this is used as a Benchmark to optimize the packaged size of the project and introduce third-party dependencies (especially Element and Lodash) as needed to reduce the project volume. But the main thing is to learn to use the Webpack analyse tool.

conclusion

In short, this project is mainly to refresh the cognition of Vuex, which can make our vUE components more readable and maintainable. At the same time, it can also make the data update section of the code more reusable. Using Vuex to build a centralized data center also makes the development process smoother and worth learning.

Reference:

What is Vuex?