• vue3 快速入门系列 —— vue3 路由


    vue3 快速入门系列 - vue3 路由

    vue3 基础上加入路由。

    vue3 需要使用 vue-router V4,相对于 v3,大部分的 Vue Router API 都没有变化。

    Tip:不了解路由的同学可以看一下笔者之前的文章:vue2 路由

    参考:vue2 路由官网vue3 路由官网

    vue-router V4

    在 Vue Router API 从 v3(Vue2)到 v4(Vue3)的重写过程中,大部分的 Vue Router API 都没有变化,但是在迁移你的程序时,你可能会遇到一些破坏性的变化 —— 从 Vue2 迁移

    vue3 需要使用 vue-router 4.x.x 版本。安装:

    PS hello_vue3> npm i vue-router
    
    changed 37 packages, and audited 69 packages in 3s
    
    8 packages are looking for funding
      run `npm fund` for details
    
    1 moderate severity vulnerability
    
    To address all issues, run:
      npm audit fix
    
    Run `npm audit` for details.
    

    版本:

    "dependencies": {
        "vue": "^3.4.15",
        "vue-router": "^4.3.0"
      },
    

    第一个示例

    在vue3项目中加入路由。

    步骤如下:

    • 创建路由 src/router/index.ts
    import { createRouter, createWebHistory } from 'vue-router'
    import Home from '@/views/Home.vue'
    import About from '@/views/About.vue'
    
    const routes = [
      { path: '/', component: Home },
      { path: '/about', component: About }
    ]
    
    // new Router 变成 createRouter
    const router = createRouter({
      // mode: 'history' 配置已经被一个更灵活的 history 配置所取代
      // 必填。否则报错:Uncaught Error: Provide the "history" option when calling "createRouter()"
      history: createWebHistory(),
      routes
    })
    
    export default router
    

    Tip:new Router 变成 createRouter 来创建路由;其中模式需要通过调用方法创建,必填

    • 创建两个组件
    
    
    
    
    • App.vue 中引入 告诉 Vue Router 在哪里渲染匹配到的组件。
    
    
    <script lang="ts" setup name="App">
    
    script>
    
    • main.ts 通过 use 使用路由
    import {createApp} from 'vue'
    import App from './App.vue'
    // 会自动加载 ./router/index.ts
    import router from './router'
    
    createApp(App)
    // 将 Vue Router 插件安装到 Vue 实例中,以便在整个应用程序中使用 Vue Router 的功能
    // Vue.use(MyPlugin) - 调用 `MyPlugin.install(Vue)`
    .use(router)
    .mount('#app')
    

    接着就可以通过浏览器体验:

    Home
    // 点击,调整到 about 路由
    to About
    
    About
    // 点击,调整到 home 路由
    to Home
    

    Tip: 通过 .use(router) 在 vue 开发者工具中就会看到路由tab

    命名路由

    Tip: vue2 路由 -> 命名路由

    路径有时太麻烦,可以使用命名路由替代。

    例如将 About 从路径改为名称跳转。核心代码如下:

    // 定义 name
    { path: '/about', component: About, name: 'guanyu' },
    
    // 跳转
    :to="{name: 'guangyu'}"
    

    Tip:to 目前有2种写法,感觉字符串方式很痛快,对象还需要写好多,但是到子路由或传递参数,会发现还是对象好用。

    // 传递字符串 - 理解为目标路由的路径
    to="/"
    // 传递对象
    :to="{path: '/'}"
    :to="{name: 'guangyu'}"
    

    嵌套路由

    Tip:和 vue2 中路由用法相同,详情请看:vue2 路由 -> 嵌套路由

    新建一个 Article 组件,里面定义一个 router-view。请看示例:

    • Article.vue
    
    
    
    

    Tip:可以不引入 import {RouterView,RouterLink} from 'vue-router'

    • Detail.vue
    
    
    • 增加路由和子路由。子路由的 path 无需增加 /
    const routes = [
      { path: '/home', component: Home,},
      {
        path: '/article',
        component: Article,
        children: [
          {
            path: 'detail',
            component: Detail
          }
        ]
      },
    ]
    
    • Home.vue 增加Article入口
    "{name: 'guanyu'}">About
    
    <router-link :to="{path: '/article'}">Articlerouter-link>

    测试:进入Home,点击 Article,点击 文章 id1 详情,显示 文章id: 1,测试通过。

    路由 query 参数

    在”嵌套路由“中我们是这样取得 query 参数:

    文章id: {{ $route.query.id }}

    js 中通过 useRoute hooks 取得 $route。请看示例:

    
    
    <script lang="ts" setup name="App">
    import {toRefs} from 'vue'
    // 返回当前的路由地址。相当于在模板中使用 $route。
    // useRouter 返回路由器实例。相当于在模板中使用 $router
    import {useRoute} from 'vue-router'
    
    const route = useRoute()
    
    // route: Proxy
    console.log('route: ', route);
    
    // 错误:解构需要用到 toRefs,否则页面不会更新
    // const {query} = route
    
    // 正确:解构
    const {query} = toRefs(route)
    
    script>
    

    Tip:如果需要解构,需使用 toRefs。若想将 query.id 中的 query 去掉,可以使用后面章节的 路由 props 属性,代码将更优雅

    路由 params 参数

    Tip:请看 vue2 路由 -> $route.params

    将上节 query 参数示例改成 params。

    • params需要增加占位符,比如:id
    {
        path: '/article',
        component: Article,
        children: [
          {
            name: 'xiangxi',
            path: 'detail/:id',
            component: Detail
          }
        ]
    },
    
    • id传递方式调整一下,不用 query 那种方式:
    "/article/detail/4">文章 id4 详情
    • 接收 id

    文章id: {{ $route.params.id }}

    :params 不能传数组或对象;/a/:b/:c,则你必须传 /a/1/2,如果传 /a/1 则报错,如果有时没有c 可传,可以改成 /a/:b/:c?

    对象形式

    将 to 改成对象形式:

     "{
        path: '/article/detail/4',
        params: {
            id: 5
        }
    }">文章 id5 详情

    浏览器报错更容易理解,说 path 被忽略:

    // vscode 报错:
    对象字面量只能指定已知属性,并且“params”不在类型“RouteLocationPathRaw”中。
    
    // 浏览器报错
    [Vue Router warn]: Path "/article/detail/4" was passed with params but they will be ignored. Use a named route alongside params instead.
    

    将 path 改成 name即可:

    "{
        // path: '/article/detail/4',
        name: 'xiangxi',
        params: {
            id: 5
        }
    }">文章 id5 详情

    路由 props 属性

    不就是想接收 params 或 query 传来的参数的,还得写这么一大块代码,太麻烦:

    
    
    <script lang="ts" setup name="App">
    import {toRefs} from 'vue'
    import {useRoute} from 'vue-router'
    
    const route = useRoute()
    const {query} = toRefs(route)
    script>
    

    可以通过 props 解决。细节如下:

    props 布尔

    • 定义 props
    {
        name: 'xiangxi',
        path: 'detail/:id',
        component: Detail,
        // 通过 props 属性来将路由参数传递给组件
        // 底层好些这样:
        props: true
    }
    
    • 直接通过 defineProps 接收
    
    
    <script lang="ts" setup name="App">
        defineProps(['id'])
    script>
    

    props 函数

    如果需要接收 query,需要用 props 函数,参数是 route,返回需要接收的对象:

    // RouteLocationNormalized 是 Vue Router 中的一个类型,它用于描述路由的位置信息
    import { type RouteLocationNormalized } from 'vue-router';
    
    {
        name: 'xiangxi',
        path: 'detail',
        component: Detail,
        // 通过 props 属性来将路由参数传递给组件
        // props: true
        props(route: RouteLocationNormalized ) {
            return route.query
        }
    }
    
    • 触发路由从 params 改成 query:
    "{
        name: 'xiangxi',
        query: {
            id: 5
        }
    }">文章 id5 详情
    • 接收方式不变:
    
    
    <script lang="ts" setup name="App">
        defineProps(['id'])
    script>
    

    Tip:其实 props: true 就相当于下面这段代码:

    props(route: RouteLocationNormalized ) {
        return route.params
    }
    

    props 对象

    props 还可以写成对象,但用得较少:

    props: {
        id: 100
    }
    

    replace

    HTML5的历史API包含了pushState(),replaceState()和popstate事件

    路由默认是 push。比如启动第一个示例,未点击 home 或 about 导航时,浏览器左上方既不能前进也不能后退,因为栈中只有当前页面,指针没地方去。在你点击home和about导航后,就可以前进和后退,即使刷新页面,这个历史记录也不会变。

    "{name: 'guanyu'}">About
    
    <router-link :to="{path: '/article'}">Articlerouter-link>

    vue-router 的 replace 作用和用法和 react replace 相同。

    现在点 About 就会直接替换

    "{name: 'guanyu'}">About
    

    编程式导航

    Tipvue2 路由 -> 编程式导航

    三秒后跳转到 article:

    
    

    编程式导航使用频率大于声明式导航(

    to也支持对象,和声明式导航用法相同,更多介绍请看:vuer-router v4 编程式导航

    其他

    路由组件和一般组件

    路由组件通常放在 pages 或 views 文件夹中,一般组件通常放在 components 文件夹中 —— 一般开源的项目都会这样分类

    看一个组件是哪种,需要看其如何用。比如定义一个 Demo.vue,如果通过标签 这种写法来使用,就属于一般组件,如果该组件通过路由渲染,则称为路由组件。

    卸载和挂载

    通过导航,视觉上消失的路由组件,默认被卸载,需要用的时候在挂载。

    第一个示例 中给 About.vue 增加两个生命周期钩子,再次切换 Home 和 About 组件,就能看到效果:

    
    
    <script lang="ts" setup name="App">
    import {onMounted, onUnmounted} from 'vue'
    onMounted(() => {
      console.log('About 挂载了');
    })
    onUnmounted(() => {
      console.log('About 卸载了');
    })
    script>
    

    路由模式

    history 模式 url 美观,后期上线,需要服务端配合处理路径问题,否则刷新会有404。当用户在浏览器中直接访问一个路由,或者刷新页面时,如果服务器端没有正确配置,可能会导致 404 错误,因为此时服务器会尝试去寻找对应的文件或路由路径,而实际上这个路径是由前端控制的,并不一定存在于服务器端的文件系统中。为了解决这个问题,你需要在服务器端配置一个通配符路由,将所有的路由请求都指向你的应用的入口文件(比如 index.html),这样就会确保 Vue Router 能够正确地处理路由请求。

    如果你使用的是 Node.js 服务器,可以使用 Express 框架来进行配置,示例代码如下所示:

    const express = require('express');
    const path = require('path');
    const app = express();
    
    // 静态资源目录,例如你的 CSS、JavaScript 文件等
    app.use(express.static(path.join(__dirname, 'public')));
    
    // 通配符路由,将所有的路由请求都指向 index.html
    app.get('*', (req, res) => {
      res.sendFile(path.join(__dirname, 'public', 'index.html'));
    });
    
    // 启动服务器,监听端口
    const port = process.env.PORT || 3000;
    app.listen(port, () => {
      console.log(`Server is running on port ${port}`);
    });
    

    这样配置后,无论用户访问哪个路由,服务器都会返回 index.html,然后 Vue Router 就可以根据路由配置来正确地渲染相应的组件,避免了刷新页面时出现的 404 错误。

    Hash 模式在 SEO 优化方面相对较差。

    • 比如不利于搜索引擎爬虫:Hash 模式下,URL 中的哈希部分(#后面的内容)不会被包含在 HTTP 请求中,因此在服务器接收请求时,哈希部分对于服务器来说是不可见的。这意味着搜索引擎爬虫无法直接获取到 URL 中的实际内容,因为爬虫主要是通过 HTTP 请求获取页面内容的,所以无法获取到 hash 后面的内容,这样就会导致搜索引擎无法正确地索引和解析页面。

    虽然使用 history 模式相对于 hash 模式在 SEO 优化方面有所改善,但它仍然是单页应用(SPA),可以和服务端渲染结合

    没有匹配到指定的路径 /

    配置如下路由,第一次打开,浏览器控制台有警告:main.ts:9 [Vue Router warn]: No match found for location with path "/"

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

    可以通过重定向解决。就像这样:

    const routes = [
      { path: '/', redirect: '/home'},
      { path: '/home', component: Home,},
    
  • 相关阅读:
    C++前缀和算法应用:和至少为 K 的最短子数组的原理、源码及测试用例
    投资理财基础知识分享(二)
    基于Python的51job的招聘信息可视化分析系统的设计与实现
    [免费专栏] Android安全之绕过直连、HOST校验、系统证书校验、代理检测、双向认证抓HTTPS数据
    综合指南:如何确定 Java 线程池大小
    SpringCloud
    VR家居为什么盛行?可以解决哪些传统家居的痛点?
    JavaEE初阶——计算机是如何工作的
    platform总线驱动
    十五、异常(6)
  • 原文地址:https://www.cnblogs.com/pengjiali/p/18123646