先前写过一篇为 material 组件自定义 AngularJS 路由器的文章。最近有一个为 Element UI 组件添加自定义路由器的需求,结合 vue-router
也不难实现。
需求
- 初始地址为
#city
,不会选中区号按钮,面包屑All
;如果导航地址为#city/0755
,则选中0755,面包屑All > 深圳
- 点击区号按钮(021、0755)会相应修改访问地址(#city/021、#city/0755)
- 点击区号按钮,面包屑会显示为
All
> 城市名(广州、深圳) - 点击面包屑
All
跳转到初始地址#city
- 可以通过导航栏或浏览器的前进后退按钮导航
- 同步修改浏览器标题栏为当前选择城市名
一句话,如何实现区号按钮组、导航栏、浏览器导航三者的同步更新?
实现区号按钮组
新建 Breadcrumb.vue
, 这里我们用 el-radio-group
来渲染区号按钮
<el-radio-group v-model="selected" @change="handleChange">
<el-radio-button
v-for="item in cities"
:label="item.code"
:key="item.code"
>
</el-radio-button>
</el-radio-group>
以下是单选按钮组遍历要用到的数据:
const cities = [
{
city: "上海",
code: "021",
degree: 28,
},
{
city: "北京",
code: "010",
degree: 24,
},
{
city: "广州",
code: "020",
degree: 33,
},
{
city: "深圳",
code: "0755",
degree: 32,
},
];
我们为其绑定了 selected
保留,并声明了 handleChange
事件处理方法:
handleChange(value) {
console.log(value)
可以简单测试以下,当切换单选按钮组,会打印不同的区号。
为方便,我们没有将这部分实现放到了 Breadcrum
组件中,并没有单独拆分成一个组件。
实现导航栏
在 Breadcrum
组件中:
<nav>
<el-button class="el-icon-back" @click="back"></el-button>
<el-button class="el-icon-right" @click="forward"></el-button>
<router-link>All</router-link>
<template v-if="selected">
<i class="el-icon-arrow-right"></i>
{{ currentCity }}
</template>
</nav>
我们在这里添加了前进后退按钮和面包屑,下面我们来实现单选按钮组与面包屑的同步。添加以下计算属性:
computed: {
currentCity() {
const found = this.cities.find(item =>item.code === this.selected)
if (found) {
return found.city
}
return 'All'
}
}
测试以下,点击区号按钮,面包屑会显示为 All
> 城市名,我们完成了第二个需求。要实现其他需求,着重看 Vue Router。
配置路由器
根据强两个需求,新建 router\index.js
,配置如下路由对象后,导出自定义路由器:
export default new Router({
routes: [
{
path: "/",
redirect: "/city"
},
{
path: "/city/:code",
name: "Breadcrumb",
component: Breadcrumb
}
]
});
第一个路由默认会跳转到 #city
,第二个路由地址使用了参数 code
,参数为 0755
则会跳转到 #city/0755
。
注意,Vue Router 中路由地址传参方式 :paramName
。
添加路由器
在 App
组件中,引入之前的自定义路由器,将其最为插件添加 Vue 示例中。
import router from "./router";
//...
new Vue({
// ...
router,
// ...
});
对照需求 1
测试一下, 没啥问题后来看需求 3
:点击面包屑 All
跳转到初始地址 #city
。
修改面包屑
在 Breadcrumb
组件中做如下修改
<router-link exact exact-active-class="exact" :to="{ path: '/city' }">
All
</router-link>
<router-link>
组件支持用户在具有路由功能的应用中 (点击) 导航。
这里,我们做了两件事:
- 配置了目标路由被精确匹配的时候应该激活的样式
- 配置了表示目标路由的链接
'/city'
对照需求 1
测试一下。最后我们来看需求 4
:通过导航栏或浏览器的前进后退导航
自定义前进后退导航
在 Breadcrumb
组件中,我们之前已经添加了前进后退按钮,现在需要实现交互:
- 处理前进
forward() {
this.$router.go(1);
}
router.go(n)
方法的参数是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)
。
- 处理后退
back() {
this.$router.go(-1);
}
- 修改
handleChange
handleChange(value) {
this.$router.push({ path: `/city/${value}` });
},
注意:在 Vue 实例内部,你可以通过 $router 访问路由实例。因此你可以调用 this.$router.push。
都是 Vue Router 编程式的导航,很简单。对照需求 1
测试一下。最后我们来看需求 4
:通过导航栏或浏览器的前进后退导航
同步修改浏览器标题栏
这个操作需要直接修改 DOM,是一个副作用,需要监听$route.params.code
watch: {
"$route.params.code": {
handler(value) {
document.title = this.currentCity
this.selected = value;
},
immediate: true,
},
},
注意,我们还同步修改了selected
,并设置immediate
为true
,确保该回调将会在侦听开始之后被立即调用。
参考示例
- 访问 codesandbox 查看项目代码
- 使用 navbar 和 ui-router 动态加载外部模板
- React Router 简介
评论 (0)