目录
路由 VueRouter
- 官网:
https://router.vuejs.org/zh/
- 概念:就是url路径,使用#在一个页面之中跳转,类似于a标签的锚链接!
注意点:这种hash # 不会刷新页面,也不会发起新的请求,只是实现客户端页面的跳转!
注意点2:就是http请求之中,不携带#,那么就是说不能向服务器发起请求
注意点3:# 会修改浏览器的历史记录!
前端路由和后端路由的区别
- 前端路由:就是根据#/ 后面的hash值,去匹配不同的path路径,显示不同的组件,达到页面跳转效果! hash => 组件
- 目的:是为了单页面应用程序!(Single Page Application)
- 后端路由:就是根据前端发送请求的url路径,去匹配url所对应的操作处理函数方法,待操作后,把数据返回给前端(渲染页面),实现前端页面的刷新!
路由的原理
<div id="app">
<a href="#/a">a</a>
<a href="#/b">b</a>
<a href="#/c">c</a>
<!-- 显示当前的某个组件 -->
<component :is="comname"></component>
</div>
<script src="../vue.js"></script>
<script>
Vue.component("com1", {
template: "<div>a组件</div>"
})
Vue.component("com2", {
template: "<div>b组件</div>"
})
Vue.component("com3", {
template: "<div>c组件</div>"
})
let data = {
comname: "com1"
}
let methods = {}
new Vue({
el: "#app",
data,
methods,
mounted() {
let self = this;
window.onhashchange = function () {
let hash = location.hash;
console.log(hash, self.comname); //注意点:这边的this指向的是window
switch (hash) {
case "#/a":
self.comname = "com1"
break;
case "#/b":
self.comname = "com2"
break;
case "#/c":
self.comname = "com3"
break;
}
}
}
})
</script>
路由的安装和使用
第一种方式使用
引入:以cnd的方式引入 <script src="https://lib.baomitu.com/vue-router/3.1.3/vue-router.min.js"></script>
第二种方式使用
- 安装:
npm i vue-router
- 引用:
import Vue form vue
import VueRouter form vue-router
- 使用:
Vue.use(VueRouter)
使用第一种方式
路由的基本使用
- 注意点:导入vue-router之后,就有这一个VueRouter构造函数了(全局的) 参数为一个对象
- 创建一个路由对象 const router = new VueRouter({})
- 里面的参数为一个对象 对象里面有着一个路由规则的数组 routes(路线)
- routes:[{}] => 对象里面的有着path => 指向的是hash的路径 component => 指向的是路由的组件对象!还有redirect 重定向!
- 注意点:需要把当前创建的router对象挂载在Vue实例对象之中
- 需要呈现给用户的时候,则需要使用到 还有 这两个标签
- router-view => 表示的是路由的坑,显而易见的是,就是需要等待匹配路由路径后,才能显示这个路由组件
- router-link => 表示的是路由的链接,点击当前的链接,去往里面to属性所匹配的路由!
- to属性所设置的路由链接!
- tag属性,设置该link以哪种标签显示,默认为a链接!
<router-link to="/login" tag="span" >去登录</router-link>
<div id="app">
<router-link to="/login">登录</router-link>
<router-link to="/reg">注册</router-link>
<router-view></router-view>
</div>
<script>
//定义路由组件对象!
const login = { //这种方式 只是适合路由对应的组件才能创建的路由对象!
template: "<div>登录组件</div>"
}
const reg = {
template: "<div>注册组件</div>"
}
const router = new VueRouter({
routes: [{
path: "/login", //这是hash路径
component: login //这是hash路径所对应的组件对象 也就是说,需要从组件之中,抽离出这个单独的对象
}, {
path: "/reg",
component: reg
}]
})
let data = {}
let methods = {}
new Vue({
el: "#app",
data,
methods,
router, //把路由对象 挂载在vue实例对象身上!
})
</script>
普通组件和路由组件对象的区别
<div id="app">
<!-- 这是引用普通组件 -->
<login></login>
<!-- 这是路由组件的引用 -->
<!-- 这是路由的链接 to 去往哪里 -->
<router-link to="/login">去登录</router-link>
<router-link to="/reg">去注册</router-link>
<!-- 这是路由的坑,将来是匹配组件呈现的坑! -->
<router-view></router-view>
</div>
//定义一个普通组件
Vue.component("login", { //这种定义的普通组件,仅仅在标签之中引用! 无法在hash之中的组件使用!
template: "<div>注册组件</div>"
})
//定义一个路由组件
//路由之中的组件设置! 就是把Vue.component中的对象抽离出来!
const login = {
template: "<div>我是登录组件</div>"
}
const router = new VueRouter({ //router为路由规则 path为hash路径 component为hash要对应的组件对象
//匹配到的路由路径,想要展示给用户看,那么需要在html之中,引用一个<router-view>标签!
routes: [{
path:"/",
redirect:"/login"
},{ //routes => 路线是复数哦!
path: "/login",
component: login
}, {
path: "/reg",
component: reg
}, ]
})
new Vue({
el: "#app",
data:,
methods: {
},
router, //把router 路由对象挂载在vm实例对象上
})
路由的高亮显示和重定向
- 第一种高亮的显示,使用默认的类名: => router-link-active 给这个类名添加样式!
- 已经设置好类名的方式,那么就在new VueRouter构造函数内部,使用 linkActiveClass: “my-active”
- //配置路由的活跃的样式 默认类名为 router-link-active
- 重定向的话:就是在vue路由规则配置之中,添加一个对象
{ path: "/", redirect: "/login" }
<div id="app">
<!-- router-link-active 当你点击的路由链接的时候,自动给你添加了这个类名!因此可以在这个类名上添加活跃的样式! -->
<router-link to="/login">登录</router-link>
<router-link to="/reg">注册</router-link>
<router-view></router-view>
</div>
<script src="../vue.js"></script>
<script src="https://unpkg.com/vue-router@2.0.0/dist/vue-router.js"></script>
<script>
//定义登录和注册的路由对象
const login = {
template: "<div>登录组件</div>",
}
const reg = {
template: "<div>注册组件</div>"
}
const router = new VueRouter({
routes: [{
path: "/",
redirect: "/login"
},
{
path: "/login",
component: login
}, {
path: "/reg",
component: reg
}
],
linkActiveClass: "my-active" //配置路由的活跃的样式 默认类名为 router-link-active
})
new Vue({
el: "#app",
data: {},
methods: {},
router
})
</script>
路由的传递参数
- 注意点:不管如何,都是在route组件的传递参数,那么其存储的值在于route之中!,而this可以省略!
- 第一种方式:?参数
- 在router-link中的to属性中以?后面拼接参数,不需要修改路由规则!
<router-link to="/login?id=10">登录</router-link>
- 获取?后面的参数 => 这是因为在路由规则下的参数,存储在route之中!
this.$route.query.id
id还是其他的参数等!
- 在router-link中的to属性中以?后面拼接参数,不需要修改路由规则!
- 第二种方式:/:id/:name
- 在router-link中的to属性中以/:id/:name后面拼接参数,不需要修改路由规则!
<router-link to="/login/10/asx">登录</router-link>
- 获取这种方式的参数:
this.$route.params
- 在router-link中的to属性中以/:id/:name后面拼接参数,不需要修改路由规则!
- 第三种方式:开启一个props传递参数
- (在需要传递参数的组件中把props设置为true)
{ path: "/login/:id/:name", component: login, props: true //开启props传递参数! }
- 引用的时候,在路由对象之中使用一个props数组的形式存储这些参数 然后可以使用!
props: ["id", "name"], template: "<div>登录组件 {{id}}--{{name}}</div>",
- (在需要传递参数的组件中把props设置为true)
方式1:?参数
<div id="app">
<!-- router-link-active 当你点击的路由链接的时候,自动给你添加了这个类名!因此可以在这个类名上添加活跃的样式! -->
<router-link to="/login?id=10">登录</router-link>
<router-link to="/reg">注册</router-link>
<router-view></router-view>
</div>
<script>
//定义登录和注册的路由组件对象
const login = { //注意点:在组件之中,也有生命周期函数
template: "<div>登录组件 {{ this.$route.query.id}}</div>",
created() {//这是data和methods初始化后的!
console.log(this.$route.query)
}
}
const reg = {
template: "<div>注册组件</div>"
}
const router = new VueRouter({
routes: [{
path: "/",
redirect: "/login"
},
{
path: "/login",
component: login
}, {
path: "/reg",
component: reg
}
],
linkActiveClass: "my-active" //配置路由的活跃的样式 默认类名为 router-link-active
})
new Vue({
el: "#app",
data: {},
methods: {},
router
})
</script>
方式2:/:id/:name
<div id="app">
<!-- router-link-active 当你点击的路由链接的时候,自动给你添加了这个类名!因此可以在这个类名上添加活跃的样式! -->
<router-link to="/login/10/asx">登录</router-link>
<router-link to="/reg">注册</router-link>
<router-view></router-view>
</div>
<script>
//定义登录和注册的路由对象
const login = { //注意点:在组件之中,也有生命周期函数
template: "<div>登录组件 {{ $route.params.id}}--{{ this.$route.params.name}}</div>",
created() {
console.log(this.$route.params)
}
}
const reg = {
template: "<div>注册组件</div>"
}
const router = new VueRouter({
routes: [{
path: "/",
redirect: "/login"
},
{
path: "/login/:id/:name",
component: login
}, {
path: "/reg",
component: reg
}
],
linkActiveClass: "my-active" //配置路由的活跃的样式 默认类名为 router-link-active
})
new Vue({
el: "#app",
data: {},
methods: {},
router
})
</script>
方式3
<div id="app">
<!-- router-link-active 当你点击的路由链接的时候,自动给你添加了这个类名!因此可以在这个类名上添加活跃的样式! -->
<router-link to="/login/10/asx">登录</router-link>
<router-link to="/reg">注册</router-link>
<router-view></router-view>
</div>
<script>
//定义登录和注册的路由对象
const login = { //注意点:在组件之中,也有生命周期函数
props: ["id", "name"],
template: "<div>登录组件 {{id}}--{{name}}</div>",
created() {
console.log(this);
}
}
const reg = {
template: "<div>注册组件</div>"
}
const router = new VueRouter({
routes: [{
path: "/",
redirect: "/login"
},
{
path: "/login/:id/:name",
component: login,
props: true //开启props传递参数!
}, {
path: "/reg",
component: reg
}
],
linkActiveClass: "my-active" //配置路由的活跃的样式 默认类名为 router-link-active
})
new Vue({
el: "#app",
data: {},
methods: {},
router
})
</script>
路由的嵌套
- 在router对象里面的routes(路由规则)里面定义每一个路由规则,但是路由规则内还有子路由规则,那么需要使用到children属性了
注意点:就是使用children属性定义的子路由,证明是在当前路由的之路由了,因此所匹配的组件路径,不需要添加 /const router = new VueRouter({ routes: [{ //routes:定义路由规则 children:定义的是子路由规则 在children内的路径不需要添加/ 因为children已经代表是当前路由孩子了! path: "/account", component: account, children: [ { path: "login", component: login }] }] })
<div id="app">
<router-link to="/account">显示账号组件</router-link>
<router-link to="/newlist">显示新闻组件</router-link>
<router-view></router-view>
</div>
<template id="account">
<div class="account">
<!-- 这是路由的链接 -->
<router-link to="/account/login">登录</router-link>
<router-link to="/account/reg">注册</router-link>
<!-- 这是路由匹配后,显然的容器 -->
<router-view></router-view>
</div>
</template>
<template id="login">
<div>这是登录组件</div>
</template>
<template id="reg">
<div>
这是注册组件
</div>
</template>
<script src="../vue.js"></script>
<script src="https://lib.baomitu.com/vue-router/3.1.3/vue-router.min.js"></script>
<script>
// 显示账号组件
const account = {
template: "#account",
}
// 新闻列表的组件
const newlist = {
template: `
<div class="newlist">新闻列表组件</div>
`
}
//登录组件对象
const login = {
template: "#login"
}
//注册组件对象
const reg = {
template: "#reg"
}
const router = new VueRouter({
routes: [{ //routes:定义路由规则 children:定义的是子路由规则 在children内的路径不需要添加/ 因为children已经代表是当前路由孩子了!
path: "/account",
component: account,
children: [{
path: "/",
redirect: "login"
}, {
path: "login",
component: login
}, {
path: "reg",
component: reg
}]
},
{
path: "/newlist",
component: newlist
}
]
})
new Vue({
el: "#app",
data: {},
methods: {},
router
})
</script>
路由懒加载
- 打包构建项目的时候,js包会变得越来越大,影响页面的加载速度
- 因此可以使用路由的懒加载方式处理,就是用到的时候就加载(把路由模块分为几个模块)
- 比如首页 - 我的 - 购物车 - 商品列表 (这是个大的路由,分为4个打包模块!)
const Home = ()=> import("路径")
然后把Home组件,在路由规则之中配置!
路由的传递参数 => 方式之编程式导航
- 声明式导航
- 编程式导航
方式1 某个组件之中.vue => 编程式导航
- 需求:点击新闻,跳转到新闻这个路由,并且传递id过去
<!-- 声明式的路由导航 借助内部组件 router-link-->
<router-link to="/news/20">新闻</router-link>
<router-link to="/profile/222/菲菲">档案</router-link>
<!-- 编程式的按钮 -->
<button @click="goNews(122)">新闻</button>
<button @click="goProfile(222,'啦啦')">档案</button>
<router-view></router-view>
- 编程式导航的处理 跳转
methods: {
goNews(id) {
this.$router.push({
name: "News",
params: { id },
});
},
goProfile(id, name) {
this.$router.push({
name: "Profile",
params: { id, name },
});
},
},
- 在具体组件之中接受参数Profile.vue
<template>
<div>
我是档案
{{$route.params.id}} --- {{$route.params.name}}
<router-view></router-view>
</div>
</template>
- 路由的配置
const routes = [{
path: '/',
name: 'Home',
component: Home
},{
path: '/profile/:id/:name',
name: 'Profile',
component: () => import('../views/Profile.vue')
}, {
path: '/news/:id',
name: 'News',
component: () => import('../views/News.vue')
}
]
路由导航守卫
- 官网:
https://router.vuejs.org/zh/guide/advanced/navigation-guards.html#%E5%85%A8%E5%B1%80%E5%89%8D%E7%BD%AE%E5%AE%88%E5%8D%AB
- 关于更新你点击的页面,显示对应的标题!
- 这就需要在监听路由的跳转,实时的显示对应的标题!
全局前置路由守卫 => 带有next()
- route/index.js文件
- 01:需要在路由配置的时候,设置一个meta对象,里面有着title属性 => 这是关于需要显示的title
- 02:需要使用路由守卫, => 取出从哪里跳转到哪里路由的title属性
- to => 去往那个路由
- 由于to去往的路由,可能存在路由的嵌套,那么最好的话,使用
to.matched[0] 取出第一个路由
- 由于to去往的路由,可能存在路由的嵌套,那么最好的话,使用
- from => 从那个路由跳转
- next() => 就是一个管道运输,执行下一个的钩子函数,如果全部钩子执行完了,则导航的状态就是 confirmed (确认的)。
//路由守卫
router.beforeEach((to, from, next) => {
document.title = to.matched[0].meta.title
<!-- document.title = to.meta.title -->
next();
})
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes = [{
path: '/',
name: 'Home',
meta: {
title: "首页"
},
component: Home
}, {
path: '/profile/:id/:name',
name: 'Profile',
meta: {
title: "档案"
},
component: () => import('../views/Profile.vue')
}, {
path: '/news',
name: 'News',
meta: {
title: "新闻"
},
component: () => import('../views/News.vue')
}
]
const router = new VueRouter({
// mode: 'history',
// base: process.env.BASE_URL,
routes
})
//路由守卫
router.beforeEach((to, from, next) => {
document.title = to.matched[0].meta.title
next();
})
export default router