Vue route —— vue-router

          Looking back at the first two articles, we talked about first-level routing, declarative navigation, programmatic navigation, routing redirection, nested routing, and dynamic routing. Then in this article, we will talk about Vue routing-related content:

named route        

        Named routes, as the name suggests, have named routes, and continue the previous case:

        Configure routing information in the /router/index.js file - route naming

<!-- /router/index.js -->
...
  {
    path: '/play/:id',
    component: Play,
    name: 'playMusic'
  }
]
...

params

        Add a name to the route information and assign the route name of 'playMusic'; so what can be done by adding this route name? The previous article selected the song and clicked to jump to the play page, using the js method (location.href) and the programmatic navigation method provided by vue-router (this.$router.push(`/play/${id}` ) ), now that you have a route name, you can still use the programmatic navigation method provided by vue-router to adjust the code as follows:

<!-- /views/music/KuGou.vue -->
...
  methods: {
    handlePlay (id) {
      // alert('获取歌曲id:' + id)
      // location.href = '#/play'
      // 编程式导航
      // this.$router.push(`/play/${id}`)
      this.$router.push({ name: 'playMusic', params: { id: id } })
    }
  }
}
</script>

        Let's test run it:

query

        What is used here is a dynamic routing method. By selecting a song, carrying the id of the song to jump to the playback page, and requesting the playback link of the song through the song id. Before using dynamic routing, this.$ is used router.push(`/play/${id}`), the following situation occurs:

        There is no routing information for /play/10001 configured in the routing, and there are more than a dozen songs. It is obviously unreasonable to configure such routing information! But how can this be done without using dynamic routing?

<!-- /router/index.js -->
...
  {
    path: '/play',
    component: Play,
    name: 'playMusic'
  }
]
...

        The parameters carried by the dynamic route are in the format of /play/:id, so if the parameters carried are in the format of /play?id=, how can they be obtained? —— query

<!-- PlayView.vue -->
<template>
    <div>
        <h3>播放界面</h3>
        当前歌曲Id —— {
   
   { songId }}
    </div>
</template>

<script>
export default {
  mounted () {
    // this.songId = this.$route.params.id
    this.songId = this.$route.query.id
    // console.log(this.$router)
    console.log(this.$route)
  },
  data () {
    return {
      songId: ''
    }
  }
}
</script>

        Let's test run it:

         Then this piece of content has come to an end, send the carried id to the playback page, and play through ajax to request the backend to get the playback link and play it in the playback page; then let’s talk about the routing mode:

routing pattern

        Vue supports two routing modes: 1. hash mode 2. history mode

hash模式:        http://localhost:8080/#/music/
history模式:     http://localhost:8080/music

        The above example uses the hash mode:

        How to modify it to history mode? Just add mode: 'history' in /router/index.js;

<!-- /router/index.js -->
...
const router = new VueRouter({
  mode: 'history',
  routes
})

export default router

        After the addition is complete, re-run the project npm start;

         The history mode obviously looks better than the hash mode, but is there a problem with the history mode? This mode requires back-end configuration support, because the application is a single-page client application. If the back-end is not configured correctly, it will return 404 when the user directly accesses it in the browser, which is ugly! Therefore, it is necessary to add a candidate resource covering all situations on the server side: if the URL does not match any static resource, it should return the same index.html page, which is the page on which the app depends.

For details, please take a look at this article: Different History Modes | Vue Router

Routing principle:

1) hash routing:

        To know when the path will change, you can monitor the path change through window.onhashchange provided by BOM, and location.hash can switch the path and obtain the hash value;

2) History route:

        Using the new features of H5, the window.onpopstate provided by BOM monitors the change of the path, the changed path can be updated, and the path is switched through history.pushState;

route interception

        What is route interception? To give a very common scenario, when you open a website, when you want to browse the website, when you click to read, it will suddenly jump to a login interface, if you have not selected login to continue to click to read other content When you log in, a login interface pops up again. When you log in, it will not appear again; when you jump to read, you are suddenly blocked by logging in; then when you generally enter certain pages, what means do you use? To check whether you have permission to continue reading. For example, you can check whether there is a token when logging in. If there is, you can continue reading without intercepting it. If not, intercept it and jump to the login interface to log in to obtain the token. Let’s look at a common How to write:

...
<script>
export default {
    mounted () {
        // 检查是否有token
        if (!localStorage.getItem('token') {
            this.$router.push('/login')
        })
    }
}
</script>

         There is obviously no problem with this, but it is not the best. If there are too many pages to check, then it is necessary to check whether there is a token in each component, and everything that needs to be checked needs to be written. In this way, not only a lot of code is repeated, It's hard to write, is there a better way? Yes, it is the routing guard to be mentioned below, it is called more often, but it is not important;

        Routing guards are divided into global guards and component internal guards, which are very easy to understand. If most components need to be checked and logged in before entering, you can use the global one. If it is local or a small number of places will involve checking and logging, you can use the internal guards of the components. way, let's use it as follows:

beforeEach - global pre-routing

        When http://localhost:8080/music is switched to http://localhost:8080/music/kugou, it is necessary to intercept and check the route, and write the global front route in /router/index.js:

<!-- /router/index.js -->
...
const router = new VueRouter({
  mode: 'history',
  routes
})

router.beforeEach((to, from, next) => {
  // 拦截
  if (to.fullPath === '/music/kugou') {
    if (!localStorage.getItem('loginToken')) {
      console.log('请先登录')
    } else {
      next()
    }
  } else {
  // 放行
    next()
  }
})

export default router

Test and run the effect:

         If there are multiple paths, it can be written in the form of an array:

const auth = ['/music', '/order', 'monkey']
  if (auth.includes(to.auth)) {
    console.log('请先登录')
  } else {
    next()
  }

beforeRouteEnter —— component internal guard

        Then if you need this kind of interception inside a component, you can use the internal guard of the component to check the interception before entering this route: beforeRouteEnter

<!-- PlayView.vue -->
...
<script>
    export default {
        beforeRouteEnter (to, from, next) {
            if (!localStorage.getItem('loginToken')) {
              console.log('检查token')
            } else {
              next()
            }
        }
    }
</script>

        Then some beginners have to ask, is mounted not available? The mounted life cycle has been loaded, and the component instance has not been created when the component guard beforeRouterEnter is used. When the route has not been switched, it will judge whether there is a login token. If there is no login token, it will not switch. If there is a loginToken, it will choose next () Release the route;

Of course, if you want to know more about the content of routing guards, please go here——Official document address: Navigation Guard | Vue Router

Routing lazy loading

        Before talking about lazy loading of routes, let’s talk about a common scenario it handles. Have you opened some websites? When you enter the website, the page has been loaded for a long time and has not been displayed; at this time, it may be loading many files, such as after packaging. Some js, css files and some static resources;

         Sometimes it takes a long time for the website to open, and those who are impatient may start to scold. Why does it take so long to open the website? Some mistakenly think that "scientific Internet access" is needed to enter the website, so it will lead to poor user experience. Although the content of the website is rich, the first step for users to enter the website is to be able to enter the website normally!

        When packaging and building an application, the JavaScript package will become very large, affecting page loading. If the components corresponding to different routes can be divided into different code blocks, and the corresponding components are loaded when the route is accessed, it will become more efficient! Combining Vue's asynchronous components and Webpack's code splitting function can be achieved. For details, you can take a look here: Routing lazy loading | Vue Router

         Let's optimize the code written earlier for routing lazy loading:

Original code:

import Vue from 'vue'
import VueRouter from 'vue-router'
// 引入组件
import KuGou from '../views/music/KuGou.vue'
import KuWo from '../views/music/KuWo.vue'
import Play from '../views/PlayView.vue'
import Login from '../views/LoginView.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    redirect: '/music'
  },
  {
    path: '/music',
    component: Music,
    children: [
      {
        path: 'kugou',
        component: KuGou
      },
      {
        path: 'kuwo',
        component: KuWo
      }
    ]
  },
....

Optimization - lazy loading of routes:

import Vue from 'vue'
import VueRouter from 'vue-router'
// 引入组件
// import Music from '../views/MusicView.vue'
// import KuGou from '../views/music/KuGou.vue'
// import KuWo from '../views/music/KuWo.vue'
// import Play from '../views/PlayView.vue'
// import Login from '../views/LoginView.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    redirect: '/music'
  },
  {
    path: '/music',
    // component: Music,
    component: () => import('../views/MusicView.vue'),
    children: [
      {
        path: 'kugou',
        // component: KuGou
        component: () => import('../views/music/KuGou.vue')
      },
      {
        path: 'kuwo',
        // component: KuWo
        component: () => import('../views/music/KuWo.vue')
      }
    ]
  },
....

Components are grouped into chunks 

ps:

  {
    path: '/music',
    // component: Music,
    component: () => import('../views/MusicView.vue'),
...


// 按组分块
{
    path: '/music',
    // component: Music,
    // component: () => import('../views/MusicView.vue'),
    component: () => import(/* webpackChunkName : "group-foo" */ '../views/MusicView.vue')

        Then the content of this article ends here, and the content related to routing will also come to an end in this article. Review the previous content related to routing: first-level routing configuration, declarative navigation, routing redirection, nested routing, programmatic Navigation, dynamic routing, command routing, routing interception and routing lazy loading; attach the first two content links: Finally, thank you for your support!

Guess you like

Origin blog.csdn.net/weixin_52203618/article/details/128788617