现在就来讲解一下在vue中非常重要的一个技术, 也就是路由; 只要是使用vue书写的项目必定会涉及到路由的问题.
从生活中出发, 我们说路由首先会想到路由器.
生活中的路由器可以让多台设备同时上网, 也就是说每一个接口都会对应着一个设备; 一个接口对应一个接口.
路由就是一组key-value的对应关系, 多个路由(多组对应关系route)就需要被路由器所管理router.
生活中的路由是为了能够上完, 那么代码中路由就是为了spa单页面应用的导航区和展示区的来来回回切换.
在以前的项目都是多页面的应用, 多个页面互相跳转, 不好的就是有抖动; 单页面就是不断的匹配路由, 然后切换显示组件.
router会一直监听的路由变化, 如果路由发送变化就会找到与当前路由匹配的组件显示到页面, 这就是路由的整个流程.
想要将router挂载到vue实例上面, 我们就得借助到vue-router这个插件库了(npm i vue-router或yarn add vue-router).
但是现在推出了vue-router 4 的版本, 它只服务于vue3. 3的版本是服务于vue2的, 所以就得指定版本下载npm i vue-router@3.
- // 第一步, 导入Vue, 后面将vue-router注册插件
- import Vue from 'vue'
-
- // 第二步, 导入VueRouter构造器
- import VueRouter from 'vue-router'
-
- // 第三步, 将路由插件库注册
- Vue.use(VueRouter)
-
- // 第四步, 使用VueRouter创建实例对象
- const router = new VueRouter({
- // 第五步, 创建路由规则
- routes: [
- {
- path: '/home',
- component: () => import('@/views/HomeView')
- },
- {
- path: '/about',
- component: () => import('@/views/AboutView')
- }
- ]
- })
-
- // 第六步, 将路由实例导出
- export default router
- import Vue from 'vue'
- import App from './App.vue'
- import store from './store'
-
- // 第七步, 将路由实例导入
- import router from './router/index.js'
-
- Vue.config.productionTip = false
-
- new Vue({
- // 第八步, 将路由实例挂载到Vue的实例上面
- router,
- store,
- render: h => h(App)
- }).$mount('#app')
- <template>
- <div id="app">
- <nav>
- <!-- 第十步, 设置链接 -->
- <router-link to="/home">home</router-link> |
- <router-link to="/about">about</router-link>
- </nav>
- <!-- 第九步, 设置路由出口 -->
- <router-view></router-view>
- </div>
- </template>
-
- <style lang="less">
- #app {
- font-family: Avenir, Helvetica, Arial, sans-serif;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
- text-align: center;
- color: #2c3e50;
- }
-
- nav {
- padding: 30px;
-
- a {
- font-weight: bold;
- color: #2c3e50;
-
- &.router-link-exact-active {
- color: #42b983;
- }
- }
- }
- </style>
注意点:
那我们再思考一个问题, 现在路由匹配规则匹配的组件是about组件; 那home组件去哪了?
我们home组件被效果了, 上代码:
- <template>
- <h3>home</h3>
- </template>
-
- <script>
- export default {
- name: 'HomeCom',
-
- beforeDestroy () {
- console.log('home组件即将被销毁')
- },
-
- mounted () {
- console.log('home组件挂载完毕')
- }
- }
- </script>
-
-
-
-
- <template>
- <h3>
- about
- </h3>
- </template>
-
- <script>
- export default {
- name: 'AboutCom',
-
- beforeDestroy () {
- console.log('about组件即将被销毁')
- },
-
- mounted () {
- console.log('about组件挂载完毕')
- }
- }
- </script>
这里我们再抛出一个面试题:
router和route区别在哪?
嵌套路由我们也可以称之为多级路由, 我们需要在一级路由中设置一个属性"children", 它得是一个数组. 因为一个一级路由可以有n多个二级路由, 以数组包对象的形式.
- // 第一步, 导入Vue, 后面将vue-router注册插件
- import Vue from 'vue'
-
- // 第二步, 导入VueRouter构造器
- import VueRouter from 'vue-router'
-
- // 第三步, 将路由插件库注册
- Vue.use(VueRouter)
-
- // 第四步, 使用VueRouter创建实例对象
- const router = new VueRouter({
- // 第五步, 创建路由规则
- routes: [
- {
- path: '/home',
- component: () => import('@/views/HomeView'),
- // children得是一个数组, 因为一个一级路由可以有n多个二级路由
- children: [
- {
- path: 'secondone',
- component: () => import('@/views/Second_one')
- },
- {
- path: '/secondtwo',
- component: () => import('@/views/Second_two')
- }
- ]
- },
- {
- path: '/about',
- component: () => import('@/views/AboutView')
- }
- ]
- })
-
- // 第六步, 将路由实例导出
- export default router
- <template>
- <div>
- <h3>home</h3>
-
- <!-- 在书写二级路由的路径的时候, 需要加上一级路由的路径 -->
- <router-link to="/home/secondone">第一个子组件</router-link> |
- <router-link to="/home/secondtwo">第二个子组件</router-link>
-
- <!-- 当然二级路由也需要设置路由出口, 我们将这个出口称为二级路由出口 -->
- <router-view></router-view>
- </div>
- </template>
-
- <script>
- export default {
- name: 'HomeCom'
- }
- </script>
-
- <style>
-
- </style>
注意:
query传参的方法是在路径后面以"?"进行拼接, 以键值对的形式显示在地址栏, 比如搜索引擎的搜索.
- <template>
- <div>
- <h3>我是第三个页面</h3>
- <template v-for="item in threeList">
- <router-link :to="`/one/three/threeDetail?id=${item.id}&name=${item.name}`" :key="item.id">第三个页面的第{{ item.id }}个详情页</router-link> 
- </template>
- <router-view></router-view>
- </div>
- </template>
-
- <script>
- export default {
- name: 'ThreeCom',
-
- data () {
- return {
- threeList: [
- { id: 1, name: '大帅' },
- { id: 2, name: '张三' },
- { id: 3, name: '李四' }
- ]
- }
- }
- }
- </script>
-
- <style>
-
- </style>
- <template>
- <div>
- <h3>我是第三个页面</h3>
- <template v-for="item in threeList">
- <router-link :to="{
- path: '/one/three/threeDetail',
- query: {
- id: item.id,
- name: item.name
- }
- }" :key="item.id">我是第三个页面的第{{ item.id }}个详情页面</router-link> 
- </template>
- <router-view></router-view>
- </div>
- </template>
-
- <script>
- export default {
- name: 'ThreeCom',
-
- data () {
- return {
- threeList: [
- { id: 1, name: '大帅' },
- { id: 2, name: '张三' },
- { id: 3, name: '李四' }
- ]
- }
- }
- }
- </script>
-
- <style>
-
- </style>
- <template>
- <div>
- <h3>我是第三个页面</h3>
- <template v-for="item in threeList">
- <router-link :to="{
- path: '/one/three/threeDetail',
- query: {
- id: item.id,
- name: item.name
- }
- }" :key="item.id">我是第三个页面的详情页面</router-link> 
- </template>
- <router-view></router-view>
- </div>
- </template>
-
- <script>
- export default {
- name: 'ThreeCom',
-
- data () {
- return {
- threeList: [
- { id: 1, name: '大帅' },
- { id: 2, name: '张三' },
- { id: 3, name: '李四' }
- ]
- }
- }
- }
- </script>
-
- <style>
-
- </style>
顾名思义就是跟你的路由起一个规则, 想给路由起个名字非常简单, 直接配置一个name属性, 它是一个字符串.
它的作用就是可以简化一些编码. 比如, 如果router-link中to属性的值太多的话, 我们可以直接使用name代替. 来上代码:
- import Vue from 'vue'
-
- import VueRouter from 'vue-router'
-
- Vue.use(VueRouter)
-
- const router = new VueRouter({
- routes: [
- {
- path: '/one',
- name: 'OneCom',
- component: () => import('@/pages/One.vue'),
- children: [
- {
- path: 'three',
- name: 'ThreeCom',
- component: () => import('@/pages/Three.vue'),
- children: [
- {
- path: 'threeDetail',
- name: 'ThreeDetail',
- component: () => import('@/pages/ThreeDetail')
- }
- ]
- },
- {
- path: 'four',
- name: 'FourCom',
- component: () => import('@/pages/Four.vue')
- }
- ]
- },
- {
- path: '/two',
- name: 'TwoCom',
- component: () => import('@/pages/Two.vue')
- }
- ]
- })
-
- export default router
- <template>
- <div>
- <h3>我是第一个页面</h3>
- <router-link to="/one/three">第三个页面</router-link> |
- <router-link :to="{name: 'FourCom'}">第四个页面</router-link>
- <router-view></router-view>
- </div>
- </template>
-
- <script>
- export default {
- name: 'OneCom'
- }
- </script>
-
- <style>
-
- </style>
- <template>
- <div>
- <h3>我是第三个页面</h3>
- <template v-for="item in threeList">
- <router-link :to="{
- name: 'ThreeDetail',
- query: {
- id: item.id,
- name: item.name
- }
- }" :key="item.id">我是第三个页面的第{{ item.id }}个详情页面</router-link> 
- </template>
- <router-view></router-view>
- </div>
- </template>
-
- <script>
- export default {
- name: 'ThreeCom',
-
- data () {
- return {
- threeList: [
- { id: 1, name: '大帅' },
- { id: 2, name: '张三' },
- { id: 3, name: '李四' }
- ]
- }
- }
- }
- </script>
-
- <style>
-
- </style>
- {
- path: 'four',
- name: 'FourCom',
- component: () => import('@/pages/Four.vue'),
- children: [
- {
- // params传参需要对路由匹配规则进行配置一下
- path: 'fourDetail/:id/:name',
- name: 'FourDetail',
- component: () => import('@/pages/FourDetail.vue')
- }
- ]
- }
- <template>
- <div>
- <h3>我是第四个页面</h3>
- <router-link to="/one/four/fourDetail/1/大帅">第四个页面的详情页</router-link>
- <router-view></router-view>
- </div>
- </template>
-
- <script>
- export default {
- name: 'FourCom'
- }
- </script>
-
- <style>
-
- </style>
- <template>
- <div>
- <h3>我是第四个页面</h3>
- <router-link :to="{
- name: 'FourDetail',
- params: {
- id: 1,
- name: '大帅'
- }
- }">第四个页面的详情页</router-link>
- <router-view></router-view>
- </div>
- </template>
-
- <script>
- export default {
- name: 'FourCom'
- }
- </script>
-
- <style>
-
- </style>
注意:
演示一下, 将name改为path:
- <template>
- <div>
- <h3>我是第四个页面</h3>
- <!-- <router-link to="/one/four/fourDetail/1/大帅">第四个页面的详情页</router-link> -->
- <router-link :to="{
- path: 'FourDetail',
- params: {
- id: 1,
- name: '大帅'
- }
- }">第四个页面的详情页</router-link>
- <router-view></router-view>
- </div>
- </template>