路由

路由

参考地址:https://router.vuejs.org/zh/

​ Vue实质上是一个 SPA(单Web应用程序) 应用,也就是实质上其实只有一张页面。所以我们使用route进行切换。

基本构成:

​ 1、导航区、展示区

​ 2、路由器

​ 3、制定路由的具体规则(什么路径,对应着什么组件)

​ 4、形成 一个一个的 xxx.vue 文件

​ 5、告诉路由把命中的组件放在哪里:RouterView

​ 6、不要通过直接在浏览器输入路由,通过:RouterLink

基本的切换效果

1、安装路由
npm install vue-router
2、创建路由器并暴露

对应位置:src/router/index.ts

//### 创建一个路由器,并暴露出去 ###
import { createRouter, createWebHashHistory } from "vue-router";  //引入createRouter
//以下是需要呈现的组件
import Home from "@/components/Home.vue";
import About from "@/components/About.vue";
import News from "@/components/News.vue";

//创建路由器
const router = createRouter({
  history: createWebHashHistory(),  //路由器的工作模式
  routes: [ //一个一个的路由规则
    {
      path: '/home',
      component: Home
    },
    {
      path: '/about',
      component: About
    },
    {
      path: '/news',
      component: News
    }
  ]
})

export default router;  //暴露出去router
3、创建对应的路由组件

4、创建了路由器实例,并将其注册为插件

位于:/src/main.ts

// 引入createApp用于创建应用
import { createApp } from "vue";
// 引入App根组件
import App from "./App.vue";
// 引入路由器
import router from "./router";

const app = createApp(App);

app.use(router);

app.mount("#app");
5、设置对应显示的位置
    <div class="main-content">
      <!-- 呈现对应组件 -->
      <RouterView></RouterView>
    </div>
6、点击后进行路由切换

​ 这样就不用手动输入路由路径了,当然这里还通过属性设置了选中后的样式。

    <!-- 导航区 -->
    <div class="navigate">
      <RouterLink to="/home" active-class="active">首页</RouterLink>
      <RouterLink to="/news" active-class="active">新闻</RouterLink>
      <RouterLink to="/about" active-class="active">关于</RouterLink>
    </div>

路由组件放置位置与切换后卸载组件

为了区分路由组件和一般组件,路由组件通常存放在pagesviews文件夹,一般组件通常存放在components文件夹。

​ 通过点击导航,视觉效果上“消失” 了的路由组件,默认是被卸载掉的,需要的时候再去挂载。编写对应生命周期即可查看。

to的两种写法

<!-- 第一种:to的字符串写法 -->
<RouterLink to="/home" active-class="active">首页</RouterLink>

<!-- 第二种:to的对象写法 -->
<RouterLink :to="{path: '/about'}" active-class="active">关于</RouterLink>>	<!-- 通过路由 -->
<RouterLink :to="{name: 'news'}" active-class="active">新闻</RouterLink>     <!-- 通过命名 -->

路由的工作模式

history模式

写法:

​ Vue2:mode:'hsitory'

​ Vue3: history:createWebHistory()

​ React: BrowserRouter

优点:URL更加美观,不带有#,更接近传统的网站URL

缺点:后期项目上线,需要服务端配合处理路径问题,否则刷新会有404错误。

参考代码:

const router = createRouter({
	history:createWebHistory(), //history模式
	/******/
})

补充(因为hash模式不会把#后面的路径给到对应服务端所以用特殊处理,因为SPA):

# 参考nginx简单处理方案
location / {
  try_files $uri $uri/ /index.html;
}
hash模式

优点:兼容性更好,因为不需要服务器端处理路径。

缺点:URL带有#不太美观,且在SEO(搜索引擎优化)优化方面相对较差。

参考代码:

const router = createRouter({
	history:createWebHashHistory(), //hash模式
	/******/
})

命名路由

作用:可以简化路由跳转及传参(后面就讲)。

给路由规则命名:

  routes: [ //一个一个的路由规则
    {
      name:'home',
      path: '/home',
      component: Home
    },
    {
      name:'about',
      path: '/about',
      component: About
    },
    {
      name:'news',
      path: '/news',
      component: News
    }
  ]
<!-- 命名后,对象写法就可以通过命名来,如/news/xxx路由也可以简化命名书写 -->
<RouterLink :to="{name: 'news'}" active-class="active">新闻</RouterLink>     <!-- 通过命名 -->

嵌套路由

​ 这里步骤中不再包含一些必要的如安装路由,use到App的操作了。

编写嵌套路由
  routes: [ //一个一个的路由规则
    {
      name:'home',
      path: '/home',
      component: Home
    },
    {
      name:'about',
      path: '/about',
      component: About
    },
    {
      name:'news',
      path: '/news',
      component: News,
      children: [
        {
          path: 'detail',  //子级前面不用加/
          component: Detail
        }
      ]
    }
  ]
编写对应路由组件
<template>
  <ul class="news-list">
    <li>编号:xxx</li>
    <li>标题:xxx</li>
    <li>内容:xxx</li>
  </ul>
</template>

<script setup lang="ts" name="Detail">
</script>


<style scoped>
  .news-list {
    list-style: none;
    padding-left: 20px;
  }

  .news-list>li {
    line-height: 30px;
  }
</style>
使用
<template>
  <div class="news">
    <!-- 导航区 -->
    <ul>
      <li v-for="news in newsList" :key="news.id">
        <RouterLink to="/news/detail"> {{ news.content }} </RouterLink>
        <!-- <RouterLink :to="{path: '/news/detail'}"> {{ news.content }} </RouterLink> -->        
      </li>
    </ul>
    <!-- 展示区 -->
    <div class="news-content">
      <RouterView></RouterView>
    </div>
  </div>
</template>

<script setup lang="ts" name="News">
  import {reactive} from 'vue'
  import {RouterView, RouterLink} from 'vue-router'

  const newsList = reactive([
    {id:'asfdtrfay01',title:'很好的抗癌食物',content:'西蓝花'},
    {id:'asfdtrfay02',title:'如何一夜暴富',content:'学IT'},
    {id:'asfdtrfay03',title:'震惊,万万没想到',content:'明天是周一'},
    {id:'asfdtrfay04',title:'好消息!好消息!',content:'快过年了'}
  ])
</script>

<style scoped>
/* 新闻 */
.news {
  padding: 0 20px;
  display: flex;
  justify-content: space-between;
  height: 100%;
}
.news ul {
  margin-top: 30px;
  /* list-style: none; */
  padding-left: 10px;
}
.news li::marker {
  color: #64967E;
}
.news li>a {
  font-size: 18px;
  line-height: 40px;
  text-decoration: none;
  color: #64967E;
  text-shadow: 0 0 1px rgb(0, 84, 0);
}
.news-content {
  width: 70%;
  height: 90%;
  border: 1px solid;
  margin-top: 20px;
  border-radius: 10px;
}
</style>

路由传参(重点)

query参数

1、在导航区点击时通过query传递参数:

    <!-- 导航区 -->
    <ul>
      <li v-for="news in newsList" :key="news.id">
        <!-- 第一种写法: -->
        <!-- <RouterLink :to="`/news/detail?id=${news.id}&title=${news.title}&content=${news.content}`"> {{ news.title }} </RouterLink> -->

        <!-- 第二种写法 -->
        <RouterLink 
          :to="{
            name: 'detail',
            query: {
              id: news.id,
              title: news.title,
              content: news.content
            }
          }"
        >
          {{ news.title }} 
        </RouterLink>
      </li>
    </ul>

2、对应的路由组件接收参数

<script setup lang="ts" name="Detail">
  import { useRoute } from 'vue-router';  // 从命名中可以看出 这是已给hooks
  import { toRefs } from 'vue';

  let router = useRoute();
  // console.log('查看', router);
  let { query } = toRefs(router); //从响应式中解构属性会失去响应式
  console.log('查看是否为响应式:', query);
</script>
params参数

1、先配置路由

  routes: [ //一个一个的路由规则
    {
      name:'home',
      path: '/home',
      component: Home
    },
    {
      name:'about',
      path: '/about',
      component: About
    },
    {
      name:'news',
      path: '/news',
      component: News,
      children: [
        {
          name: 'detail',
          path: 'detail/:id/:title/:content?',  //子级前面不用加 ? 表示可传可不传
          component: Detail
        }
      ]
    }
  ]

2、在导航区点击时通过params传递参数:

    <ul>
      <li v-for="news in newsList" :key="news.id">
        <!-- 第一种写法: -->
        <!-- <RouterLink :to="`/news/detail/${news.id}/${news.title}/${news.content}`"> {{ news.title }} </RouterLink> -->

        <!-- 第二种写法 -->
        <RouterLink 
          :to="{
            name: 'detail', //必须使用name
            params: { //参数不能是对象和数组
              id:news.id,
              title:news.title,
              content:news.content,
            }
          }"
        > 
          {{ news.title }} 
        </RouterLink>
      </li>
    </ul>

3、接收参数

<script setup lang="ts" name="Detail">
  import { useRoute } from 'vue-router';
  import { toRefs } from 'vue';

  const route = useRoute();
  // console.log(route);
  let { params } =  toRefs(route);
  console.log(params);
</script>
注意事项

​ 备注1:传递params参数时,若使用to的对象写法,必须使用name配置项,不能用path

​ 备注2:传递params参数时,需要提前在规则中占位。

​ 备注3:传递params参数时,不能传递对象或数组参数。

路由_props配置

​ 作用:让路由组件更方便的收到参数(可以将路由参数作为props传给组件),这样可以简化接收位置的书写,只是需要注意三种写法,第一种适用于写了params的方式,第二种query和params都可以,第三种写的较死。

参考代码:

	children: [
        {
          name: 'detail',
          path: 'detail/:id/:title/:content?',  //子级前面不用加 ? 表示可传可不传
          component: Detail,
          //### 第一种写法:将路由收到的所有params参数作为props传给路由组件
          // props: true         //从<Detail>  --> <Detail id = ?? title = ?? content = ??>

          //### 第二种写法:函数写法,可以自己决定将什么作为props给路由组件
          // props(arg) {  //这个参数就是路由参数,可以获取params或者query,一般用于处理query,毕竟params有上面的写法
          //   return arg.params;
          // }

          //### 第三种写法:对象写法,可以自己决定将什么作为props给路由组件
          props: {  //有点写死了
            a: 100,
            b: 200,
            c: 300
          }
        }
      ]
推荐

​ 1、使用query参数的时候用第二种写法

          props(arg) {
             return arg.query;
          }

​ 2、使用params参数的时候用第一种写法

        {
          name: 'detail',
          path: 'detail/:id/:title/:content?',  //子级前面不用加 ? 表示可传可不传
          component: Detail,
          props: true
        }

​ 3、第三种写法可以用于一些较为固定的地方

        {
          name: 'detail',
          path: 'detail/:id/:title/:content?',  //子级前面不用加 ? 表示可传可不传
          component: Detail,         
          props: {  //有点写死了
            a: 100,
            b: 200,
            c: 300
          }
        }

replace属性

​ 作用:控制路由跳转时操作浏览器历史记录的模式。

​ 浏览器的历史记录有两种写入方式:分别为pushreplace

push是追加历史记录(默认值)。

replace是替换当前记录。

开启replace模式(在对应的 RouterLink 中加上属性后就可以设置,然后点击这个后就无法使用浏览器回退):

      <RouterLink replace .......>...</RouterLink>

​ 使用编程式路由导航,我们可以脱离 RouterLink进行路由跳转,无论是点击按钮、鼠标滑过、定时跳转如跳到秒杀页面等场景都可以使用。关键在于:学了to,我们通过获取路由器进行跳转中如使用 push 的方式也可以接受字符串或者对象,所以可以直接用to写法的格式

参考代码:

  function showNewsDetail(news:NewsInter) { //可以写 :any 跳过检查
    //### 这里push可以接收的对象是字符串 或者 对象,所以可以直接使用to的写法
    router.push({ //这里也可以使用一个 replace 就不能使用浏览器回退了
      name: 'detail', //必须使用name
      params: { //参数不能是对象和数组
        id:news.id,
        title:news.title,
        content:news.content,
      }
    });
  }

路由_重定向

​ 如做初始跳转:

    {
      path:'/',
      redirect: '/home'
    }
posted @ 2024-12-24 09:54  如此而已~~~  阅读(40)  评论(0)    收藏  举报
//雪花飘落效果