Vue Family bucket -Vue-router&Vuex

About the routing and data management of Vue, I will briefly summarize the most frequently asked questions in the interview:

  • How does routing work?
  • Hash and History modes used in the project? What else is there besides these two? Under what circumstances?
  • What happens when I go live in History mode
  • If you know redux, will you compare the difference between vuex and Redux?
  • Let’s talk about how VUEX works

Come on, old iron, feel good students, leave your likes and attention ah

Vue-Router

data

  • Vue-router
  • Vuex

introduce

The Vue Router is the official route manager of vue. js. Its deep integration with the vue.js core makes building a single page application a breeze. The functions included are:

  • Nested routing/viewing diagrams
  • Modular, component-based routing configuration
  • Route parameters, queries, and wildcards
  • View transition effect based on vue. js transition system
  • Fine-grained navigation control
  • Links with automatically activated CSS classes
  • HTML5 history mode or hash mode, automatically demoted in IE9
  • Custom scroll bar behavior

start

Creating a single page application with vue.js + Vue Router is very simple. With vue.js, we can already compose applications by combining components. When you add a Vue Router, what we need to do is map the components to routes and tell the Vue Router where to render them

The installation

npm i vue-router -S

In the main. In js

import Vue from 'vue'
import VueRouter from 'vue-router'

Vue.use(VueRouter)
Copy the code

Recommended use: Vue Add Router (remember to submit in advance)

The basic use

router.js

import Vue from 'vue'
/ / 1. Imported
import Router from 'vue-router'
import Home from './views/Home.vue'
import About from './views/About.vue'
//2. The modularization mechanism uses Router
Vue.use(Router)

//3. Create the router object
const router = new Router({
    routes: [{path: '/home'.component: Home
    },
    {
      path: '/about'.component: About
    }
  ]
})
export default router;
Copy the code

main.js

import Vue from 'vue'
import App from './App.vue'
import router from './router'

Vue.config.productionTip = false

new Vue({
  // 4. Mount the root instance
  router,
  render: h= > h(App)
}).$mount('#app')

Copy the code

After completing the above configuration

App.vue

<template>
  <div id="app">
    <div id="nav">
      <! -- Use router-link component to navigate -->
      <! -- Specify the connection by passing the TO attribute -->
      <! -- Router-link is rendered as an A tag by default -->
      <router-link to="/">Home</router-link> |
      <router-link to="/about">About</router-link> |
    </div>
    <! -- Route exit -->
    <! -- Routing matching components will be rendered here -->
    <router-view/>
  </div>
</template>
Copy the code

Open your browser and switch the Home and About hyperlinks to see what happens

After routing

When configuring a route, you can add a name to the route. Then you can access the route dynamically based on the name

const router = new Router({
    routes: [{path: '/home'.name:"home".component: Home
    },
    {
      path: '/about'.name:'about'
      component: About
    }
  ]
})
Copy the code

To link to a named route, pass an object to the to property of the router-link:

<router-link :to="{name:'home'}">Home</router-link> |
<router-link :to="{name:'about'}">About</router-link> |
Copy the code

Dynamic route matching

It is often necessary to map all routes that a pattern matches to the same component. For example, we have a User component that is used to render all users with different ids. We can do this by using the “dynamic segment” in the vue-Router’s routing path

User.vue

<template> <div> <h3> user page </h3> </div> </template> <script> export default {}; </script> <style lang="scss" scoped> </style>Copy the code

The routing configuration

const router = new Router({
    routes:[
        {
            path: '/user/:id'.name: 'user'.component: User,
        },
    ]
})
Copy the code
<router-link :to="{name:'user',params:{id:1}}">User</router-link> |
Copy the code

access

http://localhost:8080/user/1

http://localhost:8080/user/2

See the effect

When a route is matched, the parameter value is set to this.$route.params, which can be used in each component. Therefore, we can update the User template to output the ID of the current User:

<template>
  <div>
    <h3>{{$route.params.id}}</h3>
  </div>
</template>
Copy the code
Responds to changes in route parameters

As a reminder, when using routing parameters, such as navigating from /user/1 to /user/2 ‘, the original component instance is reused. Because both routes render the same component, reuse is more efficient than destroying and creating. However, this also means that the component’s lifecycle hooks are no longer called.

To respond to changes in routing parameters when reusing components, you can simply watch the $route object:

$route object watch: {$route(to, from) {console.log(to.params.id); }}, * /
// Or use the navigation guard
beforeRouteUpdate(to,from,next){
	// Check the route change
    // Make sure to call next, otherwise it will block the route change
    next();
}
Copy the code
404 routing
const router = new Router({
    routes: [//....
        // If the reason is not matched, the 404 page is displayed
        {
            path: The '*'.component: () = > import('@/views/404')}]})Copy the code

When using wildcard routes, ensure that the routes are in the correct order, that is, the routes containing wildcards should be placed last. The route {path: ‘*’} is usually used for client 404 errors

When a wildcard is used, a parameter called pathMatch is automatically added to $route.params. It contains the parts of the URL that are wildcard matched:

{
    path: '/user-*'.component: () = > import('@/views/User-admin.vue')}this.$route.params.pathMatch // 'admin'
Copy the code
Matching priority

Sometimes, a path can match multiple routes. In this case, the preference of the routes is based on the definition order of the routes: The one that is defined first has the highest preference.

Query parameters

Like address that appear on this: http://localhos:8080/page? id=1&title=foo

const router = new Router({
    routes: [//....
        {
            name:'/page'.name:'page'.component:() = >import('@/views/Page.vue')}]})Copy the code
 <router-link :to="{name:'page',query:{id:1,title:'foo'}}">User</router-link> |
Copy the code

Go to http://localhos:8080/page? Id = 1 & title = foo view the Page

Page.vue

< span style = "box-sizing: border-box; color: RGB (74, 74, 74); line-height: 20px; font-size: 13px! Important; white-space: inherit! Important; () {// check the route information object console.log(this.$route); }, } </script> <style lang="scss" scoped> </style>Copy the code

Route redirection and aliases

Example redirects from/to /home:

const router = new Router({
    mode: 'history'.routes: [
        / / redirection
        {
            path: '/'.redirect: '/home'
        }
        {
        path: '/home'.name: 'home'.component: Home
        },
    ]
})
Copy the code

The target of the redirect can also be a named route:

const router = new VueRouter({
  routes: [{path: '/'.redirect: { name: 'name'}}}])Copy the code

The alias

{
    path: '/home'.name: 'home'.component: Home,
    alias: '/alias'
}
Copy the code

Names, names only When users visit http://loacalhost:8080/alias, display Home components

The “alias” feature gives you the freedom to map UI structures to arbitrary urls, rather than being limited to configured nested structures.

Routing components pass parameters

Using a $route in a component makes it highly coupled to its corresponding route, limiting its flexibility by making the component usable only at certain urls.

Use props to decouple components from routes:

Replace coupling with $route

 {
      path: '/user/:id'.name: 'user'.component: User,
      props:true
},
Copy the code

User.vue

<template> <div> <h3> user page {{$route.params.id}}</h3> user page {{{id}}</h3> </h3> user page {{id}}</h3> </h3> </div> </template> <script> <script> export default{ / /... props: { id: { type: String, default: '' }, }, } </script>Copy the code

Props can also be a function

{
      path: '/user/:id'.name: 'user'.component: User,
      props: (route) = >({
        id: route.params.id,
        title:route.query.title
      })
      
}
Copy the code

User.vue

< the template > < div > < h3 > user page {{id}} - {{title}} < / h3 > < / div > < / template > < script > export default {/ /... props: { id: { type: String, default: '' }, title:{ type:String } }, }; </script>Copy the code

Programmatic navigation

In addition to using

to create a tag to define the navigation link, we can write code to do this using the instance method of the router.

Note: Within the Vue instance, you can pass
r o u t e r Access the route instance. So you can call t h i s . Router Accesses a route instance. So you can call this.
The router. Push.

declarative programmatic
<router-link :to="..." > router.push(...)

The argument to this method can be a string path or an object describing the address. For example,

/ / string
this.$router.push('home')

/ / object
this.$router.push({ path: 'home' })

// The named route
this.$router.push({ name: 'user'.params: { userId: '123' }})

// With query parameters, change to /register? plan=private
this.$.push({ path: 'register'.query: { plan: 'private' }})
Copy the code

Move back

// Move forward in the browser record, equivalent to history.forward()
router.go(1)

// Record a step back, equivalent to history.back()
router.go(-1)

// Record 3 steps forward
router.go(3)

// If the history record is not enough, then fail silently
router.go(-100)
router.go(100)
Copy the code

Embedded routines by

Real-world application interfaces are typically composed of multiple layers of nested components. Similarly, the segments of the dynamic path in the URL correspond to the nested layers of components in some structure

/user/1/profile                     /user/1/posts +------------------+ +-----------------+ | User | | User | | +--------------+ | | +-------------+ | | | Profile |  | +------------> | | Posts | | | | | | | | | | | +--------------+ | | +-------------+ | +------------------+ +-----------------+Copy the code

router.js

{
      path: '/user/:id'.name: 'user'.component: User,
      props: ({params,query}) = >({
        id: params.id,
        title:query.title
      }),
      children: [// If /user/:id/profile is successfully matched,
        // The Profile will be rendered in the User's 
      
        {
          path:"profile".component: Profile
        },
        // When /user/:id/posts matches,
        // Posts will be rendered in User's 
      
        {
          path: "posts".component: Posts
        }
      ]
      
}
Copy the code

Add a

to the User component template:

<template>
  <div>
    <h3>{{$route.params.id}}</h3>
    <h3>User page {{id}}</h3>
    <router-view></router-view>
  </div>
</template>
Copy the code

App.vue

<template>
	<div id='app'>
         <! -- Nesting reasons -->
      <router-link to="/user/1/profile">User/profile</router-link> |
      <router-link to="/user/1/posts">User/posts</router-link> |
    </div>
</template>
Copy the code

Named view

Sometimes you want to show multiple views at the same time (peer), rather than nested display, such as creating a layout with sidebar and main, this time the named view will come in handy

{
      path: '/home'.name: 'home'.// Note that the key is components
      components: {
        default: Home, // Default name
        main: () = >import('@/views/Main.vue'),
        sidebar: () = > import('@/views/Sidebar.vue')}},Copy the code

App.vue

<router-view/>
<router-view name='main'/>
<router-view name='sidebar'/>
Copy the code

Navigation guard

Navigation indicates that the route is changing.

Complete navigation parsing process
  1. Navigation is triggered.
  2. Call exit guard in a deactivated component.
  3. Call globalbeforeEachThe guards.
  4. Called in a reused componentbeforeRouteUpdateGuard (+ 2.2).
  5. Called in the routing configurationbeforeEnter.
  6. Resolve the asynchronous routing component.
  7. Called in an activated componentbeforeRouteEnter.
  8. Call globalbeforeResolveGuard (+ 2.5).
  9. Navigation is confirmed.
  10. Call globalafterEachHook.
  11. Triggers a DOM update.
  12. Called with the created instancebeforeRouteEnterGuard passnextCallback function.
Global guard

You can register a global front guard using router.beforeeach

const router = new VueRouter({ ... })

router.beforeEach((to, from, next) = > {
  // ...
})
Copy the code

There is a demand, the user access in browsing the site, will visit many components, when the user to jump to/notes, found that the user is not logged in, should allow the user to log in to view at this time, should allow the user to jump to the login page, login to finish before he can see the contents of my notes, at this time of global guard has played a key role

There are two routes/Notes and /login

router.vue

const router = new VueRouter({
    routes:[
        {
            path: '/notes'.name: 'notes'.component: () = > import('@/views/Notes')}, {path: "/login".name: "login".component: () = > import('@/views/Login')]}})// Global guard
router.beforeEach((to, from, next) = > {
    // The user accesses '/notes'
    if (to.path === '/notes') {
        // Check to see if the user saved the login status information
        let user = JSON.parse(localStorage.getItem('user'))
        if (user) {
            // If yes, release directly
            next();
        } else {
            // If no, the user logs in to the login page
            next('/login')}}else{ next(); }})Copy the code

Login.vue

<template> <div> <input type="text" v-model="username"> <input type="password" v-model="pwd"> <button </div> </template> <script> export default {data() {return {username: "", PWD: ""}; }, methods: { handleLogin() { // 1. SetTimeout (() => {let data = {username: this.username}; Localstorage.setitem ("user", json.stringify (data)); $router.push({name: "notes"}); }, 1000); }}}; </script>Copy the code

App.vue

<! -- Global guard demo -->
<router-link to="/notes">My notes</router-link> |
<router-link to="/login">The login</router-link> |
<button @click="handleLogout">exit</button>
Copy the code
export default {
  methods: {
     handleLogout() {
      // Delete the login status information
      localStorage.removeItem("user");
      // Go to the home page
      this.$router.push('/')}}}Copy the code
A guard inside a component

You can define the following route navigation guards directly in the routing component:

  • beforeRouteEnter
  • beforeRouteUpdate(new) 2.2
  • beforeRouteLeave
<template> <div> <h3> User edit page </h3> <textarea name id cols="30" rows="10" v-model="content"></textarea> <button @ click = "saveData" > save < / button > < div class = "wrap" v - for = "(item, index) in the list" : the key = "index" > < p > {{item. The title}} < / p > < / div > </div> </template> <script> export default { data() { return { content: "", list: [], confir: true }; }, methods: { saveData() { this.list.push({ title: this.content }); this.content = ""; } }, beforeRouteLeave(to, from, Next) {// this' if (this.content) {alert(" make sure you save the information before you leave "); next(false); } else { next(); }}}; </script>Copy the code
Implement permission control on routing meta information

Set the meta field for the route to which you want to add permission

{
      path: '/blog'.name: 'blog'.component: () = > import('@/views/Blog'),
      meta: {
        requiresAuth: true}}, {// Route exclusive guards
      path: '/notes'.name: 'notes'.component: () = > import('@/views/Notes'),
      meta: {
        requiresAuth: true}},Copy the code
// Global guard
router.beforeEach((to, from, next) = > {
  if (to.matched.some(record= > record.meta.requiresAuth)) {
    // Requires permission
    if(!localStorage.getItem('user')){
      next({
        path:'/login'.query: {redirect:to.fullPath
        }
      })
    }else{ next(); }}else{ next(); }})Copy the code

login.vue

// Login operation
handleLogin() {
    // 1. Obtain the user name and password
    // 2. Interacts with the backend
    setTimeout(() = > {
        let data = {
            username: this.username
        };
        localStorage.setItem("user".JSON.stringify(data));
        // Go to the previous page
        this.$router.push({path: this.$route.query.redirect });
    }, 1000);
}
Copy the code
Data acquisition

Sometimes, after entering a route, you need to get data from the server. For example, when rendering user information, you need to get the user’s data from the server. We can do this in two ways:

  • Fetch after navigation: Complete the navigation and then fetch the data in the following component lifecycle hooks. Displays an indication such as “loading” during data fetch.
  • Fetch before navigation: Before navigation is complete, data is obtained from the guard that the route enters, and the navigation is performed after the data is obtained successfully.
Obtain the data after the navigation is complete

When you do this, we immediately navigate and render the component, and then get the data in the component’s created hook. This gives us the opportunity to show a loading state during data acquisition and to show different loading states between different views.

<template> <div class="post"> <div v-if="loading" class="loading">Loading... </div> <div v-if="error" class="error">{{ error }}</div> <div v-if="post" class="content"> <h2>{{ post.title }}</h2> <p>{{ post.body }}</p> </div> </div> </template>Copy the code
export default {
  name: "Post".data() {
    return {
      loading: false.post: null.error: null
    };
  },
    // Obtain data after the component is created,
    // The data is already monitored
  created() {
     // If the route changes, the method is executed again
    this.fetchData();
  },
  watch: {
    $route: "fetchData"
  },
  methods: {
    fetchData() {
      this.error = this.post = null;
      this.loading = true;
      this.$http.get('/api/post')
      .then((result) = > {
          this.loading = false;
          this.post = result.data;
      }).catch((err) = > {
          this.error = err.toString(); }); }}};Copy the code

Vuex

Vuex is a state management pattern developed specifically for vue.js applications. It uses centralized storage to manage the state of all components of an application, and rules to ensure that the state changes in a predictable manner

Install vuex

vue add vuex
Copy the code

store.js

import Vue from 'vue'
import Vuex from 'vuex'
// Make sure to start with vue.use (Vuex)
Vue.use(Vuex)

export default new Vuex.Store({
  state: { //this.$store.state.count
    count:0
  },
  getters: {evenOrOdd:(state) = >{ //this.$store.getters.evenOrOdd
      return state.count % 2= = =0 ? 'even number': 'odd'}},mutations: { 
    increment(state){ //this.$store.commit('increment')
      state.count++
    },
    decrement(state){ //this.$store.commit('decrement')
      state.count--
    }
  },
  actions: {
    increment({commit}){  //this.$store.dispatch('increment')
      // The only way to change the state is to commit mutation
      commit('increment');
    },
    decrement({ commit }) { //this.$store.dispatch('decrement')
      commit('decrement');
    },
    incrementAsync({commit}){ //this.$store.dispatch('incrementAsync')
       return new Promise((resolve, reject) = > {
        setTimeout(() = > {
          commit('increment');
          resolve(10);
        }, 1000); }}}})Copy the code

We can get the state object from this.$store.state at an appropriate time for the component, and use the this.store.com. MIT method to violate the state change

this.$store.commit('increment');
Copy the code

MapState helper function

When a component needs to obtain multiple states, declaring them all as computed properties can be somewhat repetitive and redundant. To solve this problem, we can use the mapState helper function to help us generate computed properties that allow you to press the key fewer times

// In the separately built version, the helper function is vuex.mapState
import { mapState } from 'vuex'

export default {
  // ...
  computed: mapState({
    // The arrow function makes the code more concise
    count: state= > state.count,

    // Pass the string argument 'count' as' state => state.count '
    countAlias: 'count'.// In order to be able to use 'this' to get local state, you must use regular functions
    countPlusLocalState (state) {
      return state.count + this.localCount
    }
  })
}
Copy the code

We can also pass an array of strings to mapState when the name of the mapping’s computed property is the same as the name of the state’s child node.

computed: mapState([
  // Map this.count to store.state.count
  'count'
])
Copy the code

Object expansion operator

The mapState function returns an object. How do we mix it with locally computed properties? Often, we need to use a utility function to combine multiple objects into one so that we can pass the final object to the computed property. But since the advent of the object expansion operator, writing has been greatly simplified

computed:{ ... mapState({"count"})}Copy the code

MapGetters helper function

The mapGetters helper function simply maps getters in a store to locally computed properties:

import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
     ...mapGetters([
       'evenOrOdd'])}}Copy the code

If you want to give a getter property another name, use the object form:

mapGetters({
  // Map 'this.doneevenorodd' to 'this.$store.getters. EvenOrOdd'
  doneEvenOrOdd: 'evenOrOdd'
})
Copy the code

Mutation

The only way to change the state in Vuex’s Store is to submit mutation. Mutations in Vuex are very similar to events: each mutation has an event type (type) of a string and a callback function (handler). This callback function is where we actually make the state change, and it takes state as the first argument:

MapMutation

You can use this.store.com MIT (‘ XXX ‘) to submit mutations in the component, or map the methods in the component to store.com MIT calls using the mapMutations assist function, which requires injecting the Store at the root node.

import { mapMutations } from 'vuex'

export default {
  // ...
  methods: {
   ...mapMutations('counter'['increment'.'decrement',].}}Copy the code

Action

Action is similar to mutation, except that:

  • The Action commits the mutation instead of directly changing the state.
  • An Action can contain any asynchronous operation

MapAction helper function

import { mapMutations } from 'vuex'

export default {
  // ...
  methods: {
    ...mapActions('counter'['incrementAsync'])}}Copy the code

submission

// Inside the component
// Distribute as a payload
this.$store.dispatch('incrementAsync', {
  amount: 10
})

// Distribute as objects
this,.$store.dispatch({
  type: 'incrementAsync'.amount: 10
})
Copy the code

Module

By using a single state tree, all the state of the application is concentrated into one 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 the same way from top to bottom:

Make a shopping cart case

There are two modules, CART and Products

Create the Store folder

| - store ├ ─ ─ index. The js └ ─ ─ modules ├ ─ ─ cart. Js └ ─ ─ products. JsCopy the code

cart.js

If you want more encapsulation and reuse, you can make your module namespaced: true by adding namespaced: true

When a module is registered, all its getters, actions, and mutations are automatically named according to the registered path of the module.

export default {
    // Make the current module more encapsulated and reusable
    namespaced: true.state: {... },getters: {... },mutations: {... },actions: {... }},Copy the code

products.js

export default {
    // Make the current module more encapsulated and reusable
    namespaced: true.state: {... },getters: {... },mutations: {... },actions: {... }},Copy the code

index.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
import cart from './modules/cart';
import products from './modules/products';
export default new Vuex.Store({
    modules:{
        cart,
        products,
    }
})
$store.state.cart // Obtain the state of the cart
//this.$store.state.products // Obtain the status of products
Copy the code

Complete Shopping cart Case

The mock data

New vue. Config. Js

const products = [
    { id: 1.title: 'iphone11'.price: 600.inventory: 10 },
    { id: 2.title: 'iphone11 pro'.price: 800.inventory: 5 },
    { id: 3.title: 'iphone11 max'.price: 1600.inventory: 6},]module.exports = {
    devServer: {
        before(app, server) {
            app.get('/api/products'.(req, res) = > {
                res.json({
                    products:products
                })
            })
        }
    }
}
Copy the code

cart.js

export default {
    // Make the current module more encapsulated and reusable
    namespaced: true.state: {
        items: []},getters: {
        // Get the items in the shopping cart
        cartProducts: (state, getters, rootState) = > {
            return state.items.map(({ id, quantity }) = > {
                const product = rootState.products.products.find(product= > product.id === id)
                return {
                    title: product.title,
                    price: product.price,
                    quantity
                }
            })
        },
        // The total price of the cart
        cartTotalPrice: (state, getters) = > {
            return getters.cartProducts.reduce((total, product) = > {
                return total + product.price * product.quantity
            }, 0)}},mutations: {
        pushProductToCart(state, { id }) {
            state.items.push({
                id,
                quantity: 1})},incrementItemQuantity(state, { id }) {
            const cartItem = state.items.find(item= >item.id === id); cartItem.quantity++; }},actions: {
        // Add items to the cart
        addProductToCart({ commit, state }, product) {
            // If in stock
            if (product.inventory > 0) {
                const cartItem = state.items.find(item= > item.id === product.id);
                if(! cartItem) { commit('pushProductToCart', { id: product.id });
                } else {
                    commit('incrementItemQuantity', cartItem);
                }
                / / submit products module decrementProductInventory method
                // Reduce the number of items in inventory by 1
                commit('products/decrementProductInventory', { id: product.id }, { root: true})}},}Copy the code

products.js

import Axios from "axios";

export default {
    // Make the current module more encapsulated and reusable
    namespaced: true.state: {
        products: []},getters: {},mutations: {
        setProducts(state, products) {
            state.products = products;
        },
        // Methods of reducing commodity inventory
        decrementProductInventory(state, { id }) {
            const product = state.products.find(product= > product.id === id)
            product.inventory--
        }
    },
    actions: {
        // How to get all the goods
        getAllProducts({ commit }) {
            Axios.get('/api/products')
                .then(res= > {
                    console.log(res.data.products);
                    commit('setProducts',res.data.products)
                })
                .catch(err= > {
                    console.log(err); }})}},Copy the code

Products.vue

<template> <div> <h3> Shop </h3> <ul> <li v-for='product in products' :key =' product.id'> {{product.title}} - {{product.price | currency}} <br> <button :disabled='! Product.inventory '@click='addProductToCart(product)'> Add to cart </button> </li> </ul> <hr> </div> </template> <script> import { mapState,mapActions } from "vuex"; export default { name: "ProductList", data() { return {}; }, computed: { products(){ return this.$store.state.products.products } }, methods: { ... mapActions('cart',[ 'addProductToCart' ]) }, created() { this.$store.dispatch("products/getAllProducts"); }}; </script> <style scoped> </style>Copy the code

Cart.vue

<template> <div> <h2> < I > Please add products to your cart.</ I > <ul> <li v-for="product in products" :key="product.id" - > {{product. The title}} {{product. The price | currency}} x {{product. Quantity}} < / li > < / ul > < p > total price: {{total | currency}} < / p > </div> </template> <script> import { mapGetters,mapState } from "vuex"; export default { name: "shoppingcart", computed:{ ... mapGetters('cart',{ products:'cartProducts', total:'cartTotalPrice' }) } }; </script> <style scoped> </style>Copy the code

Under what circumstances should I use Vuex?

Vuex helps manage shared state and comes with more concepts and frameworks. This requires a balance between short – and long-term benefits.

If you don’t plan to develop large, single-page applications, using Vuex can be tedious and redundant. That’s true — if your application is simple enough, you’re better off not using Vuex. A simple store pattern is all you need. However, if you need to build a medium to large single-page application, you are likely to be thinking about how to better manage state outside of components, and Vuex would be a natural choice. To quote Dan Abramov, author of Redux:

The Flux architecture is like glasses: you know when you need it

The plug-in

The log plug-in

Vuex comes with a logging plugin for general debugging:

import createLogger from 'vuex/dist/logger'

const store = new Vuex.Store({
    plugins: [createLogger({
        collapsed: false.// Automatically expand the record mutation})]})Copy the code

Note that the Logger plug-in generates a snapshot of the status, so use it only in a development environment.