美文网首页Vue
Vue2路由 VueRouter

Vue2路由 VueRouter

作者: h2coder | 来源:发表于2023-08-12 00:09 被阅读0次

Vue路由,也就是VueRouter,Vue2和Vue3有版本之分,本文以Vue2为例

  • Vue2,使用3.x版本
  • Vue3,使用4.x版本

添加依赖

npm install vue-router@3.6.5

基础使用

  • 一般会将路由的配置,单独抽到router目录下的index.js文件,统一管理路由路径
  • 下面,以3个路由页面为例,通过点击不同的a标签,进行页面切换,分别是:
    • Find.vue:发现页面
    • Friend.vue,我的好友页面
    • My.vue,我的页面

创建VueRouter实例,并配置地址和组件的映射关系

  • router\index.js
import Vue from 'vue'

// 引入VueRouter
import VueRouter from 'vue-router'

// 路由页面组件
import Find from "../views/Find.vue";
import My from "../views/My.vue";
import Friend from "../views/Friend.vue";

// 安装注册
Vue.use(VueRouter);

// 创建路由实例,传入配置对象,配置url和组件的映射关系
const router = new VueRouter({
    routes: [
        // 发现音乐
        {
            // #号后面的url地址
            path: '/find',
            // url对应的组件
            // 注意:属性名是component,不是components,是不带s的
            component: Find
        },
        // 我的音乐
        {
            path: '/my',
            component: My
        },
        // 朋友
        {
            path: '/friend',
            component: Friend
        },
    ]
});

// 默认导出,导出路由实例
export default router;

注册路由给Vue实例

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

// 导入路由实例
import router from './router/index.js'

Vue.config.productionTip = false

// 注入路由对象给Vue实例
new Vue({
  render: h => h(App),
  router
}).$mount('#app')

首页(App.vue)

  • 提供3个a标签,用于跳转页面
  • 路由视图标签,也就是不同路由界面组件的内容,会渲染到<router-view></router-view>
<template>
  <div>
    <div class="footer_wrap">
      <a href="#/find">发现音乐</a>
      <a href="#/my">我的音乐</a>
      <a href="#/friend">朋友</a>
    </div>
    <div class="top">
      <!-- 路由出口 → 匹配的组件所展示的位置 -->
      <router-view></router-view>
    </div>
  </div>
</template>

<script>
export default {};
</script>

<style>
body {
  margin: 0;
  padding: 0;
}
.footer_wrap {
  position: relative;
  left: 0;
  top: 0;
  display: flex;
  width: 100%;
  text-align: center;
  background-color: #333;
  color: #ccc;
}
.footer_wrap a {
  flex: 1;
  text-decoration: none;
  padding: 20px 0;
  line-height: 20px;
  background-color: #333;
  color: #ccc;
  border: 1px solid black;
}
.footer_wrap a:hover {
  background-color: #555;
}
</style>

准备3个路由页面

  • Find.vue,发现页面
<template>
  <div>
    <p>发现音乐</p>
    <p>发现音乐</p>
    <p>发现音乐</p>
    <p>发现音乐</p>
  </div>
</template>

<script>
export default {
  name: 'FindMusic'
}
</script>

<style>
</style>
  • Friend.vue,我的好友页面
<template>
  <div>
    <p>我的朋友</p>
    <p>我的朋友</p>
    <p>我的朋友</p>
    <p>我的朋友</p>
  </div>
</template>

<script>
export default {
  name: 'MyFriend'
}
</script>

<style>
</style>
  • My.vue,我的页面
<template>
  <div>
    <p>我的音乐</p>
    <p>我的音乐</p>
    <p>我的音乐</p>
    <p>我的音乐</p>
  </div>
</template>

<script>
export default {
  name: 'MyMusic'
}
</script>

<style>
</style>

导航链接高亮

  • VueRouter在切换路由页面时,会给当前选中的导航标签,选中方式给是给a标签设置类名,所以我们只需要给这些类名添加样式,就能实现选中效果

  • VueRouter会在路由跳转时,进行路径匹配,分为精准匹配和模糊匹配

  • 精确匹配:地址和路由的URL完全一致,精确匹配,如:http://localhost:8080/#/my

  • 模糊匹配:地址在路由URL的基础上,再多加几个层级,如:http://localhost:8080/#/my/123http://localhost:8080/#/my/123/abc

  • 精确匹配有2个样式,而模糊匹配只有一个,多个类名目的是为了实现嵌套路由的高亮(嵌套路由的2个Tab都选中)

    • 精确匹配:.router-link-exact-active.router-link-active
    • 模糊匹配:.router-link-active
  • 如果使用a标签,我们需要将href属性写成类似#/my的格式,但我们注册给VueRouter的路径只有/my,而前面的#/只是使用hash路由,这样重复书写太繁琐,而且不方便切换为history路由,所以VueRouter还提供了router-link标签给我们

  • router-link标签,在H5中,其实就是a标签,该标签使用to属性指定路由路径,也就是相当于a标签的href属性

<template>
  <div>
    <div class="footer_wrap">
      <!-- 路由链接,是VueRouter封装的组件,本质就是一个a标签,通过to属性,来实现a标签的href属性 -->
      <!-- 注意,to属性,不需要加#号 -->
      <!-- 如果用a标签,href属性,还要加上#/,太麻烦 -->
      <!-- router-link组件,还可以实现跨平台,底层能映射为小程序和原生app对应的跳转功能 -->
      <router-link to="/find">发现音乐</router-link>
      <router-link to="/my">我的音乐</router-link>
      <router-link to="/friend">朋友</router-link>
    </div>
    <div class="top">
      <!-- 路由出口 → 匹配的组件所展示的位置 -->
      <router-view></router-view>
    </div>
  </div>
</template>

<script>
export default {};
</script>

<style>
// ...

/* 
  exact:是确切的意思

  精确匹配:会有2个类名,.router-link-exact-active、.router-link-active
  模糊匹配:只有一个类名,.router-link-active
  没匹配上,没有上面2个类名

  疑问:为什么要有区别?
    - 方便后面做路由嵌套,#/my/cart => 第一层是my,第二层是cart
  
  模糊匹配
    - #/my/a #/my/b #/my/c  =>  有效
    - #/my123 #/my456  =>  无效
*/
.footer_wrap .router-link-exact-active {
  background-color: blue;
  color: white;
}
</style>

自定义导航高亮类名

  • 上面说到VueRouter会给命中的路由的router-link标签或a标签,设置类名,来实现高亮。这2个类名都挺长的,其实这2个类名是可以自定义的

在路由实例上配置类名

import Find from '../views/Find'
import My from '../views/My'
import Friend from '../views/Friend'

import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter) // VueRouter插件初始化

// 创建了一个路由对象
const router = new VueRouter({
  // routes 路由规则们
  // route  一条路由规则 { path: 路径, component: 组件 }
  routes: [
    { path: '/find', component: Find },
    { path: '/my', component: My },
    { path: '/friend', component: Friend },
  ],
  // 自定义精确匹配的类名
  linkExactActiveClass: "exact-active-link",
  // 自定义模糊匹配的类名
  linkActiveClass: "active-link",
})

export default router

设置类名对应的样式

//...

<style>

/* 精确匹配 */
.exact-active-link {
  background-color: red;
  color: white;
}
</style>

导航链接传参-查询参数传参

  • 查询参数传参,和Ajax请求的查询参数类型,都是URL地址?号后面,添加参数1名=值1&参数名2=值2,这种方式适合参数比较多时,看参数名就能知道参数值对应哪个参数
  • 准备2个页面,分别是:
    • 首页,Home.vue
    • 搜索结果页面,SearchResult.vue

路由配置

import Home from '../views/Home'
import Search from '../views/Search'
import Vue from 'vue'
import VueRouter from 'vue-router'

// VueRouter插件初始化
Vue.use(VueRouter)

// 创建了一个路由对象
const router = new VueRouter({
  routes: [
    { path: '/home', component: Home },
    { path: '/search', component: Search }
  ]
})

export default router

首页

  • 通过router-link标签的to属性,设置路径和参数
<template>
  <div class="home">
    <div class="logo-box"></div>
    <div class="search-box">
      <input type="text" />
      <button>搜索一下</button>
    </div>
    <div class="hot-link">
      热门搜索:
      <!-- 查询参数传参 (比较适合传多个参数) -->
      <!-- 路由(导航)链接,参数放在to属性中,通过URL传参的方式,也就是?号后面,参数名=参数值&参数名2=参数值2 -->
      <router-link to="/search?words=程序员">程序员</router-link>
    </div>
  </div>
</template>

<script>
export default {
  name: "HomePage",
};
</script>

<style>
// ...
</style>

搜索结果页面

  • 通过Vue实例的$route路由对象,读取query属性,就能前面页面传递过来的查询参数
<template>
  <div class="search">
    <p>搜索关键字: {{ $route.query.words }}</p>
    <p>搜索结果:</p>
    <ul>
      <li>.............</li>
      <li>.............</li>
      <li>.............</li>
      <li>.............</li>
    </ul>
  </div>
</template>

<script>
export default {
  name: "MyFriend",
  created() {
    console.log(this.$route);
    // 获取首页传过来的参数,格式:$route.query.参数名
    console.log(this.$route.query.words);
  },
};
</script>

<style>
// ...
</style>

导航链接传参-动态路由传参

  • 处理使用查询参数来传递页面参数外,还可以使用URL路径传参的方式,这种传参方式在Ajax请求中也是有的,在VueRouter中,被成为动态路由
  • 参数名,并不是在导航标签上配置,而是在路由配置中
  • 这种方式适合参数只有少量的时候,例如1个。当然也可以多个,但没有参数名,并不直观,例如:
    • 参数
    • 搜素关键字:新闻
    • 页码:1
    • 一页15条
    • 结果:/search/新闻/1/15

配置路由

import Home from '../views/Home'
import Search from '../views/Search'
import Vue from 'vue'
import VueRouter from 'vue-router'

// VueRouter插件初始化
Vue.use(VueRouter)

// 创建了一个路由对象
const router = new VueRouter({
  routes: [
    {
      path: '/home',
      component: Home
    },
    {
      // 动态路由传参,格式:/路径/:参数名
      // 注意:如果没有配置,或配置出错,那就页面跳转的路由匹配就不正确,会白屏
      path: '/search/:words',
      component: Search
    }
  ]
})

export default router

首页

  • 通过router-link标签的to属性,配置路径,注意参数是直接通过路径,没有查询参数
<template>
  <div class="home">
    <div class="logo-box"></div>
    <div class="search-box">
      <input type="text" />
      <button>搜索一下</button>
    </div>
    <div class="hot-link">
      热门搜索:
      <!-- 动态路由传参 (优雅简洁,传单个参数比较方便) -->
      <!-- 导航链接,动态路由传参,格式:/路径/参数 -->
      <router-link to="/search/程序员">程序员</router-link>
    </div>
  </div>
</template>

<script>
export default {
  name: "HomePage",
};
</script>

<style>
// ...
</style>

搜索结果页

  • 通过Vue实例的$route属性,获取到路由对象,通过它的params属性,就可以访问到前面页面传递的参数
<template>
  <div class="search">
    <!-- 获取动态路由传参 -->
    <p>搜索关键字: {{ $route.params.words }}</p>
    <p>搜索结果:</p>
    <ul>
      <li>.............</li>
      <li>.............</li>
      <li>.............</li>
      <li>.............</li>
    </ul>
  </div>
</template>

<script>
export default {
  name: "SearchResult",
  created() {
    console.log(this.$route);
    console.log(this.$route.params.words);
  },
};
</script>

<style>
// ...
</style>

动态路由-可选符

  • 上面说到,参数可以通过查询参数或路径传参(动态路由)的方式来传递,其中动态路由可以配置参数为可选,只需要在路由配置中的参数后面加一个?号可选符即可

路由配置

import Home from '../views/Home'
import Search from '../views/Search'
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter) // VueRouter插件初始化

// 创建了一个路由对象
const router = new VueRouter({
  routes: [
    { path: '/home', component: Home },

    // /search/:words ,表示必须要传参数
    // 如果不传参,就会匹配不上,就不会显示 Search 组件
    // { path: '/search/:words', component: Search },

    // 如果不传参数,也希望匹配,那就加个可选符?号
    { path: '/search/:words?', component: Search }
  ]
})

export default router

首页

<template>
  <div class="home">
    <div class="logo-box"></div>
    <div class="search-box">
      <input type="text" />
      <button>搜索一下</button>
    </div>
    <div class="hot-link">
      热门搜索:
      <router-link to="/search">不传参</router-link>
      <router-link to="/search/程序员">程序员</router-link>
    </div>
  </div>
</template>

<script>
export default {
  name: "HomePage",
};
</script>

<style>
// ...
</style>

路由重定向

  • 前面的路由配置,都是路径在/home/search时,才能路由正确,而还有一个页面根路径/也是经常用的,但目前使用根路径跳转会一片空白,因为没有一个规则和它匹配。
  • VueRouter还可以配置路由重定向,当路由到根路径时,重定向到/home首页
  • 通过redirect属性,指定/根页面时,则路由到/home页面
import Home from '../views/Home'
import Search from '../views/Search'
import Vue from 'vue'
import VueRouter from 'vue-router'

// VueRouter插件初始化
Vue.use(VueRouter)

// 创建了一个路由对象
const router = new VueRouter({
  routes: [
    // 配置路由重定向,如果访问的是根路径,则切换到 /home
    { path: '/', redirect: '/home' },
    { path: '/home', component: Home },
    { path: '/search/:words?', component: Search }
  ]
})

export default router

路由404页面配置

  • 除了路由重定向,VueRouter还能支持路由不到匹配的路径时,还能跳转到404页面,这在网站开发中是很常见的,如果将404页面样式美化得很好看,也能提升用户体验
  • 通过*号通配符,VueRouter会在匹配完所有路径都没有匹配到时,跳转到配置了*路径的组件页面
import Home from '../views/Home'
import Search from '../views/Search'
import NotFound from '../views/NotFound.vue'
import Vue from 'vue'
import VueRouter from 'vue-router'

// VueRouter插件初始化
Vue.use(VueRouter)

// 创建了一个路由对象
const router = new VueRouter({
  routes: [
    { path: '/', redirect: '/home' },
    { path: '/home', component: Home },
    { path: '/search/:words?', component: Search },
    // 路由404,*表示通配符,匹配任意路径,当路径不匹配时,就命中这个规则,跳转到一个404提示页面
    { path: '*', component: NotFound },
  ]
})

export default router

路由模式

  • Vue支持2种路由模式,分别是hashhistory
  • Vue是单页面应用,多个页面是通过在同一个页面种,使用JS进行切换,而传统的多页面应用,是通过跳转新的页面来跳转,2种应用各有优缺点,它们的区别如下:

单页面、多页面应用对比

开发分类 实现方式 页面性能 开发效率 用户体验 学习成本 首屏加载 SEO
单页 一个HTML页面 按需更新,性能高 非常好
多页 多个HTML页面 整页更新,性能差 中等 一般 中等
  • 根据它们的优缺点,可以分类出,不同场景使用哪种方式
  • 单页面应用:系统类网站、内部网站、文档类网站、移动端站点
  • 多页面应用:公司官网、电商类网站

实现细节

  • hash模式,使用的是H5的新特性,当路径中存在的是#/时,浏览器不会跳转,而是发生hashchange事件,Vue就是监听这个事件来监听路径变化,再进行路径匹配,切换到对应的组件页面。缺点是URL比较丑,莫名其妙出现了个#/在前面
  • history模式,浏览器一开始就支持的模式,当路径变化时,浏览器会发出GET请求服务器,访问这个路径的页面,但单页面应用只有一个HTML页面,所以需要服务端进行配置支持,否则不配置的话,会产生404(其实就是让服务端将404时,返回的页面改为index.html

路由配置

  • 通过mode属性,切换模式是hash还是history
  • 注意:开发阶段,使用webpack,会使用node.js启动一个开发服务器,已经内置了配置,所以没有问题,但是到线上时,使用的是服务端的服务器,就需要进行配置
import Home from '../views/Home'
import Search from '../views/Search'
import NotFound from '../views/NotFound'
import Vue from 'vue'
import VueRouter from 'vue-router'

// VueRouter插件初始化
Vue.use(VueRouter)

// 创建了一个路由对象
const router = new VueRouter({
  /* 
    路由的路径有#,看起来不自然,,能否切成真正路径形式?
      hash路由(默认) 例如: http://localhost:8080/#/home
      history路由(常用) 例如: http://localhost:8080/home (以后上线需要服务器端支持)
  */
  // hash路由,默认值
  // mode: "hash",
  // 好看
  mode: "history",
  routes: [
    { path: '/', redirect: '/home' },
    { path: '/home', component: Home },
    { name: 'search', path: '/search/:words?', component: Search },
    { path: '*', component: NotFound }
  ]
})

export default router

编程式导航-两种跳转方式

  • 上面提到的导航链接跳转,都是声明式导航,也就是使用标签来跳转,也就是使用router-link标签。而编程式导航,就是通过JS调用VueRouter的API来进行跳转
  • 编程式导航,还支持命名导航,也就是路由映射时,给映射关系配置一个名称,跳转时使用名称来代替具体路径,这样更好管理路由

路由配置

  • 命名路由,通过给映射关系,配置一个name属性,也就是给路由设置了一个名称,后面页面跳转使用这个名称,就能跳转,而不需要在页面跳转时写路径
import Home from '../views/Home'
import Search from '../views/Search'
import NotFound from '../views/NotFound'
import Vue from 'vue'
import VueRouter from 'vue-router'

// VueRouter插件初始化
Vue.use(VueRouter)

// 创建了一个路由对象
const router = new VueRouter({
  // 注意:一旦采用了 history 模式,地址栏就没有 #,需要后台配置访问规则
  mode: 'history',
  routes: [
    { path: '/', redirect: '/home' },
    { path: '/home', component: Home },
    
    // 命名路由,通过name属性指定路由的名称,后续则通过指定这个名称去跳转
    { name: 'search', path: '/search/:words?', component: Search },
    
    { path: '*', component: NotFound }
  ]
})

export default router

跳转方式

<template>
  <div class="home">
    <div class="logo-box"></div>
    <div class="search-box">
      <input @keyup.enter="goSearch" type="text" />
      <button @click="goSearch">搜索一下</button>
    </div>
    <div class="hot-link">
      热门搜索:
      <router-link to="/search/程序员">程序员</router-link>
    </div>
  </div>
</template>

<script>
export default {
  name: "HomePage",
  methods: {
    goSearch() {
      // ------- 编程式导航,路径跳转 -------
      // 适合路径比较短,直接在这里写上路径

      // 写法一,直接传入路径
      this.$router.push("/search");

      // 写法二,通过配置对象的path属性指定路径
      this.$router.push({
        path: "/search",
      });

      // ------- 编程式导航,命名路由跳转 -------
      // 适合路径比较长的,将路径放到路由配置文件中,在这里使用名称去找到对应的路径

      // 通过配置对象的name属性,配置命名路由的名称
      this.$router.push({
        name: "search",
      });
    },
  },
};
</script>

<style>
// ...
</style>

编程式导航-跳转传参

上面的编程式导航,没有传参,接下来就来看看怎么传参

<template>
  <div class="home">
    <div class="logo-box"></div>
    <div class="search-box">
      <input @keyup.enter="goSearch" v-model="inpValue" type="text" />
      <button @click="goSearch">搜索一下</button>
    </div>
    <div class="hot-link">
      热门搜索:
      <router-link to="/search/程序员">程序员</router-link>
    </div>
  </div>
</template>

<script>
export default {
  name: "HomePage",
  data() {
    return {
      inpValue: "",
    };
  },
  methods: {
    goSearch() {
      // 方式一:路径路由,使用查询参数,传递参数
      this.$router.push(`/search?words=${this.inpValue}`);

      // 方式二,路径路由,使用配置对象
      this.$router.push({
      path: "/search",
        query: {
          words: this.inpValue,
        },
      });

      // 写法三,动态路由-直接拼路径的方式
      this.$router.push(`/search/${this.inpValue}`);

      // 写法四,动态路由-配置对象的方式
      this.$router.push({
        path: `/search/${this.inpValue}`,
      });

      // 写法五,命名路由的方式
      this.$router.push({
        name: "search",
        params: {
          words: this.inpValue,
        },
      });
    },
  },
};
</script>

<style>
// ...
</style>

keep-alive

一级路由(App.vue)

<template>
  <div class="h5-wrapper">
    <!--
      Vue组件一般什么时候会被销毁掉?
        - vue实例.$destroy(),手动销毁组件
        - v-if,是将DOM元素直接从DOM树中移除,所以组件也被销毁了
        - 路由切换,例如Tab切换,离开了组件,就会被销毁
     -->

    <!-- keep-alive,缓存组件,保证页面跳转到详情页后返回,一级路由的所有组件都不会被销毁 -->
    <!-- 一级路由,包括 LayoutPage 和 ArticleDetailPage,但我们指向Layout被会缓存,详情页不要被缓存 -->

    <!-- 注意:默认Vue组件的名称就是文件名,但如果可以在组件身上指定 name 属性,就是我们手动指定的 name 属性,而不是文件名 -->

    <!-- (常用)include属性,则指定要被缓存的组件,就是要缓存谁,属性值是要被缓存的组件名数组,是组件名,而不是文件名!!! -->
    <!-- exclude属性,配置不被缓存的组件,就是不要缓存谁,和include属性是相反的,这2个属性一般不会同时用,只会选其一 -->
    <!-- max属性,缓存组件的实例数量 -->
    <!-- 
      注意:
        一般我们使用 exclude 属性,它是默认所有都不缓存,只缓存我们指定的组件,节省内存
        而 include 属性,是所有组件都缓存,然后不缓存我们指定的组件,会导致缓存的组件太多,导致性能问题
     -->
    <keep-alive :include="keepAliveArr">
      <!-- 一级路由-出口 -->
      <router-view></router-view>
    </keep-alive>
  </div>
</template>

<script>
export default {
  name: "h5-wrapper",
  data() {
    return {
      // 缓存的组件的组件名数组
      keepAliveArr: ["LayoutPage"],
    };
  },
};
</script>

<style>
body {
  margin: 0;
  padding: 0;
}
</style>
<style lang="less" scoped>
.h5-wrapper {
  .content {
    margin-bottom: 51px;
  }
  .tabbar {
    position: fixed;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 50px;
    line-height: 50px;
    text-align: center;
    display: flex;
    background: #fff;
    border-top: 1px solid #e4e4e4;
    a {
      flex: 1;
      text-decoration: none;
      font-size: 14px;
      color: #333;
      -webkit-tap-highlight-color: transparent;
      &.router-link-active {
        color: #fa0;
      }
    }
  }
}
</style>

二级路由(Layout.vue)

<template>
  <!-- 一级路由页面-首页 -->
  <div class="h5-wrapper">
    <div class="content">
      <!-- 组件缓存,缓存所有Tab页面 -->
      <keep-alive>
        <!-- 二级路由-出口, -->
        <router-view></router-view>
      </keep-alive>
    </div>
    <!-- 底部TabBar -->
    <nav class="tabbar">
      <router-link to="/article">面经</router-link>
      <router-link to="/collect">收藏</router-link>
      <router-link to="/like">喜欢</router-link>
      <router-link to="/user">我的</router-link>
    </nav>
  </div>
</template>

<script>
export default {
  // 组件名(如果没有配置 name,才会找文件名作为组件名)
  name: "LayoutPage",
  // 注意:一般组件被缓存了,反复进入该组件,组件的created、mounted、destroyed,就只有第一次的时候被执行
  // 默认组件是不会被缓存的,每次进出页面,都会重新加载组件,声明周期回调函数就会被执行,但缓存后就不会了
  // 被缓存后,会多2个生命周期函数回调,分别是 activated 和 deactivated
  created() {
    console.log("created 组件被加载了...");
  },
  mounted() {
    console.log("mounted 组件的DOM渲染完毕了...");
  },
  destroyed() {
    console.log("destroyed 组件被销毁了...");
  },
  activated() {
    console.log("activated 组件被激活了,也就是页面可见了...");
  },
  deactivated() {
    console.log("deactivated 组件失活,也就是页面不可见了...");
  },
};
</script>

<style>
body {
  margin: 0;
  padding: 0;
}
</style>
<style lang="less" scoped>
.h5-wrapper {
  .content {
    margin-bottom: 51px;
  }
  .tabbar {
    position: fixed;
    left: 0;
    bottom: 0;
    width: 100%;
    height: 50px;
    line-height: 50px;
    text-align: center;
    display: flex;
    background: #fff;
    border-top: 1px solid #e4e4e4;
    a {
      flex: 1;
      text-decoration: none;
      font-size: 14px;
      color: #333;
      -webkit-tap-highlight-color: transparent;
    }
    a.router-link-active {
      color: orange;
    }
  }
}
</style>

相关文章

网友评论

    本文标题:Vue2路由 VueRouter

    本文链接:https://www.haomeiwen.com/subject/grntmdtx.html