Vue3.0 family bucket most complete Getting Started Guide - vue-router@4.x and vuex@4.x (3/4)

Posted by plex303 on Wed, 09 Feb 2022 04:22:02 +0100

3, vue-router@4.x and vuex@4.x

vue-router@4.x and vuex@4.x
vue2.x uses vue-router@3.x and vuex@3.x ,vue3.x uses vue-router@4.x and vuex@4.x , avoid following vue3 The version numbers of X are mixed. In fact, vue3 Both router and vuex used by X are 4 x.
Vue2.0 is used here for convenience of understanding x router,vue3.x router instead of vue-router@3.x And vue-router@4.x , unified use of vue2 x vuex,vue3.x vuex instead vuex@3.x and vuex@4.x .

1,vue-router@4.x

Create instance

// vue2.x router
import Vue from 'vue'
import Router from 'vue-router'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]

Vue.use(Router)

const router = new Router({
  base: process.env.BASE_URL,
  mode: 'history',
  scrollBehavior: () => ({ y: 0 }),
  routes
})

export default router

// vue3.x router
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
  }
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default router

scrollBehavior scrollbehavior

vue3. Vue2 is discarded by X router The {selector, x, y, offset} in X router is replaced by {el, left, top, behavior}. The new api semantics are closer to the original DOM

// vue2.x router
const router = new Router({
  base: process.env.BASE_URL,
  mode: 'history',
  scrollBehavior: () => ({ x: 0, y: 0 }),
  routes
})

// vue3.x router
const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes,
  scrollBehavior(to, from, savedPosition) {
    // scroll to id `#app` + 200px, and scroll smoothly (when supported by the browser)
    return {
      el: '#app',
      top: 0,
      left: 0,
      behavior: 'smooth'
    }
  }
})

Routing component jump

vue2.x use the route option redirect to set automatic route adjustment, vue3 If this option is removed from X, an empty path origin matching jump will be added to the sub route

// vue2.x router
[
  {
    path: '/',
    component: Layout,
    name: 'WebHome',
    meta: { title: 'Platform home page' },
    redirect: '/dashboard', // Write jump here
    children: [
      {
        path: 'dashboard',
        name: 'Dashboard',
        meta: { title: 'workbench' },
        component: () => import('../views/dashboard/index.vue')
      }
    ]
  }
]
// vue3.x router
[
  {
    path: '/',
    component: Layout,
    name: 'WebHome',
    meta: { title: 'Platform home page' },
    children: [
      { path: '', redirect: 'dashboard' }, // Write jump here
      {
        path: 'dashboard',
        name: 'Dashboard',
        meta: { title: 'workbench' },
        component: () => import('../views/dashboard/index.vue')
      }
    ]
  }
]

Capture all routes: /: catchAll(. *)
When capturing all routes (/ *), you must now define them using parameters with custom regular expressions: /: catchAll(. *)

// vue2.x router
const router = new VueRouter({
  mode: 'history',
  routes: [
    { path: '/user/:a*' },
  ]
})

// vue3.x router
const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/user/:a:catchAll(.*)', component: component },
  ]
})

When the route is / user/a/b, the captured params are {"a": "a", "catchAll": "/ b"}

router.resolve

router.match Resolve is merged into router Resolve, but the signature is slightly different

// vue2.x router
...
resolve ( to: RawLocation, current?: Route, append?: boolean) {
  ...
  return {
    location,
    route,
    href,
    normalizedTo: location,
    resolved: route
  }
}

// vue3.x router
function resolve(
    rawLocation: Readonly<RouteLocationRaw>,
    currentLocation?: Readonly<RouteLocationNormalizedLoaded>
  ): RouteLocation & { href: string } {
  ...
  let matchedRoute = matcher.resolve(matcherLocation, currentLocation)
  ...
  return {
    fullPath,
    hash,
    query: normalizeQuery(rawLocation.query),
    ...matchedRoute,
    redirectedFrom: undefined,
    href: routerHistory.base + fullPath,
  }
}

Get current route

Delete router Getmatchedcomponents, which can be obtained from router currentRoute. value. Get router from matched Getmatchedcomponents returns the target location or the component array matched by the current route (it is the definition / construction class of the array, not the instance). It is usually used when the data rendered by the server is preloaded.

[{
  aliasOf: undefined
  beforeEnter: undefined
  children: []
  components: {default: {...}, other: {...}}
  instances: {default: null, other: Proxy}
  leaveGuards: []
  meta: {}
  name: undefined
  path: "/"
  props: ƒ (to)
  updateGuards: []
}]

use

If used, you may need to wait until the router is ready to mount the application
app.use(router)

// Note: on Server Side, you need to manually push the initial location
router.isReady().then(() => app.mount('#app'))

In general, normal mounting can also be used, but now navigation is asynchronous. If there is a route guard during route initialization, there will be a transition of initial rendering before resolve, just like providing an appear ance for
In server-side rendering (SSR), you need to pass the appropriate history mode

const history = isServer ? createMemoryHistory() : createWebHistory()
const router = createRouter({ routes, history })
// on server only
router.push(req.url) // request url
router.isReady().then(() => {
  // resolve the request
})

When push ing or resolving a named route that does not exist, an error will be raised instead of navigating to the root route "/" and displaying nothing
In vue2 In X router, when push ing a named route that does not exist, the route will navigate to the root route "/", and nothing will be rendered. The browser console will only print warnings, and the url will jump to the root route.

const router = new VueRouter({
  mode: 'history',
  routes: [{ path: '/', name: 'foo', component: Foo }]
}
this.$router.push({ name: 'baz' })

In vue3 In X router, the same method will cause errors.

const router = createRouter({
  history: routerHistory(),
  routes: [{ path: '/', name: 'foo', component: Foo }]
})
...
import { useRouter } from 'vue-next-router'
...
const router = userRouter()
router.push({ name: 'baz' })) // This line of code will report an error

Get route

Some online tutorials will tell you to access router and store objects through ctx, but in fact, this method can only be effective in the development mode. After compiling in the production environment, the properties seen by ctx under development cannot be accessed, which is easy to mislead you.

Examples of errors:

import { getCurrentInstance } from 'vue'

export default {
  setup () {
    const { ctx } = getCurrentInstance()
    console.log(ctx)
    console.log(ctx.$router.currentRoute.value)
    const userId = computed(() => ctx.$store.state.app.userId)
    return {
      userId
    }
  }
}

Correct use:

import { getCurrentInstance } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useStore } from 'vuex'

export default {
  setup () {
    const { ctx } = getCurrentInstance()
    console.log(ctx)
    const router = useRouter()
    const route = useRoute()
    const store = userStore()
    console.log(router, route, store)
    console.log(router.currentRoute.value)
    const userId = computed(() => store.state.app.userId)
    return {
      userId
    }
  }
}

2,vuex@4.x

vuex4. There are few breaking change s in X, and there are few overall changes
Create instance

// vue2.x vuex
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {},
  mutations: {},
  actions: {},
  getters: {},
  modules: {}
}
// vue3.x vuex
import Vuex from 'vuex'

export default Vuex.createStore({
  state: {},
  mutations: {},
  actions: {},
  getters: {},
  modules: {}
})

Get store

// vue3.x vuex
import { getCurrentInstance } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { useStore } from 'vuex'

export default {
  setup () {
    const { ctx } = getCurrentInstance()
    console.log(ctx)
    const router = useRouter()
    const route = useRoute()
    const store = userStore()
    console.log(router, route, store)
    console.log(router.currentRoute.value)
    const userId = computed(() => store.state.app.userId)
    return {
      userId
    }
  }
}

Topics: TypeScript Vue