前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >前端路由工作原理与使用

前端路由工作原理与使用

原创
作者头像
CRMEB商城源码
发布2022-05-19 12:10:18
2K0
发布2022-05-19 12:10:18
举报
文章被收录于专栏:crmeb

单页应用和多页应用

单页面应用:所有功能在一个页面上实现

  • 一个.html 文件
  • 前端路由
  • 组件化开发

网易云音乐 小米移动端 多页应用:与单页应用相对应的,不同的功能通过不同的页面来实现

单页面 - 多页面对比

对比部分

单页应用(最流行)

多页面应用(传统方式)

页面组成

一个 html 文件多个组件组成

多个 html 文件

静态资源共用

共用,一次性加载完毕,借助 ssr 优化

不共用,每个页面都加载一遍

刷新方式

页面局部刷新

整页加载

url 模式

itcast.com/#/pageone

itcast.com/pageone.html

用户体验

用户体验良好

页面切换加载缓慢体验较差

数据传递

容易

依赖 url 传参,cookie,localStorage

搜索引擎优化

不利于 seo 优化,需要 ssr(服务器端渲染)优化

支持良好

使用场景

追求高体验 不要求 seo

高度要求 seo

开发成本

较高 需要依赖专业的框架,开发效率高

较低 重复代码多,开发效率低

路由

vue 路由官网

路由理解的概念

路由:就是一一对应关系的集合

前端路由(单页应用程序): 一个 url 地址,对应哪个组件 后端路由:一个接口地址,对应哪一段接口地址

前端路由

后端路由

前端路由工作原理

前端路由的本质,对 url 的 hash 值进行改变和监听,切换对应页面组件的 dom 结构

分析

根据地址栏变化(不重新向服务器发请求),去局部更新不同的页面内容,完成前端业务场景切换

思路

  1. URL 地址栏中的 Hash 值发生了变化
  2. 前端 js 监听了到 Hash 地址的变化 window.onhashchange=()=>{}
  3. 前端 js 把当前 Hash 地址对应的组件渲染都浏览器中

前端路由简单实现

1 . src/views/ 创建并在 App.vue 里导入和注册组件 MyHome.vue MyMovie.vue MyAbout.vue

代码语言:javascript
复制
<script>
import MyAbout from './views/my-about.vue'
import MyHome from './views/my-home.vue'
import MyMovie from './views/my-movie.vue'
export default {
  components: {
    MyHome,
    MyAbout,
    MyMovie
  }
}
</script>
复制代码
  1. 通过动态组件,控制要显示的组件
代码语言:javascript
复制
<template>
  <div>
    <h1>App组件</h1>
    <component :is="comName"></component>
  </div>
</template>
​
<script>
export default {
  // ...省略其他
  data () {
    return {
      comName: 'MyHome'
    }
  }
}
</script>
复制代码
  1. 声明三个导航链接,点击时修改地址栏的 hash 值
代码语言:javascript
复制
<template>
  <div>
    <h1>App组件</h1>
    <a href="#/home">首页</a>&nbsp;
    <a href="#/movie">电影</a>&nbsp;
    <a href="#/about">关于</a>&nbsp;
    <component :is="comName"></component>
  </div>
</template>
复制代码
  1. 在 created 中,监视地址栏 hash 时的变化,一旦变化,动态切换展示的组件
代码语言:javascript
复制
created () {
  window.onhashchange = () => {
    switch(location.hash) {
      case '#/home':
        this.comName = 'my-home'
        break
      case '#/movie':
        this.comName = 'my-movie'
        break
      case '#/about':
        this.comName = 'my-about'
        break
    }
  }
},
复制代码

小结

改变浏览器 url 的 hash 值,JS 监听到 hash 值改变,把对应的组件显示到同一个挂载点

路由 - 官方路由基本使用

vue-router 文档

说明⚠️:如果使用 vue-cli 创建项目,没有选择路由插件,需要单独安装和配置

步骤

  1. 安装包
  2. 配置路由
  3. 使用路由

操作

  1. 安装 npm i vue-router@3.5.3
  2. 创建路由文件

router/index.js

代码语言:javascript
复制
// 导入路由插件
import VueRouter from 'vue-router'
import Vue from 'vue'
​
// 使用插件 - 重要
Vue.use(VueRouter)
​
// 导入组件
​
import Page1 from './Page1.vue'
import Page2 from './Page2.vue'
import Page3 from './Page3.vue'
​
​
// 创建路由规则
const router = new VueRouter({
  routes: [
    {
      path: "/page1", // 当浏览器访问 http://localhost:8080/#/page1时,
      component: Page1  // 装入组件 Page1
    },
    {
      path: "/page2",
      component: Page2
    },
    {
      path: "/page3",
      component: Page3
    }
  ]
})
​
export default router
复制代码
  1. 使用路由 在 main.js 中
代码语言:javascript
复制
import router from './router/index.js'
​
new Vue({
  router: router, // 使用路由
  render: h => h(App),
}).$mount('#app')
​
复制代码

使用路由

代码语言:javascript
复制
<router-view></router-view>
复制代码

测试

在地址栏中输入地址来访问

图示

小结

下载路由模块,编写对应规则注入到 vue 实例上,使用 router-view 挂载点显示切换的路由

链接导航 - router-link

掌握 router-link 的用法

Router-link 组件介绍

作用: 用于提供路由链接,实现页面跳转 格式: <router-link to="/home">首页</router-link> 要点:

  • 是 vue-router 提供的组件
  • router-link 最终会渲染成 a 链接
  • router-link 自带链接导航高亮的功能

示例

代码语言:javascript
复制
<template>
  <div>
    <h1>App组件</h1>
    <ul>
      <li><router-link to="/home">首页</router-link></li>
      <li><router-link to="/movie">电影</router-link></li>
      <li><router-link to="/about">关于</router-link></li>
    </ul>
    <router-view></router-view>
  </div>
</template>
复制代码

激活类名

router-link-exact-active router-link-active

小结

链接导航,用 router-link 配合 to, 实现点击切换路由

  • router-link 组件会被 vue 解析成 a 标签,但不能直接通过 a 标签来跳转。
  • 如果当前路由被激活会添加特殊的类名:

页面跳转传参

掌握跳转传参的方式

回顾

html 页面之间如何传参? =》url?key=val&key=val

vue 路由传参的方式

两种方式: 1.query 传参。 适用场景:页面搜索 2.params 传参。 适用场景:详情页

  1. 创建 components/MyGoods.vue - 准备接收路由上传递的参数和值
代码语言:javascript
复制
<div>
    你要浏览的商品是: {{ $route.query.name }} {{ $route.params.goodsId}}
</div>
复制代码
  1. 路由定义
代码语言:javascript
复制
{
    path: "/goods",
    component: MyGoods
  },
  {
    path: "/goods/:goodsId",
    component: MyGoods
  },
复制代码
  1. 导航跳转,传值给 MyGoods.vue 组件
代码语言:javascript
复制
<li><router-link to="/goods?name=外套">外套</router-link></li>
<li><router-link to="/goods/123">详情</router-link></li>
复制代码

图示 - 查询字符串

图示 - params 传参

小结

?key=value =》  用 route.query.key 取值 / 值−需要提前在路由规则 /path/:key=》 用 route.query.key 取值 / 值 - 需要提前在路由规则 /path/:key =》  用 route.query.key 取值 / 值−需要提前在路由规则 /path/:key=》 用 route.params.key  取值

路由 - 重定向

掌握路由重定向的用法

理解

重定向, 用户访问的是 A 地址,系统把它切换到 B 地址。

应用场景:改变默认访问页面的行为

示例

router/index.js - 修改配置

代码语言:javascript
复制
const routes = [
  {
    path: "/",
    redirect: "/home" // 重定向
  }
]
复制代码

路由 404

统一处理异常地址:那些个正常配置的地址之外的地址。

代码

修改路由规则即可:

通过通配符 *,设置 404 页面

代码语言:javascript
复制
import NotFound from "@/components/NotFound";

const routes = [
  {
    path: "/",
    redirect: "/home" // 重定向
  },
  
  // ...正常路由
  
  { // 当上面路由都不匹配, 匹配这个通配符, 显示NotFound页面
    path: "*",
    component: NotFound
  }
]
复制代码

编程式导航

掌握编程式导航的使用。

编程式导航

编程式: 写代码 导航:页面跳转

编程式导航 ====> 写代码的方式来让页面跳转

API

代码语言:javascript
复制
// 跳转页面不传参
this.$router.push('/路由路径')
this.$router.push({path: '路由路径'})
this.$router.push({name: '路由名称'})

// 跳转并query传参-方式1
this.$router.push("/路由路径?参数1=值1&参数2=值2")
// 跳转并query传参-方式2
this.$router.push({
    path: "路由路径",
    query: {
        "参数1":值1,
        "参数2":值2
    }
})

// 跳转并params传参-方式1
this.$router.push("/路由路径/值1/值2")
// 跳转并params传参-方式2
this.$router.push({
    name: "路由名称",
    params: {
        "参数1":值1,
        "参数2":值2
    }
})


// 后退
$router.back()
复制代码

小结

路由嵌套

原理:router-view 中再次包含 router-view。 背景:一个组件内部包含的业务还是很复杂,需要再次进行拆分。 格式:

代码语言:javascript
复制
routes:[
  {
    path: '/page1', 
    component: Page1, // 这个组件内部还有router-view
    children: [
      {
        path:'',  // path为空,表示当 #/page1时,显示 Page1组件+组件1
        component: 组件1  // 
      },
      {
        path:'/xx1', // path以/开头,表示当 #/xx1时,显示 Page1组件+组件2
        component: 组件2
      },
      {
        path:'xx2', // path以/开头,表示当 /page1/xx2时,显示 Page1组件+组件3
        component: 组件3
      }
    ]
  }
]
复制代码

示例

总结:

  1. 在已有的路由容器中,再实现一套路由,再套一个路由容器,叫:嵌套路由。
  2. 嵌套路由除了 router-view 之间需要嵌套,路由规则也需要通过 children 来实现嵌套。

案例 - 模拟网易云音乐效果

二级路由示例 - 网易云音乐 - 发现音乐下

思路:

  1. 创建路由需要的所有页面组件 => 两个一级路由和三个二级路由
    • src/views/MyMusic.vue     --  我的音乐页 - 1
    • src/views/FindMusic.vue   --  发现音乐页 - 2
      • src/views/Child/Recommend.vue    --  发现音乐页 / 推荐页面 - 2-1
      • src/views/Child/Ranking.vue           --  发现音乐页 / 排行榜页面 - 2-2
      • src/views/Child/SongList.vue           --  发现音乐页 / 歌单页面 - 2-3
  1. router/index.js 中配置路由
    • 一级路由 path 从 / 开始定义
    • 二级路由 path 直接写名字或带上一级路由 path(在对应一级路由的 children 数组中配置)
    • 设置默认显示某个二级路由,path 和一级路由保持一致或为空
代码语言:javascript
复制
import Vue from 'vue'
import VueRouter from 'vue-router'

// 一级路由
import FindMusic from '@/views/FindMusic'
import MyMusic from '@/views/MyMusic'

// 二级路由
import Recommend from '@/views/Child/Recommend'
import Ranking from '@/views/Child/Ranking'
import SongList from '@/views/Child/SongList'

Vue.use(VueRouter)

const routes = [
    {
        path: "/",
        redirect: "/find"
    },
    {
        path: "/find", // 一级路由
        component: FindMusic,
        // find下的二级路由
        children: [
              {
                path: "/find", // 和父路由路径一样,默认加载这个路由
                component: Recommend
              },
              {
                path: "/find/ranking",
                component: Ranking
              },
              {
                path: "/find/songlist",
                component: SongList
              }
        ]
    },
    {
        path: "/my",
        component: MyMusic
    }
];

const router = new VueRouter({
    routes
})

export default router
复制代码
  1. App.vue - 一级导航和路由展示
代码语言:javascript
复制
<template>
  <div>
    <div>
      <router-link to="/find">发现音乐</router-link>
      <router-link to="/my">我的音乐</router-link>
    </div>
    <div style="border: 1px solid orange">
      <!-- 一级路由挂载点 -->
      <router-view></router-view>
    </div>
  </div>
</template>

<script>
export default {};
</script>

<style>
.router-link-active{
  color: orange;
}
</style>
复制代码
  1. FindMusic.vue - 设置二级导航和二级路由显示位置
代码语言:javascript
复制
<template>
  <div>
    <p>发现音乐 - 页面</p>
    <div>
      <router-link to="/find">推荐</router-link>
      <router-link to="/find/ranking">排行榜</router-link>
      <router-link to="/find/songlist">歌单</router-link>
    </div>
    <div style="border: 1px solid red; padding: 20px solid block;">
         <!-- 二级路由挂载点 -->
        <router-view></router-view>
    </div>
  </div>
</template>

<script>
export default {};
</script>

<style>
</style>
复制代码

说明:

  • App.vue, 外层的 router-view 负责发现音乐和我的音乐页面切换
  • FindMusic.vue 内层的 router-view 负责发现音乐下的子路由页面切换

全局前置守卫

目标:路由跳转之前,会触发一个函数

语法:router.beforeEach((to, from, next) => {})

案例:在跳转路由前,判断用户登陆了才能去 <我的音乐> 页面,未登录弹窗提示回到发现音乐页面

实现:

  • router/index.js 路由对象上使用固定方法 beforeEach
代码语言:javascript
复制
// 路由前置守卫
router.beforeEach((to, from, next) => {
  // to代表要跳转到哪个路径去, to的值是个对象可以打印看到
  // from代表从哪个路径跳过去
  console.log(to);
  console.log(from);

  // fullPath带?后面参数的, path是完整的路径
  console.log("路由要跳转了");

  // 模拟判断登录了没有, 登录后才能去我的音乐
  let loginFlag = false; // 假设false代表未登录
  if (to.path == "/my" && loginFlag == false) {
    // 如果去个人中心页面, 判断未登录, 提示登录(并强制跳转回find)
    alert("请先登录!");
    next("/find");
  } else {
    // 如果不去/my页面就直接跳转
    next();
  }
});
复制代码

全局后置守卫

目标:路由跳转后,触发的函数

语法:router.afterEach((to, from) => {})

使用:

router/index.js - 添加

代码语言:javascript
复制
router.afterEach((to, form) => {
    console.log(to);
    console.log(form);
    console.log("路由发生了跳转");
})
复制代码

路由模式设置

目标:修改路由在地址栏的模式

模式文档

router/index.js

代码语言:javascript
复制
const router = new VueRouter({
  routes,
  mode: "history" // 打包上线后需要后台支持
})
复制代码

history 和 hash 模式对比:

  1. 功能一样(跳转页面)
  2. history 模式的 path 路径不带 #号,hash 有 #号
  3. hash 模式兼容性好

示例

hash 路由例如:   http://localhost:8081/#/home

history 路由例如: http://localhost:8081/home

源码附件已经打包好上传到百度云了,大家自行下载即可~

代码语言:javascript
复制
链接: https://pan.baidu.com/s/14G-bpVthImHD4eosZUNSFA?pwd=yu27
提取码: yu27

百度云链接不稳定,随时可能会失效,大家抓紧保存哈。

如果百度云链接失效了的话,请留言告诉我,我看到后会及时更新~

开源地址

码云地址: http://github.crmeb.net/u/defu

Github 地址: http://github.crmeb.net/u/defu

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 单页应用和多页应用
  • 路由
    • 路由理解的概念
    • 前端路由工作原理
      • 分析
        • 思路
        • 前端路由简单实现
          • 小结
          • 路由 - 官方路由基本使用
            • 步骤
              • 操作
                • 使用路由
                  • 测试
                    • 图示
                      • 小结
                      • 链接导航 - router-link
                        • Router-link 组件介绍
                          • 示例
                            • 激活类名
                              • 小结
                              • 页面跳转传参
                                • 回顾
                                  • vue 路由传参的方式
                                    • 图示 - 查询字符串
                                      • 图示 - params 传参
                                        • 小结
                                        • 路由 - 重定向
                                          • 理解
                                            • 示例
                                            • 路由 404
                                              • 代码
                                              • 编程式导航
                                                • 编程式导航
                                                  • API
                                                    • 小结
                                                    • 路由嵌套
                                                    • 案例 - 模拟网易云音乐效果
                                                    • 全局前置守卫
                                                    • 全局后置守卫
                                                    • 路由模式设置
                                                      • history 和 hash 模式对比:
                                                        • 示例
                                                        • 开源地址
                                                        相关产品与服务
                                                        容器服务
                                                        腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                                                        领券
                                                        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档