vue-router基本使用

254 阅读7分钟

通过vue.js我们已经创建了应用,接下来要做的就是将我们的组件映射到路由上去。vue-router能让我们在不完全刷新页面的情况下,根据url的指示,对组件进行展示

基础使用

1.下载安装

unpkg.com/vue-router@…

npm install vue-router@4
yarn add vue-router@4

2.将组件映射到路由上的基本操作

在src文件夹下创建router文件夹,创建index.js,配置路由参数 一共分为五步 导入需要的模块

import {
  createRouter,
  createWebHashHistory,
  createWebHistory,
} from "vue-router";

1.创建路由组件,或导入路由组件

const Home = { template: '<div>Home</div>' }
const About = { template: '<div>About</div>' }
//或静态导入
import User from "../views/User.vue";
// 路由懒加载,在需要的时候才导入,使用关键字About代替路径
const About = () => import("../views/About.vue");

2.定义路由表,每个组件都映射到一个路由

const routes = [
  { path: '/', component: Home },
  { path: '/about', component: About },
]

3.创建路由实例,并传递 routes 配置

const router = createRouter({
  // 4. 内部提供了 history 模式的实现。
  // 使用 hash 模式,有# ,不会向服务器发送数据
  // history: createWebHashHistory(),
  //HTML5模式
  history: createWebHistory(),
  routes, // `routes: routes` 的缩写
});

export default router;

4.在路由实例内部配置history内部配置 history 模式

5.在main.js里面导入router,并将router实例挂载到跟实例上

import router from './router'
createApp(App).use(router).use(store).mount('#app')//严格按照顺序来

HTML展示

<div id="app">
  <p>
  
    <router-link to="/">Go to Home</router-link>
    <router-link to="/about">Go to About</router-link>
    
  </p>

  <router-view></router-view>
  
</div>

router-view展示与url相对应的标签,可以把他放在任何地方,来适应你的布局

router-link 使用这个组件来创建导航链接,to指向路由路径,既路由表中path后面的参数。这个标签能使得不重新加载页面的情况下更改 URL,处理 URL 的生成以及编码。

`<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签

路由模式

动态路由匹配

对于样式一样,但是数据不一样的情况,例如详情页,那么页面如何加载呢?路由要如何匹配。 这就需要动态路由匹配了。动态路由 由/:表示斜杠后面的参数可以是任何内容 router文件夹中 index.js 匹配路由

  // 动态字段以冒号开始
  { path: '/users/:id', component: User },

现在像 /users/johnny 和 /users/jolyne 这样的 URL 都会映射到同一个路由。 路径参数 用冒号 : 表示。当一个路由被匹配时,它的 params 的值将在每个组件中以 useRoute().params.id 的形式暴露出来。因此,我们可以通过更新 User 的模板来呈现当前的用户。

APP.VUE router-link中路径设置

 <router-link to="/user/123">Go to User</router-link>

组件中获取id

<script setup>
import { useRoute } from "vue-router";
// console.log(useRoute());
console.log(useRoute().params.id);
</script>

匹配所not found

写一个notfound页面,里面展示资源找不到的时候页面显示的内容 将not found的放在最后,路由从上到下查找都不匹配,找到最后的时候匹配查找到这个位置的所有路由,说明404 not found

 // 用到正则表达式,说明捕获所有路由,404 not found
  { path: "/:path(.*)", component: NotFound },

路由上的正则

{
     //后面的参数必须是数字
     path: "/new/:id(\\d+)", 
     path: "/new/:id+"//参数个数有1个或以上
    path: "/new/:id*"//参数有0个或以上
    path: "/new/:id(\\d+)*",
    component: New,
  },

设置导航

<router-link :to="/new/456"  >Go to New</router-link>

嵌套路由

在同一个组件中,点击样式一,显示组件一的内容。点击样式二,显示组件二的内容

image.png 父组件中嵌套两个组件,这两个组件的路由写进父组件的children数组中,注意此处的路由不需要/号

 //嵌套路由,一个组件的 UI 由多层嵌套的组件组成
  {
    path: "/parent",
    component: Parent,
    alias: ["/father", "/mother", "/fuqin"], //取别名,浏览器上三个名字都可以访问Parent页面
    children: [
      { path: "styleone", component: StyleOne },
      { path: "styletwo", component: StyleTwo },
    ],
  },

父组件的组件写法,如何把子组件嵌套进父组件中

<template>
    <div>
       <h2>父组件Parent</h2>
       <h2>嵌套路由</h2>
       <!-- router a标签,点击即可将组件呈现在router-link中 -->
       <router-link to="/parent/styleone">样式一</router-link>
       <router-link to="/parent/styletwo">样式二</router-link>
       <!-- 样式一样式二展现在route-view中 -->
       <router-view></router-view>
    </div>
</template>

app.vue中设置导航

      <router-link to="/parent">Go to Parent</router-link>

编程式导航

路由表配置 可以使用router访问路由实例。router访问路由实例。router可以导航到不同的url,可以使用router.push方法。这个方法回向history栈添加一个新的记录。所以用户点击浏览器后退按钮时,会返回之前的url. 当你点击 <router-link> 时,内部会调用这个方法,所以点击 <router-link :to="..."> 相当于调用 router.push(...) : 从page--->(跳转到)new

  { path: "/page", component: Page },
  {
    // name 命名路由,在router-link上 to= { name: 'new', params: { id: 135 } }
    name: "new",
    path: "/new/:id(\\d+)*",
    component: New,    
  }

page.vue.page页面跳转验证:this.$router.push的使用

<template>
  <div>
    <h3>跳转</h3>
    <button @click="goPage">跳转页面</button>
  </div>
</template>

<script>
export default {
  methods: {
    goPage: function () {
      //   console.log(this.$router);
      this.$router.push("/about");
      //如果条件成立才进行跳转
         if (123 === 123456) {
      //     this.$router.push("/");
      //   }
      //传入对象,但是属性path和params不能同时存在
       this.$router.push({path:"/new/1203"});
       this.$router.push({name:"new",params:{id:'987'}}); //new/987
      //带问号
       this.$router.push({ path: "/about", query: { name: "query" } });// /about?name=query
          },
  },
};

替换当前页面

它的作用类似于 router.push,唯一不同的是,它在导航时不会向 history 添加新记录,正如它的名字所暗示的那样——它取代了当前的条目。

     //替换当前位置,以下两条语句等价
      this.$router.push({ path: "/about",replace:true }); //替换当前位置
      this.$router.replace({ path: "/about"});

在历史堆栈中前进/后退

<template>
  <div>
    <h3>About</h3>
    <button @click="goBack">后退</button>
  </div>
</template>

<script setup>
import { useRoute } from "vue-router"; // console.log(useRoute()); 
console.log(useRoute().params.id);
useRoute()替换this.$router
 //前进或后退
    goBack: function () {
      this.$router.go(-1); //负1表示后退 前一个页面
      // this.$router.go(1);//正1表示前进
      // this.$router.go(n);//前进或后退n步
      //this.$router.back();  //等于go(-1);
      // this.$router.forward() //等于go(1); 
}

import { useRoute } from "vue-router"; // console.log(useRoute()); console.log(useRoute().params.id);
</script>

命名路由

在路由表中给路由添加一个属性name,这有以下优点:

  • 没有硬编码的 URL
  • params 的自动编码/解码。
  • 防止你在 url 中出现打字错误。
  • 绕过路径排序(如显示一个)
  {
    name: "new",
    path: "/new/:id(\\d+)*",
    component: New,    
  },

导航跳转这样写

      <router-link :to="{ name: 'new', params: { id: 123 } }"  >Go to New</router-link>
      或这样写
      
    this.$router.push({name:"new",params:{id:'987'}}); //new/987
    <!-- <router-link to="/new/123">Go to New</router-link> -->
    

命名路由

同一个路由展示多个视图,这几个视图都是同级的关系,和之前的嵌套路由不一样 路由配置,在shop路由中,同时展示ShopMain、ShopTop和ShopFoter三个同级组件

  {
    path: "/shop/:id",
    components: {
      default: ShopMain,
      //  前面的属性名与 `<router-view>` 上的 `name` 属性匹配
      Shoptop: ShopTop,
      ShopFoter: ShopFoter,
    },
    //是否给子组件传参 true传参,false不传参
    props: { default: true, Shoptop: true, ShopFoter: false },
  },

html/app.vue组件

这三个router-view分别展示Shoptop、ShopMain、ShopFoter

    <router-link to="/shop/gw">Go to Shop</router-link>
 
    <router-view name="Shoptop"></router-view>
    <router-view></router-view>
    <router-view name="ShopFoter"></router-view>

重定向与别名

  //重定向,使得"/"和 "/home"能访问同一个页面,redirect后面必须跟上已经定义好的路由
  {
    path: "/",
    // redirect: "/home", //第一种重定向方式 ,取用path:中的值
    // redirect: {name:"home"} //命名路由
    redirect: (to) => {
      console.log(to);
      return { path: "/home" };//返回对象
    },

重定向的时候,redirect后面需要跟着已经定义好的路由,path是新的名字,通过path上的名字,可以跳转到redirect后面接的路由 redirect后面有三种写法: 取别名

{
    path: "/parent",
    component: Parent,
    alias: ["/father", "/mother", "/fuqin"], 
}

传递参数

当 props 设置为 true 时,route.params 将被设置为组件的 props

const routes = [{ path: '/user/:id', component: User, props: true }]

在组件中通过defineProps接受从路由中传递过来的/:id的值

<script setup>
const props=defineProps({
    id:String
})

console.log(props);
console.log(props.id);
</script>

选项式API
<script>
export default {
  props: ['id'],
  mounted() {
    console.log(this.$route.params.id);
    console.log(this.id);
  },
};
</script>

命名视图

对于有命名视图的视图,必须为每个视图定义props,确定是否传递数据

const routes = [
  {
    path: '/user/:id',
    components: { default: User, sidebar: Sidebar },
    props: { default: true, sidebar: false }
  }
]

对象模式

当 props 是一个对象时,它将原样设置为组件 props。当 props 是静态的时候很有用。

const routes = [
  {
    path: '/promotion/from-newsletter',
    component: Promotion,
    props: { newsletterPopup: false }
  }
]

函数模式

你可以创建一个返回 props 的函数。这允许你将参数转换为其他类型,将静态值与基于路由的值相结合等等。



const routes = [
  {
    path: '/search',
    component: SearchUser,
    props: route => ({ query: route.query.q })
  }
]

URL /search?q=vue 将传递 {query: 'vue'} 作为 props 传给 SearchUser 组件。

请尽可能保持 props 函数为无状态的,因为它只会在路由发生变化时起作用。如果你需要状态来定义 props,请使用包装组件,这样 vue 才可以对状态变化做出反应。

历史模式

Hash模式

const router = createRouter({
  // 4. 内部提供了 history 模式的实现。
  // 使用 hash 模式,有# ,不会向服务器发送数据
  history: createWebHashHistory(),

  routes, // `routes: routes` 的缩写
});

HTML5模式

const router = createRouter({
  // 4. 内部提供了 history 模式的实现。
  //HTML5模式,正常的url,需要后端人员配置后台
  history: createWebHistory(),
  routes, // `routes: routes` 的缩写
});

导航守卫

路由守卫

全局守卫

每一次跳转都会触发,回调函数

// 全局守卫 关卡
router.beforeEach((to,from,next)=>{
  console.log(to);
  console.log(from);
  // 满足条件才能通行
  if(123==123){
    next();//通行证
  }
})

to:目标路由

from:原来的路由

next:通行证,可选参数,不带这个参数的时候不验证,直接通过。带这个参数,表示可以添加验证,验证成功,条件成立才进行跳转。例如登陆验证时候的token

每路守卫

写在路由表中

  {
    path: "/about",
    component: About,
    //每路守卫 进入about路由关卡
    beforeEnter: (to, from, next) => {
      console.log(to);
      console.log(from);
      if (123 === 123) {
        //在个人中心,这里一般是token,是否登录完成
        next(); //通行证
      }
    },
  },

组件内守卫

组件内守卫有三个验证,进入组件之前,组件内路由变化时,离开组件

<script>
export default {
  data() {
    return {
      routeage: 18,
    };
  },
  // 进入组件之前是拿不到组件数据的,组件数据通过next拿到,vm代表此组件对象
  beforeRouteEnter(to, from, next) {
    console.log(to);
    console.log(from);
    //通过vm拿到组件实例,此处vm代表new.vue对象
    next((vm) => {
      console.log(vm.routeage);
    });
    console.log("路由进入组件之前");
  },
  beforeRouteUpdate() {
    console.log("路由更新组件之前");
  },
  beforeRouteLeave() {
    console.log("路由离开组件之前");
  }
</script>

路由懒加载

当项目打包上线时,包过大,会影响页面加载,可以将不同路由对应的组件分割成代码块,当路由被访问时才加载相对应的组件 动态导入

// 路由懒加载,在需要的时候才导入,使用关键字About代替路径
const About = () => import("../views/About.vue");
路由配置
  {
    path: "/about",
    component: About,
  },