vue-router 路由传参方式/缓存路由/路由跳转

基础

前端路由

用来开发 SPA(单页面应用)

单页面应用

  • 整个应用只有一个完整页面,页面变化都是在这一个页面更新的
  • 点击链接不会刷新整个页面,会局部更新,也会更新浏览历史(地址)
  • 点击链接也不会发送请求,自己写 ajax 代码发送请求

前端路由的原理

  • 点击链接不会刷新整个页面 --> 给 a 标签绑定点击事件,阻止其默认行为
  • 会更新浏览历史(地址) --> 调用 history.push(path),就可以更新了
  • 会局部更新 --> 内部会监听浏览历史的变化(history.listen(listener)),一旦发生变化就会遍历路由的所有配置,看当前路径(浏览地址)是否匹配上路由路径(path),匹配上就加载 component

vue-router 提供组件

  • <router-link> 用来路由链接导航
  • <router-view> 用来显示当前路由组件

$route$router

$route

route用来获取路由参数(params/query)和路径(path)

$router

用来编程式导航(push/replace/go/back/forward)
在这里插入图片描述

路由传参方式总结

params参数

  • 路由配置
{
	path:"/xxx/:id",  //:id 动态路由匹配,能匹配多个地址
	component:Xxx
}
  • 跳转路由路径
<router-link to="/xxx/xxx/1">xxx</router-link>
  • 子路由接收 :id的参数
  this.$route.params.id 

// 当 :id 的参数发生变化时,需要使用watch监视属性的变化,来更新数据 
  watch: {
    $route: {
      handler(newVal) {
        const id = +newVal.params.id;
        this.message = this.messages.find((message) => message.id === id);
      },
      // 正常情况下,watch只有值发生变化的时候才会调用
      // 一上来会调用一次
      immediate: true,
    },
  },

query

  • 路由链接设置
<router-link to="/xxx?brand='rolls'&engine='6.75'"></router-link>
  • 子组件的获取
this.$route.query

props

  • 将原先的params参数和query参数以props方式传递给组件

  • 子组件路由配置

props(route) {
  return {
    ...route.params,
    ...route.query,
  };
},    
  • 子组件声明接收
props: ['id', 'name', 'age']
  • 子组件使用
this.xxx

命名路由

  • 路由配置,需要name属性
{
  name: "Detail", // 命名路由
  path: "detail/:id",
  component: Detail,
}
  • 路由路径
<router-link
  :to="{
    name: 'Detail', // 跳转哪个命名路由
    params: {
      id: message.id,
    },
    query: {
      name: 'jack',
      age: 18,
    },
  }"
>xxx</router-link>

相同层级路由传递

  • 传参
<router-view key="value"></router-view>
  • 路由组件声明接收
 props: ['key']
  • 路由组件使用
this.xxx 

最基础使用

配置

下载包

yarn add vue-router

views组件

  • About和Home组件
<template>
  <h1>About</h1>
</template>

<script>
export default {
  name: 'About',
};
</script>

<style>
</style>

src下定义router文件夹

// 因为要安装到Vue上面
import Vue from "vue";
import VueRouter from "vue-router";

// 引入组件
import About from "../views/About/index.vue";
import Home from "../views/Home/index.vue";

//     安装插件
//     一旦安装插件,就会给全局注册两个组件:router-link  router-view
//     还会给原型上添加一个属性
Vue.use(VueRouter);

const router = new VueRouter({
  // 定义路由的配置
  routes: [
    {
      path: "/about", // 路由路径
      component: About // 路由组件
    },
    {
      path: "/home",
      component: Home
    },
    {
      // 当路径是/时,会切换到/home
      path: "/",
      redirect: "/home" // 重定向
    }
  ]
});

export default router;


main.js应用路由

import Vue from "vue";
// 引入路由
import router from "./router/index";
import App from "./App.vue";

Vue.config.productionTip = false;

new Vue({
  render: h => h(App),
  // 应用路由
  router
}).$mount("#app");

app.vue显示

  • router-link 路由链接导航
    切换地址
  • router-view 显示对应的路由组件
    内部会根据当前的地址,遍历路由中routes配置,找到相应的组件显示
<template>
  <div class="container">
    <h1>Router Page</h1>
    <div class="row">
      <div class="col-md-4">
        <ul class="nav nav-pills nav-stacked">
          <li>
            <router-link to="/about">About</router-link>
          </li>
          <li>
            <router-link to="/home">Home</router-link>
          </li>
        </ul>
      </div>
      <div class="col-md-8">
        <!-- 显示对应的路由组件 -->
        <router-view></router-view>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'App',
};
</script>

<style>
</style>

在这里插入图片描述

嵌套路由

新建子组件

在这里插入图片描述

<template>
  <h2>Message</h2>
</template>

<script>
export default {
  name: 'Message',
};
</script>

<style>
</style>

引入组件,配置路由

import Message from '../views/Home/Message/index.vue'
import News from '../views/Home/News/index.vue'

{
  path: "/home",
  component: Home,
  // 子路由,即使只有一个值也应该是数组
  children: [
    {
      path: "/home/message",
      component: Message
    },
    {
      // 当路径不是 / 开头,就会已父路由路径补全,也是一种简写
      // 注意,简写一定不要再加 /
      path: "news",
      component: News
    }
  ]
},

home组件显示

<template>
  <div>
    <h1>Home</h1>
    <ul class="nav nav-tabs">
      <li>
        <router-link to="/home/message">message</router-link>
      </li>
      <li>
        <router-link to="/home/news">news</router-link>
      </li>
    </ul>
    <router-view></router-view>
  </div>
</template>

在这里插入图片描述

路由传参

params参数

message添加元素

  • 效果图
    在这里插入图片描述
<template>
  <div>
    <h2>Message</h2>
    <ul>
      <li v-for="item in messageData" :key="item.id">
        <!-- to后面必须跟字符串,:绑定以后字符串才会被当做js去解析 -->
        <router-link :to="`/home/message/detail/${item.id}`">{{
          item.content
        }}</router-link>
      </li>
    </ul>
    <router-view></router-view>
  </div>
</template>

<script>
export default {
  name: 'Message',
  data() {
    return {
      // 定义一个假数据
      messageData: [],
    };
  },
  // 模拟请求数据
  mounted() {
    setTimeout(() => {
      this.messageData = [
        { id: 1, content: 'message01' },
        { id: 2, content: 'message02' },
        { id: 3, content: 'message03' },
      ];
    }, 1000);
  },
};
</script>

<style>
</style>

在这里插入图片描述

创建Deail

<template>
  <ul>
    <li>id:{{ chilData.id }}</li>
    <li>name:{{ chilData.name }}</li>
    <li>content:{{ chilData.content }}</li>
  </ul>
</template>

<script>
export default {
  name: 'Detail',
  data() {
    return {
      baseData: [
        { id: 1, name: 'name111', content: 'content111' },
        { id: 2, name: 'name222', content: 'content222' },
        { id: 3, name: 'name333', content: 'content333' },
      ],
      chilData: {},
    };
  },
  watch: {
    $route: {
      handler(newVal) {
        const id = +newVal.params.id;
        this.chilData = this.baseData.find((item) => item.id === id);
      },
      // 正常情况下,watch只有值发生变化的时候才会调用
      // 一上来会调用一次
      immediate: true,
    },
  },
};
</script>

<style>
</style>

动态路由配置

import Detail from "../views/Home/Message/Detail/index.vue";

{
  path: "/home",
  component: Home,
  children: [
    {
      path: "/home/message",
      component: Message,
      children: [
        {
          // 动态路由,能够匹配多个路由,简写,省略 /
          path: "detail/:id",
          component: Detail
        }
      ]
    },
    {
      path: "news",
      component: News
    }
  ]
},

在这里插入图片描述

Detail

  • 在其this原型链上有一个$route
  mounted() {
    console.log(this);
  },
<template>
  <div>
    <ul>
      <li>{{ showData.id }}</li>
      <li>{{ showData.brand }}</li>
      <li>{{ showData.color }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  name: 'Detail',
  data() {
    return {
      detailData: [
        { id: 1, brand: '劳斯', color: 'green' },
        { id: 2, brand: '宾利', color: 'black' },
        { id: 3, brand: '法拉利', color: 'red' },
      ],
      showData: {},
    };
  },
  //   mounted() {
  //     console.log(this);
  //   },
  watch: {
    // 监视this原型链行的$route
    $route: {
      handler(newRouder) {
        // console.log(newRoder);  见图
        const id = +newRouder.params.id;
        this.showData = this.detailData.find((item) => item.id === id);
      },
      // 正常情况下,watch只有值发生变化的时候才会调用
      // 一上来会调用一次
      immediate: true,
    },
  },
};
</script>

<style>
</style>

在这里插入图片描述

  • wantch监视结果
    在这里插入图片描述

immediate

正常情况下,watch只有值发生变化的时候才会调用
增加这个属性一上来会调用一次

immediate: true,

在这里插入图片描述

watch监视 属性官方文档
在这里插入图片描述

done

在这里插入图片描述

query

路由链接设置

<template>
  <div>
    <h2>Message</h2>
    <ul>
      <li v-for="item in messageData" :key="item.id">
        <!-- query方法就是在之前基础上增加查询字符串 -->
        <router-link
          :to="`/home/message/detail/${item.id}?brand='rolls'&engine='6.75'`"
          >{{ item.content }}</router-link
        >
      </li>
    </ul>
    <router-view></router-view>
  </div>
</template>

子组件获取

this.$route.query

在这里插入图片描述

props

路由传递

<!-- 将原先的params参数和query参数以props方式传递给组件 -->
<router-link
  :to="`/home/message/detail/${item.id}?brand='rolls'&engine='6.75'`"
  >{{ item.content }}</router-link
>

在这里插入图片描述
#3# 子组件配置

 {
   path: "detail/:id",
   component: Detail,
   // 增加props方法
   props(routeQuery) {
     // console.log(routeQuery);
     return {
       ...routeQuery.params,
       ...routeQuery.query
     }
   }
 }

子组件声明接收


-没有props接收,可以在$attrs上面看到,也可以在组件挂载的时候打印this查看
在这里插入图片描述

  • props接收了,$attrs就没有了
  watch: {
    $route: {
      handler(newRouder) {
        const id = +newRouder.params.id;
        this.showData = this.detailData.find((item) => item.id === id);
      },
      immediate: true,
    },
  },
  // props接收
  props: ['id', 'brand', 'engine'],

3在这里插入图片描述

this使用

this.xxx

命名路由

  • 路由取个名字

路由传递

<template>
  <div>
    <h2>Message</h2>
    <ul>
      <li v-for="item in messageData" :key="item.id">
        <!-- 是个对象,有个name属性,就是要去的组件名称,在路由中配置 -->
        <router-link
          :to="{
            name: 'Detail',
            params: {
              id: item.id,
            },
            query: {
              brand: 'rolls',
              engine: 6.75,
            },
          }"
          >{{ item.content }}</router-link
        >
      </li>
    </ul>
    <router-view></router-view>
  </div>
</template>

路由配置

{
  path: "/home/message",
  component: Message,
  children: [
    {
      // 名称,和组件名称一样,一定要有
      name: "Detail",
      path: "detail/:id",
      component: Detail,
      props(routeQuery) {
        return {
          ...routeQuery.params,
          ...routeQuery.query
        };
      }
    }
  ]
},

接收

  • 同上面一样,可以props接收
    在这里插入图片描述

相同层级组件传递

  • 给相同层级的路由组件一起传递公共参数传参

传参

<template>
  <div class="container">
    <h1>Router Page</h1>
    <div class="row">
      <div class="col-md-4">
        <ul class="nav nav-pills nav-stacked">
          <!-- 给相同层级的路由组件一起传递参数 -->
          <li>
            <router-link to="/about">About</router-link>
          </li>
          <li>
            <router-link to="/home">Home</router-link>
          </li>
        </ul>
      </div>
      <div class="col-md-8">
        <!-- 这样去传参,只要显示哪个组件,就给哪个组件传参 -->
        <router-view rolls="royce"></router-view>
      </div>
    </div>
  </div>
</template>

路由组件声明接收

<template>
  <h1>About</h1>
</template>

<script>
export default {
  name: 'About',
  // 接收公共组件数据
  props: ['rolls'],
};
</script>

<style>
</style>

路由组件使用

  • this直接使用即可
    在这里插入图片描述

命名视图

命名路由

缓存路由组件

组件卸载与加载

  • 一个组件加载,另一个组件会卸载,这样性能不哈
    在这里插入图片描述

在这里插入图片描述

路由组件缓存

在这里插入图片描述

 <!-- app组件,要缓存哪个路由,就要在外面包一个keep-alive -->
 <keep-alive include="Home">
   <router-view rolls="royce"></router-view>
 </keep-alive>
  • 缓存了,所以还能看到
    在这里插入图片描述
  • 没缓存,直接看不到
    在这里插入图片描述

缓存多个 include

数组也可以

 <keep-alive include="Home,About">

在这里插入图片描述
在这里插入图片描述

排除法 exxlude

<keep-alive exclude="About">

在这里插入图片描述

max 最多缓存数量

<keep-alive exclude="About" max="1">

缓存组件问题


<keep-alive exclude="">
   <router-view rolls="royce"></router-view>
</keep-alive>
// 这两个声明周期函数只针对keep-alive缓存的组件触发
 // 已激活,在显示
  activated() {
    console.log('About activated ');
  },
  // 未激活
  deactivated() {
    console.log('About deactivated');
  },
  • 优点:性能好,不会重新发请求
  • 缺点:数据一致是旧的
    == 缓存起来以后不会再走mounted,以前发送请求都在mounted发,但是现在缓存起来了不会再走mounted,不会再请求最新数据,不能保证数据最新的 ==
<template>
  <h1>About</h1>
</template>

<script>
export default {
  name: 'About',
  props: ['rolls'],
  mounted() {
    console.log('about mounted');
  },
  beforeDestroy() {
    console.log('about beforeDestroy');
  },
  // 已激活,在显示
  activated() {
    console.log('About activated ');
  },
  // 未激活
  deactivated() {
    console.log('About deactivated');
  },
};
</script>

<style>
</style>

在这里插入图片描述

路由跳转

<router-link to=""

  • 路由链接导航
  • 如果点击链接或者按钮只需要进行路由跳转,
  • 例如:导航链接

编程式导航

  • 编程式导航
  • 如果点击链接或者按钮需要做一些其他事,再进行路由跳转,例子:登录按钮、修改按钮

push()

replace()

back()

forward()

<template>
  <div>
    <h2>Message</h2>
    <ul>
      <li v-for="item in messageData" :key="item.id">
        <!-- 是个对象,有个name属性 -->
        <router-link
          :to="{
            name: 'Detail',
            params: {
              id: item.id,
            },
            query: {
              brand: 'rolls',
              engine: 6.75,
            },
          }"
          >{{ item.content }}</router-link
        >
        <!-- 增加按钮,可以回退 -->
        <button @click="push(item.id)">push</button>
        <!-- 替换,不可以回退 -->
        <button @click="replace(item.id)">replace</button>
      </li>
    </ul>
    <!-- 后退,简写 -->
    <button @click="$router.back()">goBack</button>
    <!-- 前进,简写 -->
    <button @click="$router.forward()">goForward</button>
    <router-view></router-view>
  </div>
</template>
  methods: {
    // 编程式导航
    // 添加
    push(id) {
      // console.log(this);
      this.$router.push(`/home/message/detail/${id}?brand=rolls&engine=675`);
    },
    // 替换
    replace(id) {
      this.$router.replace(`/home/message/detail/${id}?brand=rolls&engine=675`);
    },
  },

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值