路由样式

@Style
思维导图 Xmind
引言 Introduction
. 除了可以自定义样式外,还可以使用 Vue 提供的内置样式类
. 区分匹配当前路由样式 active 和严格匹配当前路由样式 exactActive
. 嵌套路由下,路由链上的会匹配应用当前路由样式 active - 无论嵌套路径多么深,只要链接的目标路径是当前路径的一部分,就会添加
. 而末端子路由应用严格匹配当前路由样式 exactActive - 仅当 to 属性精确匹配当前激活的路由时才会应用;重定向路由不在考虑之内
. 单级路由下,当前路由会同时叠加两种样式类
[] 匹配 active 和严格匹配 exactActive
路由a:重定向到路由b,最后匹配的是路由b,路由a无法激活匹配路由和严格匹配路由
路由b:最后匹配的也是路由b,可以激活匹配路由和严格匹配路由
专有方案 Specific
1. 默认类 Default
. 默认情况下,Vue会为 <RouterLink> 匹配当前路由的链接 自动添加两个空白 的CSS样式类:router-link-active 和 router-link-exact-active,以高亮当前路由
. 通过覆盖/修改其样式可以定制路由样式
.router-link-active {
  color: #f40;
}
    
.router-link-exact-active {
  border-bottom: 1px solid #f40;
}
2. 路由属性类 RouterOptions
. 配置路由时指定属性选项:linkActiveClass、linkExactActiveClass
. 会覆盖上述默认的路由样式类
. 两个样式类默认为空,通过定制实现个性化开发
. 使用不同的样式类;样式内容可以一致
const router = createRouter({
  // ...
  linkActiveClass : "nav-color",
  linkExactActiveClass : "exact-nav-color",
})
. 或使用 options 属性更加明确的指定
router.options = {
  linkActiveClass: "nav-color",
  linkExactActiveClass: "exact-nav-color",
};
. 或
router.options.linkActiveClass = "nav-color"
router.options.linkExactActiveClass = "exact-nav-color"
3. 标签属性类 RouterLinkProps
. <RouterLink> 标签有2个样式属性 :activeClass、exactActiveClass
. 需要为每个 <RouterLink> 都指定该属性
. 指定后,会覆盖默认的两个路由样式类
. 支持小驼峰和连字符两种格式
. 使用不同的样式类;样式内容可以一致
<RouterLink activeClass="btm" exactActiveClass="color" to="/home">home</RouterLink>
<RouterLink active-class="btm" exact-active-class="color" to="/mine">mine</RouterLink>
.btm {
  color: #f40;
}
    
.color {
  border-bottom: 1px solid #f40;
}
通用方案 General
. 以上是 针对 使用了 <RouterLink> 的声明式导航
. 如果是编程式导航,按照元素的普通样式和激活样式区分设计即可;请参照 标签页 设计
. 可以使用专有方案,如默认样式类、标签属性类和路由属性类实现;也可以使用通用方案实现
. 可以分别设计路由样式;也可以先设置全局路由样式,再单独指定某个或某些路由样式,覆盖全局路由样式
Drill
[] 路由样式设计
. 本例采用路由属性类,通过全局、单独定制的方式实现
1. 配置路由时,指定路由样式类
const router = createRouter({
  history: createWebHistory(),
  routes:[
    //...
  ],
  linkActiveClass: "nav-color",
  linkExactActiveClass: "exact-nav-color",
});
2. 在主样式文件 app.css 中设置全局路由样式;这里保持一致
.nav-color {
  color: var(--main-color);
}

.exact-nav-color {
  color: var(--main-color);
}
3. 主路由/导航 AppNav.vue - 封装为组件
3.1 组件数据 <script>
const nav = ref([
  { id: 0, title: '首页', path: '/', icon: 'icon-home1' },
  { id: 1, title: '菜单', path: '/menu', icon: 'icon-coffee-cup' },
  { id: 2, title: '电商', path: '/mall', icon: 'icon-Bag-' },
  { id: 3, title: '会员卡', path: '/membership', icon: 'icon-membership_code' },
  { id: 4, title: '我的', path: '/mine', icon: 'icon-rudolfdeer' }
])
3.1 组件模板 <template> - 配合字体图标实现
<div class="app-nav">
  <RouterLink class="nav-item" v-for="(item, ind) in nav" :to="item.path" :key="item.id" replace>
    <span class="iconfont" :class="item.icon"></span>
    <div>{{ item.title }}</div>
  </RouterLink>
</div>
3.1 组件样式 <style> - 自动应用全局路由样式;其它样式略
主路由/导航 AppNav.vue 全局样式应用效果
4. 菜单视图 MenuView.vue
4.1 配置2级路由/标签页内容子路由 - 重定向到商品列表页;后期封装为组件
{
  path: "/menu",
  name: "menu",
  redirect: "/menu/goods",
  component: () => import("@/views/MenuView.vue"),
  meta: { showNav: true, title: "菜单" },
  children: [
    {
      path: "goods",
      name: "goods",
      component: () => import("@/components/Goods.vue"),
      meta: { title: "菜单-商品列表" },
    },
    {
      path: "vip",
      name: "vip",
      component: () => import("@/components/Vip.vue"),
      meta: { title: "菜单-会员卡" },
    },
    {
      path: "rank",
      name: "rank",
      component: () => import("@/components/Rank.vue"),
      meta: { title: "菜单-年度封神榜" },
    },
    {
      path: "favorite",
      name: "favorite",
      component: () => import("@/components/Favorite.vue"),
      meta: { title: "菜单-我的常点" },
    },
  ],
}
4.2 视图数据 <script> - 用于渲染视图模板
const tabs = [
  { ind: 0, title: '经典菜单', path: '/menu/goods', keyword: 'classic' },
  { ind: 1, title: '会员卡', path: '/menu/vip', keyword: 'member' },
  { ind: 2, title: '年度封神榜', path: '/menu/rank', keyword: 'rank' },
  { ind: 3, title: '我的常点', path: '/menu/favorite', keyword: 'favor' },
]
4.3 视图模板 <template> - 需要指定子路由出口 - 路由视图 <RouterView />
<div class="links">
  <RouterLink class="link" v-for="(item, ind) in tabs" :key="item.id" :to="item.path">
    {{ item.title }}
  </RouterLink>
</div>
<div class="sub-view">
  <RouterView />
</div>
4.4 视图样式 <style> - 重新制定样式,覆盖全局路由样式;采用父相子绝;其它辅助类可以自由设计
.link {
  position: relative;
}

.exact-nav-color::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 0;
  transform: translateX(-50%);
  width: 60%;
  height: 4px;
  background-color: var(--main-color);
}
菜单视图 MenuView.vue 子路由样式应用效果
5. 菜单视图其它内容请自行设计并完善
Summary

. <RouterLink> 路由样式设置

默认样式类: .router-link-active .router-link-exact-active
路由属性类: linkActiveClass、linkExactActiveClass
标签属性类: activeClass、exactActiveClass

. 全局应用路由样式和单独设置路由样式

. 标签属性类适合单独定制

. 路由属性类适合全局定制,也可以在相应的组件中,通过覆盖的方式单独定制

Homework
[] 请使用其它方案设计并实现路由样式
[] 封装导航组件,可分别应用于主视图和菜单视图
[] 不同实现的优先级