Vite + Vue3 + Ts + Router 路由

12 篇文章 1 订阅
4 篇文章 0 订阅

Vue Router 官网

1、安装

npm install vue-router - S

2、创建 router

  • 在项目根目录中 str 文件夹中创建 router 目录,并目录中创建 index.ts 文件,文件示例代码如下:
// 创建一个路由器,并暴露出去

// 第一步:引入 createRouter
import { createRouter, createWebHistory } from "vue-router";

// 第二步:创建路由器
// router :路由器
// route :路由
// routes :多个路由
const router = createRouter({
  history: createWebHistory(), // 路由器的工作模式
  routes: [
    {
      path: "/a",
      component: () => import("@/views/A.vue"),
    },
    {
      path: "/b",
      component: () => import("@/views/B.vue"),
    },
    {
      path: "/c",
      component: () => import("@/views/C.vue"),
    },
  ],
});

export default router;

3、注册路由

  • main.ts 文件中导入 router,并注册,示例代码如下:
import { createApp } from "vue";
import App from "./App.vue";
import { router } from "./router/router";

const app = createApp(App);
app.use(router);
app.mount("#app");

4、使用方法

  • App.vue 页面
<template>
  <h2 class="title">Vue3 路由测试</h2>
  <!-- 导航区 -->
  <div class="routers">
    <RouterLink to="/a" active-class="active">首页</RouterLink>
    <RouterLink to="/b" active-class="active">新闻</RouterLink>
    <RouterLink to="/c" active-class="active">体育</RouterLink>
  </div>
  <!-- 展示区 -->
  <div class="container">
    <RouterView></RouterView>
  </div>
</template>

<script setup lang="ts">
import { RouterView, RouterLink } from "vue-router";
</script>

<style>
.title {
  border-radius: 40px;
  line-height: 80px;
  text-align: center;
  border: 1px #999 solid;
  background: linear-gradient(to bottom, green, #ff9999, green);
}

.routers {
  display: flex;
  justify-content: space-around;
}

.routers a {
  border: 1px #cdcdcd solid;
  padding: 10px 20px;
  border-radius: 4px;
  background: #999;
  text-decoration: none;
}

.routers .active {
  background: #c00000;
  color: #fff;
}

.container {
  border: 1px #333 solid;
  height: 400px;
  margin-top: 20px;
  border-radius: 4px;
}
</style>
  • A.vue 页面
<template>
<h2>我是 A 页面</h2>
</template>

<script setup>

</script>

<style lang='scss' scoped>

</style>
  • B.vue 页面
<template>
  <h2>我是 B 页面</h2>
</template>

<script setup></script>

<style lang="scss" scoped></style>
  • C.vue 页面
<template>
  <h2>我是 C 页面</h2>
</template>

<script setup></script>

<style lang="scss" scoped></style>

5、两个注意点

  • 1、路由组件通常存在 pagesviews 文件夹,一般组件通常存放在 components 文件夹。
  • 2、通过点击导航,视觉效果上“消失”了的路由组件,默认是被销毁掉的,需要的时候再去挂载。

6、路由器工作模式

1、History 模式

  • 优点URL 更加美观。不带有 # ,更接近传统的网站 URL
  • 缺点:后期项目上线,需要服务端配合处理路径问题,否则刷新会有404错误。
const router = createRouter({
	history:createWebHistory()
})

2、Hash 模式

  • 优点:兼容性更好,因为不需要服务器处理路径。
  • 缺点URL 带有 # 不太美观,且在 SEO 优化方面相对较差。
const router = createRouter({
	history:createWebHashHistory()
})

7、to 的两种写法

第一种:字符串写法

<RouterLink to="/a" active-class="active">首页</RouterLink>

第二种:对象写法

  • 对象写法
<RouterLink :to="{ path: '/c' }" active-class="active">体育</RouterLink>
  • 通过 name 属性跳转方法
<RouterLink :to="{ name: 'new' }" active-class="active">新闻</RouterLink>

8、嵌套路由

  • 示例代码如下:
  • src -> router -> index.ts 文件内容如下:
// 创建一个路由器,并暴露出去

// 第一步:引入 createRouter
import { createRouter, createWebHashHistory } from "vue-router";

// 第二步:创建路由器
// router :路由器
// route :路由
// routes :多个路由
const router = createRouter({
  history: createWebHashHistory(), // 路由器的工作模式
  routes: [
    {
      path: "/",
      redirect: "/a",
    },
    {
      path: "/a",
      component: () => import("@/views/A.vue"),
    },
    {
      name: "new",
      path: "/b",
      component: () => import("@/views/B.vue"),
      children: [
        // 嵌套路由
        {
          path: "detail",
          component: () => import("@/views/NewsDatails.vue"),
        },
      ],
    },
    {
      name: "about",
      path: "/c",
      component: () => import("@/views/C.vue"),
    },
  ],
});

export default router;
  • B.vue 文件内容如下:
<template>
  <div class="p">
    <div class="menu">
      <h3>新闻列表</h3>
      <ul>
        <li v-for="item in news" :key="item.id">
          <h4>
            <RouterLink to="/b/detail">{{ item.title }}</RouterLink>
          </h4>
        </li>
      </ul>
    </div>
    <div class="content">
      <RouterView />
    </div>
  </div>
</template>

<script setup>
import { reactive } from "vue";
import { RouterView, RouterLink } from "vue-router";

const news = reactive([
  {
    id: 1,
    title: "新闻标题01",
    content: "新闻内容01",
  },
  {
    id: 2,
    title: "新闻标题02",
    content: "新闻内容02",
  },
  {
    id: 3,
    title: "新闻标题03",
    content: "新闻内容03",
  },
]);
</script>

<style lang="scss" scoped>
.p {
  display: flex;
  height: 100%;

  .menu {
    width: 30%;
  }

  .content {
    border: 4px #c00000 solid;
    border-radius: 10px;
    height: 90%;
    width: 70%;
    margin: 10px;
  }
}
</style>
  • NewsDateils.vue 页面内容如下:
<template>
  <h3>我是新闻详情页面</h3>
</template>

<script setup></script>

<style lang="scss" scoped></style>

9、传参数

  • vue 传参数方式有两种
  • query 方式传递
    • 不需要修改路由文件中的路由配置
<!-- B.vue 页面 -->
<template>
  <div class="p">
    <div class="menu">
      <h3>新闻列表</h3>
      <ul>
        <li v-for="item in news" :key="item.id">
          <h4>
            <!-- 第一种写法 -->
            <!-- <RouterLink :to="'/b/detail?content=' + item.content">{{
              item.title
            }}</RouterLink> -->

            <!-- 第二种写法 -->
            <RouterLink
              :to="{
                path: '/b/detail',
                query: {
                  content: item.content,
                },
              }"
              :query="item"
              >{{ item.title }}</RouterLink
            >
          </h4>
        </li>
      </ul>
    </div>
    <div class="content">
      <RouterView />
    </div>
  </div>
</template>

<script setup>
import { reactive } from "vue";
import { RouterView, RouterLink } from "vue-router";

const news = reactive([
  {
    id: 1,
    title: "新闻标题01",
    content: "新闻内容01",
  },
  {
    id: 2,
    title: "新闻标题02",
    content: "新闻内容02",
  },
  {
    id: 3,
    title: "新闻标题03",
    content: "新闻内容03",
  },
]);
</script>

<style lang="scss" scoped>
.p {
  display: flex;
  height: 100%;

  .menu {
    width: 30%;
  }

  .content {
    border: 4px #c00000 solid;
    border-radius: 10px;
    height: 90%;
    width: 70%;
    margin: 10px;
  }
}
</style>
<!--接受参数页面-->
<!--简单写法-->
<template>
  <h3>新闻详情</h3>
  <h4>{{ route.query.content }}</h4>
</template>

<script setup>
import { useRoute } from "vue-router";

// 接受路由传递的参数
const route = useRoute();
</script>

<style lang="scss" scoped></style>
<!--装逼写法-->
<template>
  <h3>新闻详情</h3>
  <h4>{{ query.content }}</h4>
</template>

<script setup>
import { useRoute } from "vue-router";
import { toRefs } from "vue";

// 接受路由传递的参数
const route = useRoute();
const { query } = toRefs(route); // 结构化赋值
</script>

<style lang="scss" scoped></style>
  • params 方式传递
    • 需要修改路由配置文件,路由中添加占位字符串
// 路由配置文件
// 创建一个路由器,并暴露出去

// 第一步:引入 createRouter
// 创建一个路由器,并暴露出去

// 第一步:引入 createRouter
import { createRouter, createWebHashHistory } from "vue-router";

// 第二步:创建路由器
// router :路由器
// route :路由
// routes :多个路由
const router = createRouter({
  history: createWebHashHistory(), // 路由器的工作模式
  routes: [
    {
      path: "/",
      redirect: "/a",
    },
    {
      path: "/a",
      component: () => import("@/views/A.vue"),
    },
    {
      name: "new",
      path: "/b",
      component: () => import("@/views/B.vue"),
      children: [
        // 嵌套路由
        {
          name: "xiangqing",
          path: "detail/:content?",  // 占位,可传可不传
          component: () => import("@/views/NewsDatails.vue"),
        },
      ],
    },
    {
      name: "about",
      path: "/c",
      component: () => import("@/views/C.vue"),
    },
  ],
});

export default router;
<!--B.vue 页面-->
<template>
  <div class="p">
    <div class="menu">
      <h3>新闻列表</h3>
      <ul>
        <li v-for="item in news" :key="item.id">
          <h4>
            <!-- 第一种写法 -->
            <!-- <RouterLink :to="`/b/detail/${item.content}`">{{
              item.title
            }}</RouterLink> -->

            <!-- 第二种写法 -->
            <RouterLink
              :to="{
                name: 'xiangqing', // 必须使用路由的 name 属性
                params: {
                  content: item.content,
                },
              }"
              >{{ item.title }}</RouterLink
            >
          </h4>
        </li>
      </ul>
    </div>
    <div class="content">
      <RouterView />
    </div>
  </div>
</template>

<script setup>
import { reactive } from "vue";
import { RouterView, RouterLink } from "vue-router";

const news = reactive([
  {
    id: 1,
    title: "新闻标题01",
    content: "新闻内容01",
  },
  {
    id: 2,
    title: "新闻标题02",
    content: "新闻内容02",
  },
  {
    id: 3,
    title: "新闻标题03",
    content: "新闻内容03",
  },
]);
</script>

<style lang="scss" scoped>
.p {
  display: flex;
  height: 100%;

  .menu {
    width: 30%;
  }

  .content {
    border: 4px #c00000 solid;
    border-radius: 10px;
    height: 90%;
    width: 70%;
    margin: 10px;
  }
}
</style>
<!--接受页面-->
<template>
  <h3>新闻详情</h3>
  <h4>{{ route.params.content }}</h4>
</template>

<script setup>
import { useRoute } from "vue-router";

// 接受路由传递的参数
const route = useRoute();
</script>

<style lang="scss" scoped></style>

10、路由的 props 配置

  • 作用:让路由组件更方便的收到参数(可以将路由参数作为 props 传给组件)
// 创建一个路由器,并暴露出去

// 第一步:引入 createRouter
import { createRouter, createWebHashHistory } from "vue-router";

// 第二步:创建路由器
// router :路由器
// route :路由
// routes :多个路由
const router = createRouter({
  history: createWebHashHistory(), // 路由器的工作模式
  routes: [
    {
      path: "/",
      redirect: "/a",
    },
    {
      path: "/a",
      component: () => import("@/views/A.vue"),
    },
    {
      name: "new",
      path: "/b",
      component: () => import("@/views/B.vue"),
      children: [
        // 嵌套路由
        {
          name: "xiangqing",
          path: "detail/:content?", // 占位,可传可不传
          component: () => import("@/views/NewsDatails.vue"),
          // 第一种写法:将路由收到的所有 params 参数作为 props 传给路由组件
          // props: true,

          // 第二种写法:函数写法,可以自己决定将什么作为 props 给路由组件
          props(route) {
            return route.query;
          },

          // 第三种写法:对象写法,可以自己决定将什么作为 props 给路由组件
          // props: {
          //   a: 100,
          //   b: 200,
          //   c: 300,
          // },
        },
      ],
    },
    {
      name: "about",
      path: "/c",
      component: () => import("@/views/C.vue"),
    },
  ],
});

export default router;

11、replace 属性

  • 1、作用:控制路由跳转时操作浏览器历史记录的模式
  • 2、浏览器的历史记录有两种写入方式:分别为 pushreplace
    • push 是追加历史记录(默认值)
    • replace 是替换当前记录
  • 3、开启 replace 模式:
<RouterLink replace ......>News</RouterLink>

12、编程式导航

  • 路由组件的两个重要的属性: $route$router 变成了两个 hooks
  • 编程式路由导航就是脱离 <RouterLink> 实现路由跳转
  • 简单例子,代码如下:
// 创建一个路由器,并暴露出去
// 第一步:引入 createRouter
import { createRouter, createWebHashHistory } from "vue-router";

// 第二步:创建路由器
// router :路由器
// route :路由
// routes :多个路由
const router = createRouter({
  history: createWebHashHistory(), // 路由器的工作模式
  routes: [
    {
      path: "/",
      redirect: "/a",
    },
    {
      path: "/a",
      component: () => import("@/views/A.vue"),
    },
    {
      name: "new",
      path: "/b",
      component: () => import("@/views/B.vue"),
      children: [
        // 嵌套路由
        {
          name: "xiangqing",
          path: "detail", // 占位,可传可不传
          component: () => import("@/views/NewsDatails.vue"),
          // 第一种写法:将路由收到的所有 params 参数作为 props 传给路由组件
          // props: true,

          // 第二种写法:函数写法,可以自己决定将什么作为 props 给路由组件
          props(route) {
            return route.query;
          },

          // 第三种写法:对象写法,可以自己决定将什么作为 props 给路由组件
          // props: {
          //   a: 100,
          //   b: 200,
          //   c: 300,
          // },
        },
      ],
    },
    {
      name: "about",
      path: "/c",
      component: () => import("@/views/C.vue"),
    },
  ],
});

export default router;
  • 复杂编程式路由导航例子
<template>
  <div class="p">
    <div class="menu">
      <h3>新闻列表</h3>
      <ul>
        <li v-for="item in news" :key="item.id">
          <h4>
            <RouterLink
              :to="{
                name: 'xiangqing', // 必须使用路由的 name 属性
                query: {
                  content: item.content,
                },
              }"
              >{{ item.title }}</RouterLink
            >
            <button @click="detailHandle(item.content)">查看详情</button>
          </h4>
        </li>
      </ul>
    </div>
    <div class="content">
      <RouterView />
    </div>
  </div>
</template>

<script setup lang="ts">
import { reactive } from "vue";
import { RouterView, RouterLink, useRouter } from "vue-router";

const router = useRouter();

const news = reactive([
  {
    id: 1,
    title: "新闻标题01",
    content: "新闻内容01",
  },
  {
    id: 2,
    title: "新闻标题02",
    content: "新闻内容02",
  },
  {
    id: 3,
    title: "新闻标题03",
    content: "新闻内容03",
  },
]);

/**
 * 查看详情方法
 * 编程式导航
 */
interface NewsInder {
  content: string;
}

const detailHandle = (content: NewsInder) => {
  router.push({
    name: "xiangqing", // 必须使用路由的 name 属性
    query: {
      content: content,
    },
  });
};
</script>

<style lang="scss" scoped>
.p {
  display: flex;
  height: 100%;

  .menu {
    width: 30%;
  }

  .content {
    border: 4px #c00000 solid;
    border-radius: 10px;
    height: 90%;
    width: 70%;
    margin: 10px;
  }
}
</style>

13、重定向

{
      path: "/",
      redirect: "/a",
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

W.Y.B.G

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值