# 前端路由
# 直接操作DOM元素
直接操作DOM元素流程
- ref属性给DOM元素起一个别名
- this.$refs.别名
直接操作组件实例
- ref属性给组件元素起一个别名
- this.$refs.别名
Vue.component('my-test', {
template: `
<div>
<div>测试ref操作组件实例</div>
<div>{{msg}}</div>
</div>
`,
data () {
return {
msg: 'ref测试信息'
}
},
methods: {
handleClick () {
console.log(this.msg)
}
}
})
<my-test ref='mytestcom'></my-test>
// 从组件外部访问组件内部的信息,所以必须得到组件实例
const mytest = this.$refs.mytestcom
// 只要能够获取组件的实例对象,那么就可以通过该对象获取组件的内部成员(包括属性和方法)
mytest.handleClick()
# SPA介绍
spa 是 single page application 简写,意思是单页面应用程序。vue适合开发spa类型的项目。
优点:
- 业务场景的切换,性能很好。
- 集中维护一个网站的功能。
- 完全的前后端分离(前后端可以并行开发,提供系统开发效率)
缺点:
- 所有的功能集中的一个页面,依赖的资源是非常多的,加载第一次的时候很慢(首屏加载)。
- 业务复杂度很高(解决方案:vue组件,前端路由---支持浏览器地址栏的回退功能)
# 前端路由介绍
目标:熟悉前端路由的概念
前端路由要实现的效果:支持SPA项目的页面切换,并且支持浏览器地址栏的回退和前进功能
前端路由:根据不同的url地址,页面上展示不同的内容(根据url地址的不同显示不同的组件。)

点击菜单A/B/C,会导致浏览器地址栏链接的改变,以及组件显示区域内容的变化
菜单A链接 ------> 菜单A组件
菜单B链接 ------> 菜单B组件
菜单C链接 ------> 菜单C组件
# 前端路由原理
目标:基于hash的路由原理(通过地址栏hash字符串的改变,去更新页面的内容。)
- http://localhost:3000?username=lisi#abc
- http://localhost:3000?username=lisi#hello
- 锚点(hash 哈希)作用:跳转到网页的某一个位置
- 锚点的变化是否会导致浏览器重新向服务器发送一个请求?不会
- 但是我们可以利用这个特点,实现锚点的变化导致页面的更新
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div>
<a href="#/top">头条</a>
<a href="#/tech">科技</a>
<a href="#/edu">教育</a>
</div>
<div id="area">
<!-- 显示组件的位置 -->
</div>
<script>
// 我们希望点击a标签时,实现页面内容的变化
// 我们如何知道点击了哪个菜单?
const div = document.getElementById('area')
window.onhashchange = function () {
// 该事件是原生js提供的事件,hash发生变化时自动触发
// 获取对应的hash值,从而判断要显示什么内容
switch(location.hash) {
case '#/top':
// 显示头条频道内容
div.innerHTML = '头条信息'
break;
case '#/tech':
// 显示科技频道内容
div.innerHTML = '科技信息'
break;
case '#/edu':
// 显示教育频道内容
div.innerHTML = '教育信息'
break;
}
}
</script>
</body>
</html>
# vue-router
# 基本介绍
目标:熟悉vue-router基本信息
vue-router提供一套完善的强大的前端路由控制逻辑,可以快速的基于它实现vue项目开发。
vue-router (opens new window)是基于vue的js插件,实现了前端路由功能。
下载地址:https://unpkg.com/vue-router/dist/vue-router.js
# 基本使用
目标:基于url地址的变化实现组件的切换
- 准备组件(用于路由链接变化是切换显示)
- 定义路由映射规则(什么路径对应什么组件)
- 初始化 vue-router 实例(配置路由和组件映射的关系)
- 需要把路由实例挂载到vue中(把路由和vue关联起来)
- 路由跳转链接
<router-link />(跳转的链接需要使用vue-router提供的标签实现) - 路由显示组件的位置
<router-view />(指定一个位置用于显示链接对应的组件)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- 5、配置路由的跳转链接 -->
<!-- to的值就是配置路由映射时,path属性的值 -->
<router-link to="/top">头条</router-link>
<router-link to="/tech">科技</router-link>
<router-link to="/edu">教育</router-link>
<div>
<!-- 6、配置路由组件的显示位置 -->
<router-view/>
</div>
</div>
<!-- 0、导入相关的js库文件 -->
<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<script>
// Vue.component('my-test', {
// template: ``
// })
// 1、准备路由组件
const Top = {
template: `
<div>
头条信息
</div>
`
}
const Tech = {
template: `
<div>
科技信息
</div>
`
}
const Edu = {
template: `
<div>
教育信息
</div>
`
}
// 2、定义路由映射规则
const routes = [
// path表示路由链接的路径
// component表示路由链接关联的组件
// path和component属性名称是vue-router规定的
{ path: '/top', component: Top },
{ path: '/tech', component: Tech },
{ path: '/edu', component: Edu }
]
// 3、初始化 vue-router 实例
const router = new VueRouter({
// (缩写) 相当于 routes: routes
// 冒号左侧的routes是固定的吗?是的
routes: routes
})
// 4、需要把路由实例挂载到vue中
new Vue({
el: '#app',
router,
// 冒号左侧的router是固定的吗?是的
// router: router,
data: {
msg: 'hello vue-router'
}
})
</script>
</body>
</html>
# 动态路由
目标:熟悉动态路由的用法
动态路由:根据不同的URL地址,映射到同一个组件,这样做主要是为了节省组件(简化代码)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- 路由链接 -->
<router-link to='/users/1'>张三</router-link>
<router-link to='/users/2'>李四</router-link>
<router-link to='/users/3'>王五</router-link>
<hr>
<div>
<!-- 路由填充位 -->
<router-view/>
</div>
</div>
<!-- 0、导入相关的js库文件 -->
<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<script>
// 动态路由
// 路由组件(获取动态路由参数)
// 通过$route.params可以获取动态路由参数
const UserInfo = {
template: `
<div>
<div>用户信息{{$route.params.id}}</div>
<div>用户信息{{userId}}</div>
<hr />
<ul>
<li>{{userInfo.id}}</li>
<li>{{userInfo.name}}</li>
<li>{{userInfo.age}}</li>
</ul>
</div>
`,
data () {
return {
// 所有用户数据
list: [{
id:1,
name: '张三',
age: 12
}, {
id:2,
name: '李四',
age: 13
}, {
id: 3,
name: '王五',
age: 14
}]
}
},
computed: {
userId () {
// console.log(this.$route.params)
return this.$route.params.id
},
userInfo () {
// 根据路由参数查询data中该用户的信息
// 根据路由参数中的id去数组list中查找id对应的用户信息(对象)
// const user = this.list.filter(item => {
// return parseInt(this.userId) === item.id
// })
// // 短路运算 user = [{id: 1, name: '张三', age: 12}]
// return user && user[0]
// ----------------------------
// 基于数组的find方法查询id匹配的数组中的结果
const user = this.list.find(item => {
return this.userId === item.id
})
return user
}
}
}
// 路由映射
const routes = [
// 如果path的路径这样写 /users/:id,那么可以匹配何种路径?
// /users/1
// /users/2
// /users/3
{ path: '/users/:id', component: UserInfo }
]
// 实例化路径组件
const router = new VueRouter({
routes
})
// 挂载路由
new Vue({
el: '#app',
router
})
</script>
</body>
</html>
总结:
- 路由映射规则
{ path: '/user/:id', component: UserInfo } - 获取路径传参:
<router-link to="/users/1">tom</router-link>
# 路由参数传递
目标:熟悉路由的参数传递方式
使用路由的时候,路由跳转的时候如何去进行传参?两种:
- Restful路径传参
/user/1001就是路径传参 - 查询字符串传参
/user?id=10001就是键值对传参
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<!--5、路由链接 -->
<!-- 基于Restful风格的方式传递路由参数 -->
<router-link to='/users/1'>张三</router-link>
<router-link to='/users/2'>李四</router-link>
<router-link to='/users/3'>王五</router-link>
<!-- 如下的写法:动态绑定to的值 -->
<!-- name需要在配置路由映射时设置 -->
<!-- params表示传递的动态路由的参数 -->
<!-- <router-link :to='{name: "user", params: {id: 4}}'>赵六</router-link> -->
<router-link :to='obj'>赵六</router-link>
<!-- ------------------------------------- -->
<!-- 基于查询字符串方式传递路由参数 -->
<!-- 这种形式的参数,在组件中通过$route.query获取 -->
<router-link to='/user?id=123&age=12'>小明</router-link>
<router-link :to='{path: "/user", query: {id: 456, age: 13}}'>小聪</router-link>
<router-link :to='{name: "abc", query: {id: 456, age: 13}}'>小萌</router-link>
<hr>
<div>
<!-- 6、路由填充位 -->
<router-view/>
</div>
</div>
<!-- 0、导入相关的js库文件 -->
<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<script>
// 路由的参数传递
// 1、路由组件(获取动态路由参数)
// 通过$route.params可以获取动态路由参数
const UserInfo = {
template: `
<div>
<div>用户信息{{$route.params.id}}</div>
</div>
`
}
const UserInfo1 = {
template: `
<div>
<div>用户信息1:{{$route.query.id}}</div>
</div>
`
}
// 2、路由映射
const routes = [
// name表示给path路径起一个别名
{ path: '/users/:id', name: 'user', component: UserInfo },
{ path: '/user', name: 'abc', component: UserInfo1 }
]
// 3、实例化路径组件
const router = new VueRouter({
routes
})
// 4、挂载路由
new Vue({
el: '#app',
data: {
obj: {
name: "user",
params: {
id: 4
}
}
},
router: router
})
</script>
</body>
</html>
总结:
- Restful风格
<!-- 基于Restful风格的方式传递路由参数 -->
<router-link to='/users/1'>张三</router-link>
<router-link to='/users/2'>李四</router-link>
<router-link to='/users/3'>王五</router-link>
<!-- 如下的写法:动态绑定to的值 -->
<!-- name需要在配置路由映射时设置 -->
<!-- params表示传递的动态路由的参数 -->
<!-- <router-link :to='{name: "user", params: {id: 4}}'>赵六</router-link> -->
<router-link :to='obj'>赵六</router-link>
- 查询字符串风格
<!-- 基于查询字符串方式传递路由参数 -->
<!-- 这种形式的参数,在组件中通过$route.query获取 -->
<router-link to='/user?id=123&age=12'>小明</router-link>
<router-link :to='{path: "/user", query: {id: 456, age: 13}}'>小聪</router-link>
<router-link :to='{name: "abc", query: {id: 456, age: 13}}'>小萌</router-link>
# 路由重定向
目标:熟悉路由重定向的配置方式
路由重定向:访问某一个路径,自动跳转到另外一个路径。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<!-- 如果这里只有一个路由填充位,那么可以通过浏览器的地址栏修改路径 -->
<router-view/>
</div>
<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<script>
// 路由重定向: 本来访问的是一个连接,然后立刻跳转到另一个链接
// Login和Home组件之间是什么关系:互斥关系
const Login = {
template: '<div>登录</div>'
}
const Home = {
template: '<div>主页</div>'
}
const router = new VueRouter({
routes: [
// 配置路由的重定向(如果浏览器访问/,那么自动跳转到/login)
{ path: '/', redirect: '/login'},
{ path: '/login', component: Login},
{ path: '/home', component: Home}
]
})
new Vue({
el: '#app',
router
})
</script>
</body>
</html>
# 编程式导航
目标:熟悉编程式导航实现路由跳转的方式
编程式导航:通过js的方式触发路由的跳转。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<router-view/>
</div>
<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<script>
// 编程式导航:通过js方式控制路由的跳转
const Login = {
template: `
<div>
<form>
<div>
用户名:
<input type="text" v-model='username'/>
</div>
<div>
密码:
<input type="text" v-model='password'/>
</div>
<div>
<input @click='handleLogin' type="button" value="提交" />
</div>
</form>
</div>
`,
data () {
return {
username: '',
password: ''
}
},
methods: {
handleLogin () {
// console.log(this.username, this.password)
// 实现登录功能
// 1、表单验证
// 2、调用接口实现登录
// 3、判断返回的状态,如果是成功的,跳转到主页面,否则,进行错误提示
// 假设ret是第2步返回的结果
const ret = {
// 登录成功
status: 0
}
if (ret.status === 0) {
// 登录成功,跳转到主页面
// this.$router.push方法是vue-router提供的,用于实现路由跳转
// push方法的参数一表示要跳转到的路由的路径
// 这里的$router不是$route
// 跳转到指定的路由路径
this.$router.push('/home')
console.log(this.$router)
// 向后跳转到之前的一个连接(相当于点击浏览器的回退按钮)
// this.$router.back()
// 向后跳转到下一个连接
// this.$router.forward()(相当于点击浏览器的前进按钮)
// 跳转到上/下第n个链接
// this.$router.go(-2)
}
}
}
}
const Home = {
template: '<div>主页</div>'
}
const router = new VueRouter({
routes: [
// 配置路由的重定向(如果浏览器访问/,那么自动跳转到/login)
{ path: '/', redirect: '/login'},
{ path: '/login', component: Login},
{ path: '/home', component: Home}
]
})
new Vue({
el: '#app',
router
})
</script>
</body>
</html>
总结:
$route获取路由相关信息(路由传参 this.$route.params, this.$route.query)$router提供路由相关函数 ( 跳转方法 this.$router.push() )
- 动态路由参数传递
// 编程是导航跳转时,是否可能从A组件传递数据给B组件?
this.$router.push({
path: 'home',
// 组件中获取query参数的方式this.$router.history.current.query
query: {
id: 123,
age: 12
},
// params是用于给【动态路由】传递参数
// params: {
// id: 456,
// age: 13
// }
})
- 获取路由参数
this.$router.history.current.query
# 嵌套路由
目标:熟悉嵌套路由的用法
要进行路由的嵌套,只需要在一级路由规则下,加上一个属性 children,即可定义二级路由规则。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="app">
<router-view/>
</div>
<script src="lib/vue.js"></script>
<script src="lib/vue-router.js"></script>
<script>
// 嵌套路由:在路由组件中再次配置路由的链接和路由填充位
const Login = {
template: `
<div>
<form>
<div>
用户名:
<input type="text" v-model='username'/>
</div>
<div>
密码:
<input type="text" v-model='password'/>
</div>
<div>
<input @click='handleLogin' type="button" value="提交" />
</div>
</form>
</div>
`,
data () {
return {
username: '',
password: ''
}
},
methods: {
handleLogin () {
// console.log(this.username, this.password)
// 实现登录功能
// 1、表单验证
// 2、调用接口实现登录
// 3、判断返回的状态,如果是成功的,跳转到主页面,否则,进行错误提示
// 假设ret是第2步返回的结果
const ret = {
// 登录成功
status: 0
}
if (ret.status === 0) {
// 登录成功,跳转到主页面
this.$router.push('/home')
}
}
}
}
// 一级路由组件
const Home = {
template: `
<div>
<div>主页</div>
<hr />
<router-link to='/home/tech'>科技</router-link>
<router-link to='/home/edu'>教育</router-link>
<div>
<!-- 二级路由填充位 -->
<router-view/>
</div>
</div>
`
}
const Tech = {template: '<div>科技</div>'}
const Edu = {template: '<div>教育</div>'}
const router = new VueRouter({
routes: [
// 配置路由的重定向(如果浏览器访问/,那么自动跳转到/login)
{ path: '/', redirect: '/login'},
{ path: '/login', component: Login},
{
path: '/home',
component: Home,
// children属性用于配置嵌套路由
children: [
// path后面的路由不要添加 /
{ path: 'tech', component: Tech},
{ path: 'edu', component: Edu}
]
}
]
})
new Vue({
el: '#app',
router
})
</script>
</body>
</html>
总结:
- 二级路由的路径前面不要添加斜杠
- 链接跳转的位置路径要写完整的 /home/tech
const router = new VueRouter({
routes: [
// 配置路由的重定向(如果浏览器访问/,那么自动跳转到/login)
{ path: '/', redirect: '/login'},
{ path: '/login', component: Login},
{
path: '/home',
component: Home,
// 通过路由重定向可以默认显示一个二级路由组件
redirect: '/home/tech',
// children属性用于配置嵌套路由
children: [
// path后面的路由不要添加 /
{ path: 'tech', component: Tech},
{ path: 'edu', component: Edu}
]
}
]
})
# 总结
- 直接操作组件的用法ref
- 前端路由
- 熟悉SPA应用的场景(介绍)
- 熟悉前端路由的概念(介绍)
- 理解前端路由的原理(理解)
- vue-router
- 熟悉vue-router的基本信息(介绍)
- 基本用法(6个步骤)
- 动态路由(多个路由链接映射到同一个组件,简化组件数量)
- 路由的参数传递
- Restful风格的参数(2种用法)
- 查询字符串形式的参数(2种用法)
- 路由重定向(本来访问一个连接,自动跳转到另一个链接)
- 编程式导航(用js的方法实现路由跳转并可以携带参数)
- 嵌套路由(实现更加复杂的页面结构并支持跳转)