Vue — 第五天(路由)

前端路由

问题导入

在前面完成的资产管理案例中, 我们是把列表区域和添加表单区域实现在了一个区域。当页面功能比较复杂时,我们需要它们拆分开来:一个页面中只显示一个区域。

一个比较直观的解决方案是把它们分别做成两个独立的网页文件,例如:

文件一: xxxx/index.html 显示表格区区域

文件二:xxxx/add.html显示表单区域

然后添加一个导航条来允许用户进行跳转。

这种解决方案比较直接了当,但它存在一些问题:

  • 从一个页面跳入另一个页面需要重新加载公共的资源文件,造成浪费。例如index.html中需要用到axios.js,在add.html中也需要用到。
  • 页面的跳入跳出给用户的体验也不好(特别地,是在移动端)。

那有没有一种方案在不进行页面跳转的前提下,能根据地址栏中的地址不同,来显示不同的内容?

有,这就是前端路由技术。

前端路由

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

模拟实现原理

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head>
<body><div><nav><!-- #:在地址栏有两个含义- 锚点链接:在页面内部进行导航,不会有页面跳转。- hash。在前端路由技术中,我们叫它哈希值。它不会有页面跳转,地址栏变化的浏览器中后退,前进也是可用的http://127.0.0.1:5500/index.html#/add --><a href="#/">主页</a><a href="#/add">添加</a></nav><div id="content"><!-- // 模拟不同的地址栏中的hash值,显示不同的内容 --></div></div><script>// 实现前端路由效果//    -  地址栏变化,页面内容变化,不刷新// 1. 如何监听地址栏中hash值的变化?//    答:在window上,添加hashchange监听// 2. 如何获取当前地址栏中的hash值?//    答:location.hashwindow.addEventListener('hashchange', onHashChange)// 当页面中的dom加载完成,就去执行window.addEventListener('DOMContentLoaded',function() {onHashChange()})function onHashChange (e) {console.log('hash值的变了')console.log(e)// 根据不同的hash值,显示不同的内容到content区域switch (location.hash) {case "#/": // 主页document.getElementById('content').innerHTML = "这里主页的内容"break;case "#/add": // adddocument.getElementById('content').innerHTML = "这里是add的内容"break;default:document.getElementById('content').innerHTML = "404没有这个页面"break;}// if elseif ,elseif ......}</script>
</body>
</html>

技术要点:

  • 地址url 中看到 #,这个 # 有两种情况,一个是我们所谓的锚点,比如典型的回到顶部按钮原理、Github 上各个标题之间的跳转等,路由里的 # 不叫锚点,我们称之为 hash。地址栏中hash的变化是不会发生页面跳转的
  • hashchange 事件用来监听hash值的变化。
  • hash的改变也会记录到浏览历史中,通过回退和前进可以切换业务场景

SPA

单页面应用程序,简称SPA(single page application)一个系统上的所有功能在一个页面上实现。

(在移动端比较多)

SPA是通过前端路由实现业务场景的切换的。

在vue框架中额外引入vue-router插件来配合组件系统就可以轻易地实现。

在单页面应用程序中,如何切换页面的业务场景。

  • http://zhoushugang.gitee.io/hm-toutiao-pc-93/
  • https://music.163.com/

优点:

  • 整体不刷新页面,用户体验更好。

缺点:

  • 首次加载会比较慢一点。

vue-router-使用步骤

vue-router是vue的一个插件,当我们的项目需要前端路由时,我们要先把它下载引入到页面中。

下载: https://cdn.bootcss.com/vue-router/3.1.3/vue-router.min.js

导入插件

# 先下载到本地,再引用
<script src="./vue-router.min.js"></script>
# 直接引用
<script src="https://cdn.bootcss.com/vue-router/3.1.3/vue-router.min.js"></script>

初始化vue-router插件

用VueRouter构造器创建路由实例,并配置路由规则。

基本格式

const router = new VueRouter({routes: [{path:"路径1",component:要展示的组件1},{path:"路径2",component:要展示的组件2},.....]
})

示例

  • vue-router中有一套约定的规则用来确定在哪个url下显示哪个组件。
// 初始化vue-router且使用刚定义的路由规则
const router = new VueRouter({// 初始化路由的配置对象// 有以一个配置项 routes 定义路由规则routes:[{path: '/', component: {template:`<div>我是主页</div>`}},{path: '/news', component: {template:`<div>新闻-生活早知道</div>`}},{path: '/sport', component: {template:`<div>体育-体育改变人生</div>`} }]
})

使用路由实例

在vue构造器中,有一项是router,它专门用来设置路由对象

new Vue({el: '#app',// vue提供了一个配置选项,router选项,是用来挂载路由实例的// 只有挂载了 router 实例 才可使用路由的功能router:路由对象
})

设置路由出口

在vue的模板,添加一个router-view组件,用它来指定当前路由对应组件渲染的位置。

<!-- 渲染路由对应的组件 router-view承载路由对应的组件的-->
<router-view></router-view>

测试使用

请直接在地址栏中补充对应的路由地址来查看路由效果。

路由链接导航

通过router-link来进行路由跳转。

<!-- 写路由链接 不会使用a标签  使用router-link组件 -->
<nav><!-- 组件默认解析的是a标签  to属性跳转的地址,不需要带上# --><router-link to="/">主页</router-link><router-link to="/news">新闻</router-link><router-link to="/sports">运动</router-link>
</nav>
  • router-link组件会被vue解析成a标签,但不能直接通过a标签来跳转。
  • 如果当前路由被激活会添加特殊的类名:
router-link-exact-active router-link-active

动态路由

目标:实现新闻详情的功能:即不同的新闻使用同一个组件,但要传入不同的参数。

概念:不同的路由地址,指向同一个组件,此时需要使用动态路由。

示图:

在这里插入图片描述

代码:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.router-link-exact-active{color:red;padding:0 5px;}</style>
</head>
<body><div id="app"><h3>动态路由</h3><router-link to="/detail/100">编号为100的新闻</router-link><router-link to="/detail/101">编号为101的新闻</router-link><router-link to="/detail/102">编号为102的新闻</router-link><router-link to="/detail/103">编号为103的新闻</router-link><router-view></router-view></div><script src="https://unpkg.com/vue/dist/vue.js"></script><script src="https://unpkg.com/vue-router/dist/vue-router.js"></script><script>// 动态路由//  -- 同一个组件,根据传入参数不同,显示不同的内容。// 例如:大事件项目前中的新闻详情页。//  localhost:3000/index.html#/detail/100   ---->  显示编号为100的新闻//  localhost:3000/index.html#/detail/101   ---->  显示编号为101的新闻// 1. 定义路由规则//    path:'/detail/:形参名'// 2. 跳转 `to:/detail/实参`// 3. 在组件中获取当前的参数值?//   this.$route.params.形参//   - $route 引入了vueRouter插件之后, vue组件内部通过 $route 就可以直接来访问当前的组件对象//   - $route这个对象有很多属性,params用来保存当前传入动态路由的参数值const myrouter = new VueRouter({routes: [// path是hash值,component是组件,就是显示的内容{path: '/',component:{template: `<div>我是主页!!!!!</div>`}},// /detail/:id  可以匹配类似于: /detail/XXXXX 的路径{path:'/detail/:id123',component:{template: `<div><h1>新闻详情页-{{$route.params.id123}}</h1><button @click="h1">点击</button></div>`,methods: {h1 () {console.log( this.$route.params.id123)}}}},{path: '*',component:{template: `<div>你要访问的页面不存在,404!!!!</div>`}},]})new Vue({el: '#app',data:{},methods:{},router: myrouter// 用来设置路由对象 })</script>
</body>
</html>

总结:

  • 在路由规则中,匹配到不同的地址,指向同一个组件
  • 代码:{path:'/detail/:id', component: detail}
  • 数据:模板 {{$route.params.id}} 组件 this.$route.params.id

页面跳转及传参

从页面pageA跳转到pageB ,并携带参数

跳转有两种方式:

  • 通过router-link的to属性跳转
  • 通过$router.push()方法来跳转

传参有两种方式:

  • 查询传参 /aricle?id=1001
  • 路径传参 /article/1001

获取传参数的方式: (根据传参不同,获取参数也不同)

-  查询传参: this.$route.query.id
-  路径传参:this.$route.params.id

声明式导航

通过<router-link>组件的属性to来声明它的跳转后的路由地址。

不带参数的跳转

  • 普通字符串,不带参数。
<router-link to="/list"></router-link>
  • 对象,普通跳转,不带参数
<router-link :to="{path:'/list'}"></router-link>

带参数的跳转

  • 普通字符串,进行带参数的跳转。
<!-- 路径传参  路由规则{path:'/article/:id'}-->
<router-link to="/article/10001"></router-link><!-- 查询传参 路由规则{path:'/article'}-->
<router-link to="/article?id=10001"></router-link>
  • 对象,路径传参
<!--路径传参 路由规则{path:'/article/:id',name:'article',component:Article}] ---><router-link :to="{name:'article',params:{id: 10001}}"></router-link>
<!-- /article/10001 -->
  • 对象,查询传参
<!--路径传参 路由规则 {path:'/article',component:ArticleItem} -->
<router-link :to="{path:'/article',query:{id: 10001}}"></router-link>
<!-- /article?id=10001 -->

代码:

  <div id="app"><!-- 各种router-link写法 --><!-- 字符串 --><router-link to="/list">文章列表</router-link><router-link to="/article/10001">文章详情</router-link><router-link to="/item?id=10001">文章详情</router-link><hr><!-- 对象 --><router-link :to="{path:'/list'}">文章列表</router-link><router-link :to="{name:'article',params:{id:10001}}">文章列表</router-link><router-link :to="{path:'/item',query:{id:10001}}">文章列表</router-link><!-- 显示路由对应组件容器 --><router-view></router-view></div><script src="./vue.js"></script><script src="./vue-router.min.js"></script><script>// routes 指定路由规则数组const router = new VueRouter({ routes:[{path: '/list', component: {template: `<div>列表组件</div>`}},{path: '/article/:id', name: 'article',component: {template: `<div>article文章详情组件 {{$route.params.id}}</div>`}},{path: '/item', component: {template: `<div>item文章详情组件 {{$route.query.id}}</div>`}}] })new Vue({el: '#app',router})</script>

总结:对象方式的两种传参,怎么取值。

  • :to="{name:'article',params:{id:10001}}" $route.params.id
    • 解析后:/article/10001
  • :to="{path:'/item',query:{id:10001}}" $route.query.id
    • 解析后:/item?id=10001

编程式导航

通过 js代码调用一个导航函数(this.$router.push)进行跳转。

场景:

  • 在界面上,有确切的跳转链接,使用声明式导航。
  • 当你在执行一个js逻辑的时候,你想进行跳转,此时使用编程式导航。
    • 在做登录的时候,登录成功后,才应该跳转到首页。

格式:

// 字符串
this.$router.push('/home')// 对象
this.$router.push({ path: 'home' })// 命名的路由
// 路径传参
this.$router.push({ name: 'user', params: { userId: '123' }})// 查询参数,变成 /register?plan=private
this.$router.push({ path: 'register', query: { plan: 'private' }})

代码:

  <div id="app"><!-- 声明式导航 --><router-link to="/login">登录页面</router-link><!-- 显示路由对应组件容器 --><router-view></router-view></div><script src="./vue.js"></script><script src="./vue-router.min.js"></script><script>const router = new VueRouter({ // routes 指定路由规则数组routes:[{path: '/login',component: {template: `<div><input type="text" placeholder="用户名"><input type="password" placeholder="密码"><button @click="login">登录</button></div>`,methods: {login () {// 进行登录// 假设登录成功了// 跳转到首页// 只能通过js的方式进行跳转(编程式导航)// vue实例提供了一个对象 $router // $router就是路由实例,提供一个函数 push,可以进行跳转this.$router.push('/home')}}}},{path: '/home',component: {template: `<div>首页</div>`}}] })new Vue({el: '#app',router})</script>

总结:

  • js代码执行的导航跳转就是编程式导航 this.$router.push('/home')
  • to属性解析过执行的跳转,依赖的代码其实就是编程式导航代码。
  • router-link的to属性能使用的传参方式,在编程式导航中都可以使用。
// 路径传参
this.$router.push({name:'article',params:{id:10001}})
// 键值对传参
this.$router.push({path:'/item',query:{id:10001}})

路由重定向

重定向:

  • 当你访问某个地址的时候,经过程序的处理(用户看不见),跳转到了另外一个地址。

前端的路由,使用使用重定向功能,假设一个业务场景:

  • 当你访问页面的时候,默认hash地址是 #/ ,默认的路由地址 /
  • 此时我们项目的首页 /home ,所以:当我们访问/重定向到/home,才能默认访问首页。

代码:

  <!-- 根容器 --><div id="app"><router-view></router-view></div><script src="./vue.js"></script><script src="./vue-router.min.js"></script><script>const router = new VueRouter({ // routes 指定路由规则数组routes:[// 匹配 / 路径,重定向 到 '/home' 即可{path: '/', redirect: '/home'},// 首页路由规则{path: '/home',component: {template: '<div>首页页面内容</div>'}}] })new Vue({el: '#app',router})</script>

总结:

  • 路由规则对象中 提供了一个选项:redirect 配置重定向的地址即可。

路由嵌套

原理:router-view中再次包含router-view。

背景:一个组件内部包含的业务还是很复杂,需要再次进行拆分。

格式:

routes:[{path: '/sport', component: {template:`<div><router-view></router-view></div>`},children: [path:'/xx1',]}
]

示例

在这里插入图片描述
总结:

  • 在已有的路由容器中,再实现一套路由,再套一个路由容器,叫:嵌套路由。

代码:

<!DOCTYPE html>
<html lang="zh"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><style>body {background-color: #eee;}nav {border:1px solid #ccc;padding:1em;margin:5px;}#app {background-color: #fff;width: 500px;margin: 50px auto;box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.5);padding: 2em;}.box {padding: 1em;border: 1px solid #ccc;margin: 1em;}.router-link-active{}.router-link-exact-active {color:red;}</style>
</head><body><div id="app"><nav><!-- 通过router-link来跳转页面如果是当前页,则会添加 .router-link-exact-active ,.router-link-active 类 --><router-link to="/">主页</router-link><router-link to="/news">新闻</router-link><router-link to="/sport">体育</router-link></nav><!-- 一级路由容器 --><router-view></router-view></div><script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.11/vue.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/vue-router/3.1.3/vue-router.js"></script><script>const sports = {template:`<div><h3>体育-体育改变人生</h3><router-link to="/sport">主页</router-link><router-link to="/sport/guonei">国内</router-link><router-link to="/sport/guowai">国外</router-link><router-view></router-view></div>`}// 初始化vue-router且使用刚定义的路由规则const router = new VueRouter({// 初始化路由的配置对象// 有以一个配置项 routes 定义路由规则routes:[{path: '/', component: {template:`<div>我是主页</div>`}},{path: '/news', component: {template:`<div>新闻-生活早知道</div>`}},{path: '/sport', component: sports,children: [ {path: '', // 二级路由的默认显示内容component: {template:'<div><h4>体育栏目的主页</h4></div>'}},{path: 'guonei',component: {template:'<div><h4>国内体育新闻</h4></div>'}},{path: 'guowai',component: {template:'<div><h4>国外体育新闻</h4></div>'}}]},{path: '/detail/:id', component: {template:`<div>我是新闻详情页{{$route.params.id}}</div>`}}]})new Vue({el: '#app',router})</script>
</body></html>

总结:

  • 嵌套路由除了 router-view 之间需要嵌套,路由规则也需要通过children来实现嵌套。

     children: [ {path: '', // 二级路由的默认显示内容component: {template:'<div><h4>体育栏目的主页</h4></div>'}},{path: 'guonei',component: {template:'<div><h4>国内体育新闻</h4></div>'}},{path: 'guowai',component: {template:'<div><h4>国外体育新闻</h4></div>'}}]},{path: '/detail/:id', component: {template:`<div>我是新闻详情页{{$route.params.id}}</div>`}}]
    

    })

    new Vue({
    el: ‘#app’,
    router
    })

```

总结:

  • 嵌套路由除了 router-view 之间需要嵌套,路由规则也需要通过children来实现嵌套。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/247965.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue — 第六天(vue-cli-介绍)

vue-cli-介绍 vue-cli是官方提供的开发vue项目的脚手架工具。 脚手架是为了保证各施工过程顺利进行而搭设的工作平台。 在开发过程中&#xff0c;脚手架工具是有用的&#xff0c;开发完成&#xff08;项目上线&#xff09;&#xff0c;它就没有用了。 vue-cli可以提供基于vue项…

Vue — 第七天(vue-cli-案例)

资料获取地址&#xff1a; github: https://gitee.com/wang_yu5201314/VUE_vuecli SSH&#xff1a; gitgitee.com:wang_yu5201314/VUE_vuecli.git hero案例-项目介绍 功能介绍&#xff1a; 三个模块 英雄列表(只做这个)装备列表技能列表 英雄列表 列表组件删除功能添加组件编…

postman测试工具

做文件上传测试的时候可以选择输入方式为文件 做文件下载测试的时候&#xff0c;可以选择 转载于:https://www.cnblogs.com/thesun/p/10853226.html

webpack — 概述介绍

webpack概述 webpack是一个流行的前端项目构建工具&#xff08;打包工具&#xff09;&#xff0c;可以解决当前web 开发中所面临的困境。 webpack提供了友好的模块化支持&#xff0c;以及代码压缩混淆、处理js兼容问题、性能优化等强大的功能&#xff0c;从而让程序员把工作的…

彻底解决iOS项目中 _OBJC_CLASS_$_XXXService, referenced from: 的类似问题

这是大家熟悉的开发过程中可能遇到的问题 这是提交源码到appStore不支持64位设备的提示 本人在提交项目到appStore时发生的的错误&#xff0c;提示必须要支持64的设备&#xff0c;然后自己赶紧进行相关的适应&#xff0c;出现了类似标题的问题&#xff0c;解决方法如下: 1、…

THUPCCTSAPIO2019:Far Away

流水账~ THUPC nmdwsmduliu&#xff01; THUPC Day -INF~Day -2 大概就是自己做题和每周两次的考试&#xff0c;lsy和fcw两个外校的来吊打我们qwqqq THUPC Day -1 Z208 长沙->北京 在车上看gzy/tjj/xzz打摆&#xff1f; THUPC Day 0 从火车站出来做地铁的时候和tjj做反了可海…

UIDocumentInteractionController之程序间文档共享

iOS中的沙盒可以让平台更加的安全&#xff0c;这也是沙盒给用户带来的最主要好处。不过由于沙盒的严格限制&#xff0c;导致程序之间共享数据比较麻烦。一般在程序间共享文档可以通过UIDocumentInteractionController类实现通讯。它支持在你的app中用其他app预览和显示文档。同…

c#基础知识梳理(四)

上期回顾 - https://www.cnblogs.com/liu-jinxin/p/10826971.html 一、类 当你定义一个类时&#xff0c;你定义了一个数据类型的蓝图。这实际上并没有定义任何的数据&#xff0c;但它定义了类的名称意味着什么&#xff0c;也就是说&#xff0c;类的对象由什么组成及在这个对象…

UIButton设置圆角和边框及边框颜色

UIButton *testButton [UIButton buttonWithType:UIButtonTypeSystem];[testButton setFrame:CGRectMake(self.view.frame.size.width/2, self.view.frame.size.height/2, 100,100)];[testButton setTitle:"获取屏幕尺寸" forState:UIControlStateNormal];[testButt…

Objective-C 深复制和浅复制与NSCopying协议

1.简单复制只能实现浅拷贝&#xff1a;指针赋值&#xff0c;使两个指针指向相同的一块内存空间&#xff0c;操作不安全。 2. Foundation类已经遵守了<NSCopying>和 <NSMutableCopying>协议,即实现了copy和mutableCopy方法,因此Foundation对象可以使用这些方法创建对…

NSTimer 进阶使用总结与注意事项

NSTimer 是 iOS 上的一种计时器&#xff0c;通过 NSTimer 对象&#xff0c;可以指定时间间隔&#xff0c;向一个对象发送消息。NSTimer 是比较常用的工具&#xff0c;比如用来定时更新界面&#xff0c;定时发送请求等等。但是在使用过程中&#xff0c;有很多需要注意的地方&…

一步一步教你实现iOS音频频谱动画(一)

如果你想先看看最终效果再决定看不看文章 -> bilibili示例代码下载 第二篇&#xff1a;一步一步教你实现iOS音频频谱动画&#xff08;二&#xff09; 基于篇幅考虑&#xff0c;本次教程分为两篇文章&#xff0c;本篇文章主要讲述音频播放和频谱数据的获取&#xff0c;下篇将…

微信小程序的基础 (一)

微信小程序介绍- 链接 微信小程序&#xff0c;简称小程序&#xff0c;是一种不需要下载安装即可使用的应用&#xff0c;它实现了应用“触手可及”的梦想&#xff0c;用户扫一扫或搜一下即可打开应用 1. 为什么是微信小程序? 微信有海量用户&#xff0c;而且粘性很高&#x…

IDEA提交项目到SVN

一.提交步骤 VCS--Enable...-->点击项目右键-->subversion-->share directory-->commit 二.IDEA SVN 忽略文件的设置 1》share .使用idea在将项目提交到svn的过程中遇到这样的问题 将项目share之后再设置ignore files &#xff0c;在commit的时候&#xff0c;不会将…

项目ITP(五) spring4.0 整合 Quartz 实现任务调度

版权声明&#xff1a;本文为博主原创文章&#xff0c;未经博主同意不得转载。https://blog.csdn.net/u010378410/article/details/26016025 2014-05-16 22:51 by Jeff Li 前言 系列文章&#xff1a;[传送门] 项目需求&#xff1a; 二维码推送到一体机上&#xff0c;给学生签到扫…

喜欢用Block的值得注意-Block的Retain Cycle的解决方法

本文不讲block如何声明及使用&#xff0c;只讲block在使用过程中暂时遇到及带来的隐性危险。 主要基于两点进行演示&#xff1a; 1.block 的循环引用(retain cycle) 2.去除block产生的告警时&#xff0c;需注意问题。 有一次&#xff0c;朋友问我当一个对象中的block块中的访问…

【PyQt5】QT designer + eclipse 集成开发

【写在前面的话】 考虑将pyqt5的界面开发qt designer 集成在eclipse中&#xff0c;并且&#xff0c;不利用cmd命令行进行转换。 【工具】 1、pyqt5 2、qt designer 3、eclipse pydy 【步骤】 1、首先配置Qt designer。 菜单 run-->external Tools-->External tools confi…

iOS UIlabel文字排版(改变字间距行间距)分类

在iOS开发中经常会用到UIlabel来展示一些文字性的内容&#xff0c;但是默认的文字排版会觉得有些挤&#xff0c;为了更美观也更易于阅读我们可以通过某些方法将UIlabel的行间距和字间距按照需要调节。 比如一个Label的默认间距效果是这样&#xff1a; 然后用一个封装起来的Cat…

iOS 富文本风格NSMutableParagraphStyle、定制UITextView插入图片和定制复制

问题一 开发过程中&#xff0c;经常会遇到动态计算行高的问题&#xff0c; - (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(nullableNSDictionary<NSString *, id> *)attributes context:(nullable NSStringDrawingC…

线程模块

信号量 from threading import Semaphore,Thread import timedef func(a,b):time.sleep(1)sem.acquire()print(ab)sem.release()sem Semaphore(4) for i in range(10):t Thread(targetfunc,args(i,i5))t.start() 信号量事件 # 事件被创建的时候&#xff0c;默认为False状态 #…