目录
🏮 前言
一、使用vue-router构造函数
二、实现路由跳转2种方式:声明式导航和编程式导航
1、声明式导航—router-link
◼️ router-link —声明式路由,在页面中调用—实现跳转最简单的方法
2、编程式导航
◼️ $router.push() ——函数里面调用:用JS代码来进行跳转
◼️ $router.replace()——用法同$router.push()
◼️ this.$router.go(n)
📚 编程式导航3种方式的区别
三、query和params区别
四、router、routes、route的区别
🏮 前言
本文详尽的讲了在Vue项目中,如何实现路由跳转传参的4四种方式(2大路由跳转方式,每种方式包括4种路由传参实现形式),以及每种方式中实现路由跳转包括路由传参的方法的各种写法,说实话,不能再详细了!另外,如有错误或未考虑完全的地方,望不吝赐教。
一、使用vue-router构造函数
vue-router 本质是一个第三方的包,用的时候需要下载。参考资料:👉简单了解一下vue-router是什么
步骤 (7步法 ):
1. 下载 vue-router 模块到当前工程
yarn add vue-router
2. 在src/main.js中引入VueRouter函数
// 引入路由
import VueRouter from "vue-router";
3. 在src/main.js中使用Vue.use()方法注册全局VueRouter
添加VueRouter到Vue.use()身上,注册全局RouterLink和RouterView组件
// 注册全局
Vue.use(VueRouter)
4. 在src/main.js中创建路由规则数组:路由字典 – 路径和组件名对应关系
什么是路由字典: 专门保存地址栏中相对路径与组件对象之间对应关系的一个数组。
创建路由字典(需要准备切换的页面组件)把准备好的页面组件导入到main.js中
const routes = [
{
path: "/",
redirect: "find", //默认显示推荐组件(路由的重定向)
},
{
path: "/find",
name: "Find",
component: Find, //二级路由
children: [
{
path: "/",
redirect: "recom", //默认显示推荐组件
},
{
path: "ranking", //注意二级路由的路径千万不要加/
component: Ranking,
},
{
path: "songlist",
component: SongList,
},
],
},
{
path: "/my",
name: "My",
component: My,
},
{
path: "/part",
name: "Part",
component: Part,
},
{
path: "*", //也可以写为"/*"
component: NotFound, //定义找不到已有组件时显示404
},
];
5. 在main.js中使用VueRouter构造函数生成路由对象
什么是路由(器)对象: 专门负责监控地址栏变化,并根据地址栏变化查找对应组件,替换页面中router-view的 核心对象
// 使用new调用VueRouter构造函数创建路由对象并且传入规则
const router = new VueRouter({ //
routes,
mode: "history", //路由模式(默认为hash模式)
});
番外:路由模式
(1) hash —— 即地址栏 URL 中的 # 符号
hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.abc.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。
(2) history —— 利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState()方法
history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如http://www.abc.com/book/id。如果后端缺少对 /book/id 的路由处理,将返回 404 错误。
参考资料:路由的hash和history模式的区别
6. 在main.js中把路由对象注入到new Vue实例中
new Vue({
router, //导入路由对象
render: (h) => h(App),
}).$mount("#app");
7. 用router-view作为挂载点, 切换不同的路由页面
当地址栏中url的相对路径切换时,router对象会自动获得新的相对地址。自动去routes中查找对应的组件对象。最后用找到的组件对象代替<router-view>的位置。
router-view 实现路由内容的地方,引入组件时写到需要引入的地方。需要注意的是,使用vue-router控制路由则必须以router-view标签作为容器。(可以先引入根组件App.vue中进行自测)
项目入口文件:main.js
// 导入Vue构造函数
import Vue from 'vue'
import App from './App.vue';
// 导入路由VueRouter构造函数
import VueRouter from 'vue-router';
import Details from "../components/Details.vue";
import HellWold from "../components/HelloWorld.vue";
import Find from "../components/Find.vue";
import My from "../components/My.vue";
import Part from "../components/Part.vue";
import NotFound from "../components/NotFound.vue";
import Recom from "../components/two/Recom.vue";
import Ranking from "../components/two/Ranking.vue";
import SongList from "../components/two/SongList.vue";
// 生产提示
// 改成false是用来关闭开发者提示
Vue.config.productionTip = false
//调用构造函数Vue的use方法 传入VueRouter构造函数
//作用是把VueRouter作为一个插件 全局插入到Vue中
Vue.use(VueRouter)
// 创建路由规则:定义一个路由数组对象
var routes = [
/**
*一个对象就对应了一个路由
*path 就是路由的地址
*name 给路由起的名字
*component 具体跳转的是哪个组件页面
*/
{
// path: '/' 根页面,表示已进入就显示的页面
path: "/",
// 路由重定向:redirect意味着重定向,当浏览器访问'/'根路径时,将会自动重定向到'/find'
redirect: "find", //默认显示推荐组件(路由的重定向)
},
{
path: "/find",
name: "find",
component: Find,
children: [
{
// Vue中如何实现路由跳转时单页面只含子路由的内容?
// 子路由的组件必定在上一级路由中的 router-view 中显示,可以通过条件判断,将父组件的内容隐藏,或者导向新的页面
path: "/",
redirect: "recom", //默认显示推荐组件
},
{
path: "recom",
component: Recom,
},
{
path: "ranking", //注意二级路由的路径千万不要加斜杠/
component: Ranking,
},
{
path: "songlist",
component: SongList,
},
],
},
{
path: "/my",
name: "my",
component: My,
},
{
path: "/part",
name: "part",
component: Part,
},
{
path: "/helloworld",
name: "helloworld",
component: HellWold,
},
{
path: "/details",
name: "details",
component: Details,
},
{
// path:'*' 必须要放最后
// path:'*' 表示上面的路由没有匹配到,则进入下面的页面
path: "*", //也可以写为"/*"
name: "NotFound",
component: NotFound, //定义找不到已有组件时显示404
},
];
// 实例化构造函数 VueRouter 产生一个实例化对象
// 并把上面的路由数组对象routes当作参数,以对象的方式传给构造函数 VueRouter
const router = new VueRouter({
routes, // 引入路由规则routes
mode: "history", //路由模式(默认为hash模式)
});
// 挂载
/**
* 在Vue的对象参数里面配置 el:"#app" 等于 .$mount('#app')
* 都是用来挂载到id为#app的div上的
* 把路由实例化对象router配置在Vue中,作用是保证项目中
* 所有的vue文件都可以使用router路由的属性和方法
*/
new Vue({
router, // 注入路由对象
// render函数渲染DOM结构,创建虚拟节点VNode。会把所有vue文件渲染到App组件上件上
render: h => h(App),
}).$mount('#app') // 若没有配置el属性,就需要使用$mount()函数手动挂载,等同于el:"#app""#app"
番外:当然,我们也可以在一个单独的index.js文件里面创建路由字典以及路由器对象并将路由字典传入路由器对象中中,比如,我们在src文件夹下,新建一个router文件夹,里面存放index.js。然后把index.js文件导入main.js即可。把路由文件项目入口文件main.js分开,是推荐的比较规范的做法。附:各个页面文件代码如下:
注意!在index.js文件中,不要忘记导入与路由字典对应的各个页面组件以及vue-router ,并且最后要加一句导出路由对象的代码:export default router
vue脚手架项目结构,如下:
vue版本及安装各依赖的版本情况,如下:
页面组件之间的跳转演示,如下:
* 路由文件——src/router/index.js
// 导入路由VueRouter构造函数
// 因为涉及路由规则以及路由器对象,所以需要引入VueRouter
import VueRouter from "vue-router";
// 以下是各个页面组件的引入
import Details from "../components/Details.vue";
import HellWold from "../components/HelloWorld.vue";
import Find from "../components/Find.vue";
import My from "../components/My.vue";
import Part from "../components/Part.vue";
import NotFound from "../components/NotFound.vue";
// 创建路由规则:定义一个路由数组对象
var routes = [
/**
*一个对象就对应了一个路由
*path 就是路由的地址
*name 给路由起的名字
*component 具体跳转的是哪个组件页面
*/
{
// path: '/' 根页面,表示已进入就显示的页面
path: "/",
// 路由重定向:redirect意味着重定向,当浏览器访问'/'根路径时,将会自动重定向到'/find'
redirect: "find", //默认显示推荐组件(路由的重定向)
},
{
path: "/find",
name: "find",
component: Find,
children: [
{
// Vue中如何实现路由跳转时单页面只含子路由的内容?
// 子路由的组件必定在上一级路由中的 router-view 中显示,可以通过条件判断,将父组件的内容隐藏,或者导向新的页面
path: "/",
redirect: "recom", //默认显示推荐组件
},
{
path: "recom",
component: Recom,
},
{
path: "ranking", //注意二级路由的路径千万不要加斜杠/
component: Ranking,
},
{
path: "songlist",
component: SongList,
},
],
},
{
path: "/my",
name: "my",
component: My,
},
{
path: "/part",
name: "part",
component: Part,
},
{
path: "/helloworld",
name: "helloworld",
component: HellWold,
},
{
path: "/details",
name: "details",
component: Details,
},
{
// path:'*' 必须要放最后
// path:'*' 表示上面的路由没有匹配到,则进入下面的页面
path: "*", //也可以写为"/*"
name: "NotFound",
component: NotFound, //定义找不到已有组件时显示404
},
];
// 创建路由器对象
// 实例化构造函数 VueRouter 产生一个实例化对象
// 并把上面的路由数组对象routes当作参数,以对象的方式传给构造函数 VueRouter
const router = new VueRouter({
routes,
mode: "history", //路由模式(默认为hash模式)
});
// 导出路由器对象
// 把实例化路由对象 router 默认导出
export default router;
* 项目入口文件——src/main.js
// 导入vue构造函数
import Vue from 'vue'
// 导入根组件——项目主组件,页面入口文件,vue页面资源的首加载项
import App from './App.vue';
// 导入路由VueRouter构造函数
// 需要注册全局VueRouter,所以引入VueRouter
import VueRouter from 'vue-router';
// 导入路由文件
//导入router文件夹中的index.js中的router实例化对象
//一个文件夹里面只有一个index.js文件在脚手架中可以把./router/index.js简写为./router
import router from './router'
// 生产提示
// 改成false是用来关闭开发者提示
Vue.config.productionTip = false
// 注册全局VueRouter
// 调用构造函数Vue的use方法 传入VueRouter构造函数
// 作用是把VueRouter作为一个插件 全局插入到Vue中
Vue.use(VueRouter)
// 挂载div#app
/**
* 在Vue的对象参数里面配置 el:"#app" 等于 .$mount('#app')
* 都是用来挂载到id为#app的div上的
* 把路由实例化对象router配置在Vue中,作用是保证项目中
* 所有的vue文件都可以使用router路由的属性和方法
*/
new Vue({
router, // 注入路由对象
// render函数渲染DOM结构,创建虚拟节点VNode。会把所有vue文件渲染到App组件上
render: h => h(App),
}).$mount('#app') // 若没有配置el属性,就需要使用$mount()函数手动挂载,等同于el:"#app"
* 项目根组件——src/App.vue
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png" />
<HellWold></HellWold>
<hr>
<div id="nav">
<!--使用 router-link 组件进行导航 -->
<!--通过传递 `to` 来指定链接 -->
<!--`<router-link>` 将呈现一个带有正确 `href` 属性的 `<a>` 标签-->
<router-link to="/find">发现音乐</router-link>
<router-link to="/my">我的音乐</router-link>
<router-link to="/part">我的朋友</router-link>
</div>
<hr>
<!-- 路由出口 -->
<!-- 路由匹配到的组件将渲染在这里 -->
<router-view></router-view>
</div>
</template>
<script>
import HellWold from "./components/HelloWorld.vue";
export default {
name: "App",
components: {
HellWold,
},
};
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
#nav {
display: flex;
justify-content: space-around;
}
a {
text-decoration: none;
}
</style>
* 页面组件——Find.vue
<template>
<div class="find">我是发现页
<!-- 用于展示二级路由默认路由Recom -->
<!-- 进入根路径,自动重定向到Find组件页面,然后有重定向到二级默认路由组件Recom -->
<router-view></router-view>
</div>
</template>
<script>
export default{
name:"Find"
};
</script>
<style scoped>
.find{
color: blue;
font: italic 700 25px Arial;
}
</style>
* 页面组件Find的二级默认组件——Recom.vue
<template>
<div class="recom">
<router-link to="/details">recom...</router-link>
</div>
</template>
<script>
export default {
name: "Recom",
};
</script>
<style scoped>
</style>
* 页面组件Find的二级组件——Ranking.vue
<template>
<div class="ranking">
<router-link to="/details">ranking...</router-link>
</div>
</template>
<script>
export default {
name: "Ranking",
};
</script>
<style scoped></style>
* 页面组件Find的二级组件——SongList.vue
<template>
<div class="songList">
<router-link to="/details">songlist...</router-link>
</div>
</template>
<script>
export default {
name: "SongList",
};
</script>
<style scoped>
</style>
* 页面组件——Details.vue
<template>
<div class="details">我是详情页</div>
</template>
<script>
export default {
name: "Details",
};
</script>
<style scoped>
.details {
color: rgb(20, 220, 40);
font: italic 700 25px Arial;
}
</style>
* 页面组件——My.vue
<template>
<div class="my">我是音乐页
</div>
</template>
<script>
export default{
name:"My"
};
</script>
<style scoped>
.my{
color:rgb(20, 159, 113);
font: italic 700 25px Arial;
}
</style>
* 页面组件——Part.vue
<template>
<div class="part">我是朋友页
</div>
</template>
<script>
export default{
name:"part"
};
</script>
<style scoped>
.part{
color: crimson;
font: italic 700 25px Arial;
}
</style>
* 页面组件——HelloWorld.vue
<template>
<div class="hello">如果我被App.vue导入,那么我就是App.vue的子组件</div>
</template>
<script>
export default {
name: "HelloWorld",
created() {},
};
</script>
<style scoped>
.hello{
color:cornflowerblue;
font: 700 25px Arial;
}
</style>
* 页面组件——NotPage.vue
<template>
<div class="NotFound">我是404页</div>
</template>
<script>
export default {
name: "NotFound",
};
</script>
<style scoped>
.NotFound{
color: crimson;
font: normal 900 40px Arial;
}
</style>
二、实现路由跳转2种方式:声明式导航和编程式导航
Vue Router | Vue.js 的官方路由
◼️ 声明式导航在浏览器中,点击链接实现导航的方式,叫做声明式导航。例如:普通网页中点击 a标签链接。vue项目中点击router-link标签链接都属于声明式导航。
声明式路由导航,直接写在html中,结构简单使用方便,但是只能放在<router-link>标签中使用,<router-link>标签会将路由转成<a>标签,通过点击跳转路由,因此局限性也非常大。
◼️ 编程式导航在浏览器中,调用API方法实现导航的方式,叫做编程式导航。例如:普通网页中调用location.href跳转到新页面的方式,属于编程式导航。vue项目中编程式导航有this.$router.push(),this.$router.replace(),this.$router.go()。 参考资料:Vue路由跳转方式
编程式路由导航,需要写在js中,结构也不算复杂,优势在于非常灵活,不受固定标签限制,可以在任意情景下转跳路由。
实际应用时可根据自身喜好决定使用哪种路由导航方式。
1、声明式导航—router-link
◼️ router-link —声明式路由,在页面中调用—实现跳转最简单的方法
利用组件router-link创建a标签来定义导航链接,它是用来替代a标签的;
◾ router-link 是vue-router提供的一个全局组件;
◾ router-link实质上最终会渲染成a链接,to属性指定目标地址等价于href属性;
◾ router-link提供了声明式导航高亮的功能(自带类名);
1) 不带参数
// 注意:router-link中链接如果是'/'开始就是从根路由开始,如果开始不带'/',则从当前路由开始。
// 1. 字符串属性 to ————经测试,以下2种写法都是可以的
<router-link to='/find'> // 字符串
<router-link to='find'> // 字符串
// 2. 动态属性绑定 :to或v-bind:to ————————经测试,以下4种写法都是可以的
// :to="变量或js表达式"
<router-link :to="'find'"> // 不要忘记加引号,字符串也是一个js表达式
// 对象格式,name,path都行, 建议用name
<router-link :to="{name:'find'}">
<router-link :to="{path:'find'}">
<router-link :to="{path:'/find'}">
// 经测试:有component参数时优先router-link中配置的component,没有时从js中配置取
<router-link :to="{path:'/find',component: Find}">
举个栗子:
在控制台开发者工具里检查元素时会发现激活的类名,在样式style中有定义高亮样式,点击时就会实现高亮效果
<template>
<div>
<div class="footer_wrap">
// router-link好处 : 自带激活时的类名, 可以做高亮
<router-link to="/find">发现音乐</router-link>
<router-link to="my">我的音乐</router-link>
<router-link :to="'part'">我的朋友</router-link>
</div>
<div class="top">
<router-view></router-view>
</div>
</div>
</template>
👉 <router-link>组件支持用户在具有路由功能的应用中点击导航。通过to属性指定目标地址,默认渲染为带有正确连接的<a>标签,可以通过配 置tag属性生成别的标签。另外,当目标路由成功激活时,链接元素自动设置一个表示激活的css类名。
组件的属性有:to 、replace、 append、 tag、 active-class、 exact 、 event、 exact-active-class
👉 <router-view> 是与router-link配合,用来渲染通过路由router-link映射过来的组件,当路径更改时,<router-view> 中的内容也会发生更改。
2) 携带参数
在跳转路由时, 可以给路由对应的组件内传值 ——动态路由传参
在router-link上的to属性传参数值,有以下3种方式 :
方式一:路由属性配置传参,需进行组件的路由规则配置
开启 props=true 传值
(1). 修改路由文件index.js中路由字典中的路由地址,允许传参
{path:"/details/:变量名", component:Details, props:true},
(2) 跳转时,路径: /details/变量值
<router-link to="/相对路径/参数值" // 需要动态获取参数值时,使用:to
(3). 下个页面中如何获得地址栏中的参数值:
a. 路由文件index.js中的props:true,意为让地址栏中的参数值自动变成当前页面组件的props中的一个属性值
在 Details.vue 组件中通过 props 接收
export default {
name:"details",
props:['id'] //模板中便可以使用 {{id}}
}
b. 下一个页面中就可以用: props:[ "变量名" ]
(4). 坑: 一旦一个路径配置/:变量名,则必须携带参数才能进入该路径。如果不带参数,将被禁止进入!
方式二:query方式传参,可以由name和path引入,无需配置组件的路由规则
配置路由格式:/path
,也就是普通配置。
传递的方式:对象中使用query的key作为传递方式。
传递后形成的路径:/path?参数名=参数值
。
// query传参数 ————类似get,浏览器地址栏中显示参数
<router-link to="/find?id=1"> // 路由可不配置
<router-link :to="{name:'find', query: {id:1}}"> // 路由可不配置
<router-link :to="{path:'/find', query: {id:1}}"> // 路由可不配置
// html 取参 $route.query.id
// script 取参 this.$route.query.id
新页面参数获取:通过$route.query.参数名
获取传递的值
使用用 query 来传参,这种方式是可以解决页面刷新参数消失问题的,query这种方式可以理解为是 ajax 中的 get 方法,参数是直接在 url 后面添加的,参数是可见的,所以解决页面刷新参数消失问题建议使用此方法来解决
方式三:params方式传参,只能由name引入,需进行组件的路由规则配置
- 配置路由格式:
/path/:参数变量
- 传递的方式:在path后面跟上对应的值
- 传递后形成的路径:
/path/参数值
// params传参数————类似post,浏览器地址栏中不显示参数
<router-link to="/find/1"> // 字符串格式传参
<router-link :to="{name:'find', params: {id:1}}"> // 只能用name
// 路由配置 path: "/find/:id" 或者 path: "/find:id"
// 不配置path ,第一次可请求,刷新页面id会消失
// 配置path,刷新页面id会保留
// html 取参 $route.params.id
// script 取参 this.$route.params.id
新页面参数获取:通过 $route.params.参数名
获取传递的值。
番外:vue-router中route-link的样式
<router-link>是 vue-router 中的一个组件,在vue2.0中,替代了原来的v-link指令,它的作用就是相当于 a 标签一样的给路由做导航,事实上它也确实是默认被渲染为 a 标签。关于它的详细信息请看官方文档:API 参考 | Vue Router
<router-link>这个组件接受以下属性参数,在这里我们说一说在使用中要注意的一些问题:
1. replace添加这个属性的路由在导航后不会留下 history 记录,目测这是一个非常好用的属性,可以解决以前烦死人的 history 问题,大幅提高用户体验。
2. tagroute-link 会被默认渲染为 a 标签,如果你想让它渲染成其它的标签就可以使用 tag 属性,这样可以解决一些 a 标签的默认样式问题。
3. exact
设置了这个属性的路由会被认为是处于激活状态,最典型的应用就是导航栏了,比如说一组5个 tab,给第一个 tab 设置这个属性,那么它就是处于选中状态。
4. active-class链接激活时的类名,其实这个也是为了方便导航栏切换状态的,设置这个属性就可以让链接在激活时自动切换相应的样式。
5. router-link-active这是一个类名,也是上面第四条属性的默认值,就是说链接在被激活时会自动给加上这个 class,所以就可以把这个 class 写在 style 里面,里面写上导航在激活时的一些公共样式,比如字体颜色,大小等。参考资料:vue.js学习之router-link
2、编程式导航
◼️ $router.push() ——函数里面调用:用JS代码来进行跳转
跳转到指定url路径,并想history栈中添加一个记录,点击后退会返回到上一个页面
1) 不带参数
// 字符串格式
this.$router.push('/find')
this.$router.push('find')
// 对象格式
this.$router.push({name:'find'}) // name属性不能斜杠/,因为它只是表示一个名字
// path属性斜杠/可带可不带
this.$router.push({path:'/find'})
this.$router.push({path:'find'})
2) 携带参数
方式一:路由属性配置传参,需进行组件的路由规则配置
(1). 修改路由文件index.js中路由字典中的路由地址,允许传参
{path:"/details/:变量名", component:Details, props:true},
(2) 跳转时,路径: /details/变量值
this.$router.push("/相对路径/参数值")
(3). 下个页面中如何获得地址栏中的参数值:
a. 路由文件index.js中的props:true,意为让地址栏中的参数值自动变成当前页面组件的props中的一个属性值
b. 下一个页面中就可以用: props:[ "变量名" ]
(4). 坑: 一旦一个路径配置/:变量名,则必须携带参数才能进入该路径。如果不带参数,将被禁止进入!
方式二:query方式传参,可以由name和path引入,无需配置组件的路由规则
配置路由格式:/path
,也就是普通配置。
传递的方式:对象中使用query的key作为传递方式。
传递后形成的路径:/path?参数名=参数值
。
// query传参数 ————类似get,浏览器地址栏中显示参数
this.$router.push({name:'find',query: {id:'1'}}) // 不用路由配置
this.$router.push({path:'/find',query: {id:'1'}})// 不用路由配置
// html 取参 $route.query.id
// script 取参 this.$route.query.id
新页面参数获取:通过$route.query.参数名
获取传递的值
方式三:params传参,只能由name引入,需进行组件的路由规则配置
- 配置路由格式:
/path/:参数变量
- 传递的方式:在path后面跟上对应的值
- 传递后形成的路径:
/path/参数值
// params传参数————类似post,浏览器地址栏中不显示参数
this.$router.push({name:'find',params: {id:'1'}}) // 只能用 name
// 路由配置 path: "/find/:id" 或者 path: "/find:id" ,
// 不配置path ,第一次可请求,刷新页面id会消失
// 配置path,刷新页面id会保留
// html 取参 $route.params.id
// script 取参 this.$route.params.id
params传参时,如果没有在路由规则中定义参数,也是可以传过去的,同时也能接收到,但是一旦刷新页面,这个参数就不存在了
新页面参数获取:通过 $route.params.参数名
获取传递的值。
◼️ $router.replace()——用法同$router.push()
1) 跳转到指定的URL,替换history栈中最后一个记录,点击后退会返回至上一个页面。(A----->B----->C 结果B被C替换 A----->C)
2) 设置replace属性(默认值:false)的话,当点击时,会调用router.replace(),而不是router.push(),于是导航后不会留下history记录。
3) 即使点击返回按钮也不会回到这个页面。加上replace: true时,它不会向 history 添加新纪录,而是跟它的方法名一样——替换当前的history记录。
// 声明式
<reouter-link :to="..." replace></router-link>
// 编程式:
router.replace(...)
// push方法也可以传replace
this.$router.push({path: '/homo', replace: true})
this.$router.replace({
name: this.pageFrom,
params: this.formData
})
onConfirm: () => {
this.$router.replace('/TravelManage')
}
◼️ this.$router.go(n)
向前或者向后跳转n个页面,n可为正整数或负整数
该方法的参数n是一个整数,意思是在 history 记录中向前或者后退多少步,类似 window.history.go(n)
this.$router.go(1) // 类似history.forward()
this.$router.go(-1) // 类似history.back()
📚 编程式导航3种方式的区别
this.$router.push
跳转到指定url路径,并向history栈中添加一个记录,点击后退会返回到上一个页面
this.$router.replace
跳转到指定url路径,但是history栈中不会有记录,点击返回会跳转到上上个页面 (就是直接替换了当前页面)
this.$router.go(n)
向前或者向后跳转n个页面,n可为正整数或负整数
三、query和params区别
◼️ 用法上的区别:
query传参方式可以配合path或是name来引入路由,而params只能用name来引入(如果使用path,接收参数页面会是undefined!!!),接收参数都是类似的,分别是 this.$route.query.参数名和 this.$route.params.参数名 。
用 path 的时候,提供的 path 值必须是相对于根路径的相对路径,而不是相对于父路由的相对路径,否则无法成功访问。
◼️ url地址显示与否:
query更加类似于我们ajax中的get传参,页面跳转之后页面 url后面会拼接参数,类似?id=1,刷新页面后参数id还在,会一直保留,也就是说,query传参刷新页面后可以保存。另外,非重要性的可以这样传, 密码之类等重要数据还是要使用params,这样数据安全。
query传参,比较灵活,没有条件约束随时可以追加参数,参数显示在了参数(search)的位置,参数的辨识度更高,例如:/name,/name?username=tom。
params类似post,跳转之后页面 url后面不会拼接参数,也就是说地址栏不显示参数名称id,但是有参数的值,如果刷新页面后id会消失,也就是说,params传参刷新后不会保存(除非在路由规则里配置对应参数:/path/:参数变量)
params传参,正确使用时相对严谨,对于没有在动态路由上定义的参数如果随意增删,会有数据丢失的风险。定义路由时就要考虑好路由参数定义。参数如果为字符串时,辨识度会低于query的方式,例如:/name/:username,/name/tom。
需要特别注意的点
1. params是路由的一部分,必须要在路由后面添加参数名,也就是占位符。
2. query是拼接在url后面的参数,没有也没关系。
3. params一旦设置在路由,params就是路由的一部分,如果这个路由有params传参,但是在跳转的时候没有传这个参数,会导致跳转失败或者页面会没有内容。
◼️ 小结:
query传参:👇
直白的来说query相当于get请求,name和path都行,通过this.$route.query获取,页面跳转的时候,可以在地址栏看到请求的参数名以及参数值,刷新页面,参数会一直保留。
params传参:👇
params相当于post请求,只能name,通过this.$route.params获取,页面跳转的时候,参数名不会在地址栏中显示,但是参数值会显示,刷新页面参数值丢失。(如果想要参数值即使刷新也会一直保留显示在地址栏里,必须在路由字典中对应的路由里使用冒号" : "来匹配对应参数,否则第一次可请求,虽然可以传参,但刷新页面参数值会消失)。
params传参不适于需要刷新页面,又要取值的情形。因此,解决页面刷新导致数据丢失的问题,建议使用 query传参,除此之外,也可以考虑使用 localStorage,sessionStorage来保存参数,也可以使用vuex的store来保存。
参考资料:vue通过params传参刷新页面参数丢失问题以及实现vue路由可选参数的解决办法
参考资料:params和query传参方式有何区别
番外:带参数的动态路由匹配
动态路径参数,使用冒号 : 标记。比如,当一个路由被匹配时,它的 params 的值将在每个组件中以 this.$route.params
的形式暴露出来, 你可以在同一个路由中设置有多个 路径参数,它们会映射到 $route.params
上的相应字段。例如:
匹配模式 | 匹配路径 | $route.params |
---|---|---|
/users/:username | /users/eduardo | { username: 'eduardo' } |
/users/:username/posts/:postId | /users/eduardo/posts/123 | { username: 'eduardo', postId: '123' } |
除了 $route.params
之外,$route
对象还公开了其他有用的信息,如 $route.query
(如果 URL 中存在参数)、$route.hash
等。你可以在 API 参考中查看完整的细节。这个例子的 demo 可以在这里找到。
动态路由很适合用于类似商品详情页的需求,商品详情页的页面结构都一样,只是商品id的不同,然而id不同,详情页渲染出的结果不一样,所以这个时候就可以用动态路由。
vue官方参考资料:带参数的动态路由匹配 | Vue Router
四、router、routes、route的区别
1. router:指的是路由实例。如:路由编程式导航的this.$ router.push( )也能进行跳转,这个方法则会向history里面添加一条记录,当点击浏览器回退按钮或者this.$ router.back()就会回退之前的url。而this.$router.back(-1)就是返回上一个路由。
2. routes:指创建路由实例的配置项。用来配置多个route路由对象。routes出现在router文件夹下的index.js文件里,如下图:
就是我们在routes里进行路由配置,我们发现routes里对象里的component属性值既可以写成组件名,也可以直接( )=>import(路径)写入,这两种写法都是可以的,只不过后一种方法就不用再在上面单独import…from…引入了。 一般是在懒加载时采用该方式,也就是说暂时不要把该组件import进程序中,在路由字典routes中定义,只有当用户访问到某个组件时,才动态引入这个组件。
3. route:路由对象。如:this.$route指的就是当前路由对象,可以从对象里面获取name,path,params,query,hash等。
◼️ 小结:route, routes, router
1. router: 用new VueRouter()创建出的路由器对象
a. 监视地址栏变化 ;b. 还可以执行跳转动作!
$router 是“路由实例”对象包括了路由的跳转方法,钩子函数等。——如$router.push( )
2. routes: 一个路由字典数组,包含当前网站中所有路径与组件的对应关系列表。
routes会被装入new VueRouter()即路由器对象router中,和router对象一起发挥作用!
3. route: 一个路由地址,代表当前地址栏中的url信息,像BOM中的location。如地址栏:http://127.0.0.1:5500/index.html#/details
$route 是“路由信息对象”,包括 path,params,hash,query,fullPath,matched,name 等路由信息参数 ——如$route. Params. Userid 获取参数传递的值
番外:Vue-router跳转和location.href有什么区别
使用 location.href= /url 来跳转,简单方便,但是刷新了页面;
使用 history.pushState( /url ) ,无刷新页面,静态跳转;
引进 router ,然后使用 router.push( /url )来跳转,使用了diff 算法,实现了按需加载,减少了 dom 的消耗。其实使用 router 跳转和使用 history.pushState() 没什么差别的,因为vue-router就是用了 history.pushState() ,尤其是在history模式下
番外:vue项目中跳转到外部链接方法
在项目文件中,如果是vue页面中的内部跳转,在js中用this.$router.push(“/相对地址”)或是this.$router.resolve(“/相对地址”)可以实现
例如:
this.$router.push({path:'/channeldetailview',query: {channelid:this.data.id}});
或是 在html中使用
<router-link to="/相对地址">内容</router-link>
在vue中使用this.$router.push(“/相对地址”) 或 this.$router.resolve(“/相对地址”),都可实现跳转新页面,那vue中这两种打开新页面的方式之间有什么区别呢?
实际上,这两种方式的区别如下:
$router.push()方法是一个可以直接实现链接跳转的方法,即在vue中它可以直接在当前页面打开新的路由(仅能在当前页面打开)并加载组件。返回一个Promise对象
$router.resolve()方法本身不能直接实现链接跳转,需要借助直接window全局对象中的打开链接的方法,例如open()方法才能实现,然后根据open方法的name属性的属性值_self或是_blank来选择是当前页面打开链接并加载组件还是打开新的标签页并加载组件。返回的对象,如下图:
举个梨子:this.$router.resolve() 打开新窗口跳转
◾ 通过path形式跳转
goTo() {
let routeData = this.$router.resolve({ path: "/details", });
window.open(routeData.href, "_blank");
}
◾ 通过name形式跳转
goTo() {
let routeData = this.$router.resolve({ name: "details", });
window.open(routeData.href, "_blank");
}
<template> <div class="recom"> <router-link to="/details">recom...</router-link> <button @click="goTo">我是一个按钮</button> </div> </template> <script> export default { name: "Recom", methods: { goTo() { // 1、$router.push()可直接实现从当前页面打开链接,不能实现新标签页面打开链接 // this.$router.push({ path: "/details"}) // 2.$router.resolve()配合window全局对象中的打开链接的方法,实现链接跳转 let routeData = this.$router.resolve({ path: "/details" // name: "details" }); console.log(routeData) window.open(routeData.href, "_blank"); }, }, }; </script> <style scoped> </style>
跳到外部链接,不能用这个。不然就会报错,看一下链接的路径,原来外部链接前面加上了http://localhost:8080/#/这一串导致跳转出现问题,那么我们如何跳转到外部链接呢?
① 我们只需用 window.location.href = url 来实现——直接在方法里面写
window.location.href = 'https://blog.csdn.net/sunyctf'
② 绑定事件处理函数
view界面中
<button @click="search">我的CSDN个人主页</button>
methods对象中
methods: {
search() {
window.location.href = 'https://blog.csdn.net/sunyctf'
}
}
◼️ 在当前窗口打开新连接
◾ 可后退:👇 以下3个方法等价
① window.location.assign("新url") ;② window.location.href="新url";③ window.open("url", "_self"
◾ 禁止后退:👇js: location.replace("新url")
◼️ 在新窗口打开,可打开多个:
window.open("url", "_blank");
◼️ 在新窗口打开,只能打开一个:
window.open("url", "自定义的窗口名");