Vue入门 - 应用路由

100 阅读4分钟

创建定义

创建

在packge.json添加项目依赖 vue-router,再重启项目

{
  ...
  "dependencies": {
    "core-js": "^3.6.5",
    "vue": "^3.0.0-0",
    // 为了跟课程一直,使用了相同的版本号
    "vue-router":"^4.0.0-0"
  },
  ...
}

./app目录下创建路由文件 app.router.ts

//app.router.ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
/**
 * 定义路由
 */
const routes: Array<RouteRecordRaw> = [ 
// 路由内容在这里
];

/**
 * 创建路由
 */
const router = createRouter({
  history: createWebHistory(),
  routes,
});

export default router;

在 main.ts 根中使用 创建好的路由

// main.ts 
import { createApp } from 'vue';
import App from './app/app.vue';
import appRouter from './app/app.router';
const app = createApp(App);

//应用路由
app.use(appRouter);

app.mount('#app');

定义

定义路由就是组件对应的地址,每一条路由记录是一个对象,放在路由数组中。

const routes: Array<RouteRecordRaw> = [
  {
    path: '/',
    component: Index,
  },
  {
    path: '/about',
    component: About,
  },
];

定义好路由以后,在app.vue 中用 <router-view> 定义路由显示区域

<template>
  ...
  <div class="page-body">
    <router-view></router-view>
  </div>
</template>

路由名称

定义路由时,可以为路由起名,使用路由时,直接使用名称

const routes: Array<RouteRecordRaw> = [
  ...
  {
    path: '/about',
    component: About,
    name:'about'
  },
];

当为路由使用了自定义名称时,:to="{name:'xxx'}" 需要绑定一个对象

路由模块

可以在不同的地方定义路由模块,再去到根路由中导入路由模块

//路由模块 post.route.ts
import { RouteRecordRaw } from 'vue-router';
import PostIndex from './index/post-index.vue';

const routes: Array<RouteRecordRaw> = [
  {
    path: '/post',
    component: PostIndex,
  },
  ...
];

export default routes;

// 根路由 app.routes.ts
...
import postRoutes from './post/post.route';

const routes: Array<RouteRecordRaw> = [
  ...
  // ...postRoutes是展开操作符
  ...postRoutes,
];
...
export default router;

应用路由模块时,可直接使用路由地址或路由名称,无需考虑相对位置

嵌套路由

可以为路由创建子路由,子路由创建在路由的children属性中,children是一个路由数组,里面取相对位置

//路由模块 post.route.ts
import { RouteRecordRaw } from 'vue-router';
import PostShow from './show/post-show.vue';
import Meta from './components/meta.vue';

const routes: Array<RouteRecordRaw> = [
  ...
  {
    path: '/post/:postId',
    name: 'postShow',
    component: PostShow,
    children: [
      {
        path: 'meta',
        component: Meta,
      },
    ],
  },
];

export default routes;

定义好路由地址后,需要在路由组件中设置新的<router-view> 确定显示区域

//post-show.vue
<template>
  <div>
    this is post Show
    {{ postId }}
  </div>
  <router-view></router-view>
</template>

访问的链接将会是: /post/:postId/meta ,Meta组件的内容显示在postShow组件里面

链接

router-link

通过点击页面上的元素进行路由跳转可以用 <router-link> 包装链接

<router-link> 中,具有 to="" 属性,需要填写要去的路由地址

当为路由使用了自定义名称时,:to="{name:'xxx'}" 需要绑定一个对象

<template>
  <div class="pages">
    ...
      <div class="menu">
        <router-link class="menu-item" to="/">首页</router-link>
        <router-link class="menu-item" :to="{ name: 'about' }"
          >关于</router-link
        >
        <router-link class="menu-item" :to="{ name: 'postIndex' }"
          >内容</router-link
        >
      </div>
  </div>
</template>

用代码切换

除了在template中使用<router-link>,还可以直接在 script中用代码进行切换。

例如需要在一个点击事件中使用时:

<template>
  <p>欢迎加入网站</p>
  <p @click="onTapLink">我们是谁</p>
</template>

<script>
export default {
  methods: {
    onTapLink() {
      //   this.$router.push('/about');
      this.$router.replace({ name: 'about' });
    },
  },
};
</script>

$router.push

会保存一条浏览器历史记录,可以用浏览器返回

$router.replace

不保存浏览器历史记录,无法用浏览器返回

重定向

可以使用重定向让用户访问指定位置。

重定向需要先决定重定向那个路由,所以他也是一条路由记录需要放在routes数组中。

const routes: Array<RouteRecordRaw> = [
  {
    path: '/about-us',
    // redirect: '/about',
    // redirect: { name: 'about' },
    redirect(to) {
      console.log(to);
      return '/about';
    },
  },
  ...postRoutes,
];

有三种方式可以定义重定向到哪里去:

  • redirect: '/about' 直接输入路由地址

  • redirect: { name: 'about' } 使用路由名称

  • redirect(to) {... ;return '/about';}使用一个方法 ,

    • to 表示用户要访问的路由

    • 需要返回一个路由

参数传递

动态路由

定义路由地址时,可以使用动态路由设置参数。

访问时 '/post/:postId' 中的 :postId 就是要传的参数

//路由模块 post.route.ts
import { RouteRecordRaw } from 'vue-router';
import PostShow from './show/post-show.vue';

const routes: Array<RouteRecordRaw> = [
  {
    path: '/post/:postId',
    component: PostShow,
  },
  ...
];

export default routes;

在访问对应链接时,可以在 <template><script> 上的 $route.params.postId 中找到参数的值

// post-show.vue
<template>
  <div>
    this is post Show
    {{ $route.params.postId }}
  </div>
</template>

<script>
export default {
  created() {
    console.log(this.$route.params.postId);
  },
};
</script>

传递属性

除了使用$route.params.postId获取参数,还可以使用props直接获取参数。

如果是动态路由数据,需要在路由设置中打开props的属性

如果是静态数据,可以直接在props属性中定义

//路由模块 post.route.ts
import { RouteRecordRaw } from 'vue-router';
import PostShow from './show/post-show.vue';

const routes: Array<RouteRecordRaw> = [
   {
      path: '/post/:postId',
      component: PostShow,
      // 动态数据打开props选项
      props: true,
   },
   {
      path: '/post',
      component: PostIndex,
      // 定义静态数据直接使用
      props: {
        sute: 'cute',
      },
   },
];

export default routes;

在对应组件中,需要设置props属性,数据名称需要跟路由中定义的名称保持一致

//post-show.vue
// 动态路由数据
<template>
  <div>
    this is post Show
    {{ postId }}
  </div>
</template>

<script>
export default {
  props: {
    postId: String,
  },
};
</script>
//post-index.vue
// 定义静态数据直接使用
<template>
  <p>this is a post</p>
  {{ sute }}
</template>

<script>
export default {
  props: {
    sute: String,
  },
};
</script>

守卫判断

路由守卫

路由守卫可以为每一次访问进行拦截、处理、放行。使用router对象的beforeEach方法。beforeEach方法接受三个参数(to, from, next)

  • to:要去的路由
  • from:来自那个路由
  • next() : 后路由才会继续,否则会被拦截
//app.router.ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';

const routes: Array<RouteRecordRaw> = [
  ...
];
const router = createRouter({
   ...
});

router.beforeEach((to, from, next) => {
  console.log('导航守卫开始工作');
  //判断条件只包括当前路由,他的子路由仍然可以正常访问
  if (to.name === 'postIndex') {
    next('/');
  } else {
    next();
  }
});

export default router;

路由元数据

可以为路由设置一些元数据,再根据元数据进行一些操作。

元数据可以在路由记录上使用 meta 的对象。

在守卫中使用 to.matched.some(record => record.meta.requiresAuth); 来判断是否存在对应meta值的路由。

//app.router.ts
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';

const routes: Array<RouteRecordRaw> = [
  {
    path: '/',
    component: Index,
    meta: {
      requiresAuth: true,
    },
  },
  ...
];
const router = createRouter({
   ...
});

router.beforeEach((to, from, next) => {
  const requiresAuth = to.matched.some(record => record.meta.requiresAuth);
  if (requiresAuth) {
    console.log('导航守卫开始工作');
  }
  next();
});

export default router;