第九节:Vue-router 路由
文章目录
1、简介:
路由的本质就是一种对应关系,比如说我们在url地址中输入我们要访问的url地址之后,浏览器要去请求这个url地址的对应资源,那么url地址和真是的资源之间就有一种对应的关系,这就是路由。路由分为前端路由和后端路由。
前端路由:
前端路由是依靠hash值【锚链接】的变化进行实现,前端路由的基本概率是根据不通的时间来显示不通的页面内容,即事件与事件处理函数之间的对应关系,前端路由主要做的事情就是监听事件并分发执行处理函数。
后端路由:
后端路由是由服务器进行实现,并完成资源分发,后端路由性能相对于前端来说叫低,所以我们前端学的的主要还是前端路由。
前端路由 Vue-Router:
Vue Router 是一个由VueJS官方提供的路由管理器,是一个功能更加强大的前端路由器,推荐使用,Vue Router和Vue.js非常契合,可以一起方便的实现SPA【single page web application,单页面应用程序】应用程序的开发,Vue Router 依赖于Vue,所以使用Vue-router 需要先引入Vue,在引入Vue Router。
2、Vue Router 的特性
- 支持H5历史模式或者hash模式。
- 支持嵌套路由。
- 支持路由参数
- 支持编程式路由
- 支持命名路由
- 支持路由导航守卫
- 支持路由过渡动画特效
- 支持路由懒加载
- 支持路由滚动行为
3、Vue Router 使用步骤
- 到入依赖 js 文件
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script> <script src="./vue-router.js"></script>
- 添加路由链接:是路由中提供的标签,默认会被渲染为a标签,to属性默认被渲染为href属性,to属性的值会被渲染为#开头的hash地址 例如:http://localhost:8080/#/about
<router-link class="link" to="/">Go to Index</router-link> <router-link class="link" to="/home">Go to Home</router-link> <router-link class="link" to="/about">Go to About</router-link>
- 添加路由填充位 【路由占位符】
<router-view></router-view>
- 定义路由组件. 也可以从其他文件导入
const index = { template: '<div>首页</div>' } const Home = { template: '<div>Home</div>' } const About = { template: '<div>About</div>' }
- 定义一些路由,每个路由都需要映射到一个组件。配置路由规则并创建路由实例
const myRouter = new VueRouter({ routes: [ { path: '/', component: index }, { path: '/home', component: Home }, { path: '/about', component: About }, ] })
- 将路由挂载到Vue实例中
const vm = new Vue({ el: "#app", router: myRouter, data () { return { about: "Vue-router 路由", } } })
4、Vue-Router 案例
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script src="./vue-router.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
h1 {
height: 100px;
line-height: 100px;
}
#app {
text-align: center;
}
.link {
padding: 0 20px;
}
.routerview {
height: 100px;
line-height: 100px;
border: 1px solid #000;
}
</style>
</head>
<body>
<div id="app">
<h1>{{about}}</h1>
<p>
<router-link class="link" to="/">Go to Index</router-link>
<router-link class="link" to="/home">Go to Home</router-link>
<router-link class="link" to="/about">Go to About</router-link>
</p>
<router-view class="routerview"></router-view>
</div>
</body>
</html>
<script>
const index = { template: '<div>this is Index page </div>' }
const Home = { template: '<div>this id Home page</div>' }
const About = { template: '<div>this is About page</div>' }
const myRouter = new VueRouter({
routes: [
{ path: '/', component: index },
{ path: '/home', component: Home },
{ path: '/about', component: About },
]
})
const vm = new Vue({
el: "#app",
router: myRouter,
data () {
return {
about: "Vue-router 路由",
}
}
})
</script>
5、跳转连接、路由出口
路由配置好之后,基本就和一般的跳转地址一样操作就可以了。可以在地址栏输入对应的配置的地址进行跳转。也可以通过
<router-link to="path">
进行像a标签一样的跳转,路由的出口需要设置在父路由的模板中<router-view></router-view>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script src="./vue-router.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
h1 {
height: 100px;
line-height: 100px;
}
#app {
text-align: center;
}
.link {
padding: 0 20px;
}
</style>
</head>
<body>
<div id="app">
<h1>{{about}}</h1>
<p>
<!-- 设置跳转连接 -->
<router-link class="link" to="/">Go to Index</router-link>
<router-link class="link" to="/home">Go to Home</router-link>
<router-link class="link" to="/about">Go to About</router-link>
<router-link class="link" to="/login">Go to Login</router-link>
</p>
<!-- 设置路由出口 没有路由出口子模板中内容不会显示 相当于一个iframe窗口中显示的html换成了模块 -->
<router-view></router-view>
</div>
</body>
</html>
<script>
// 路由模板
const Index = { template: '<div>this is Index page </div>' }
const Home = { template: '<div>this id Home page</div>' }
const About = { template: '<div>this is About page</div>' }
const Login = {
data () {
return {
about: "This is Login page"
}
},
template: `<div>
<h1>{{about}}</h1>
<hr>
<p>
<router-link to="/login/account">Go to Account</router-link>
<router-link to="/login/phone">Go to Phone</router-link>
</p>
<router-view></router-view>
</div>`
}
// 嵌套路由
const Account = {
data () {
return {
user: {
userName: "xiaoge",
userPwd: "123456"
}
}
},
template: `<div>
<p>
<label> 用户名:</label>
<input type='text' id="account" name="account" v-model="user.userName">
</p>
<p>
<label> 密 码:</label>
<input type='text' id="pwd" name="pwd" v-model="user.userPwd">
</p>
</div>`
}
const Phone = {
template: `<div>
<img src="" width="100px" height="100px" style="border:1px solid red;">
</div>`
}
const myRouter = new VueRouter({
routes: [
{ path: '/', component: Index },
{ path: '/home', component: Home },
{ path: '/about', component: About },
{
path: '/login',
component: Login,
children: [
{ path: '/login/account', component: Account },
{ path: '/login/phone', component: Phone },
]
},
]
})
const vm = new Vue({
el: "#app",
router: myRouter,
data () {
return {
about: "Vue-router 路由",
}
}
})
</script>
6、路由分类
- 嵌套路由
嵌套路由最关键的代码在于理解子级路由的概念:比如我们有一个/login的路由 那么/login下面还可以添加子级路由,如: /login/account /login/phone
- 动态路由
动态路由是通过、/ :参数名 的形式传递参数 $route.params.参数名读取 也可以通过props来传递参数、
- 命名路由
给路由取别名
- 编程式导航
调用js的api方法实现导航
6.1、嵌套路由
嵌套路由主要由children实现路由嵌套。
语法:
const myRouter = new VueRouter({ routes: [ { path: '/', component: Index }, { path: '/home', component: Home }, { path: '/about', component: About }, { path: '/login', component: Login, children: [ { path: '/login/account', component: Account }, { path: '/login/phone', component: Phone }, ] }, ] })
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script src="./vue-router.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
h1 {
height: 100px;
line-height: 100px;
}
#app {
text-align: center;
}
.link {
padding: 0 20px;
}
</style>
</head>
<body>
<div id="app">
<h1>{{about}}</h1>
<p>
<router-link class="link" to="/">Go to Index</router-link>
<router-link class="link" to="/home">Go to Home</router-link>
<router-link class="link" to="/about">Go to About</router-link>
<router-link class="link" to="/login">Go to Login</router-link>
</p>
<router-view></router-view>
</div>
</body>
</html>
<script>
// 路由模板
const Index = { template: '<div>this is Index page </div>' }
const Home = { template: '<div>this id Home page</div>' }
const About = { template: '<div>this is About page</div>' }
const Login = {
data () {
return {
about: "This is Login page"
}
},
template: `<div>
<h1>{{about}}</h1>
<hr>
<p>
<router-link to="/login/account">Go to Account</router-link>
<router-link to="/login/phone">Go to Phone</router-link>
</p>
<router-view></router-view>
</div>`
}
// 嵌套路由
const Account = {
data () {
return {
user: {
userName: "xiaoge",
userPwd: "123456"
}
}
},
template: `<div>
<p>
<label> 用户名:</label>
<input type='text' id="account" name="account" v-model="user.userName">
</p>
<p>
<label> 密 码:</label>
<input type='text' id="pwd" name="pwd" v-model="user.userPwd">
</p>
</div>`
}
const Phone = {
template: `<div>
<img src="" width="100px" height="100px" style="border:1px solid red;">
</div>`
}
const myRouter = new VueRouter({
routes: [
{ path: '/', component: Index },
{ path: '/home', component: Home },
{ path: '/about', component: About },
{
path: '/login',
component: Login,
children: [
{ path: '/login/account', component: Account },
{ path: '/login/phone', component: Phone },
]
},
]
})
const vm = new Vue({
el: "#app",
router: myRouter,
data () {
return {
about: "Vue-router 路由",
}
}
})
</script>
6.2、动态路由
动态路由主要是通过路由的方式传递参数。根据传递参数的个数可以选择:参数名 或者props方式传递,传递多个参数时推荐使用props传递。
/:参数名
传递参数:// $route.params.参数名接受参数 var loginTemplate = {template:`<div>用户名:{{$route.params.userName}}</div>`} var myRouter = new VueRouter({ // routes 路由数组 routes:[ // 通过 `/:参数名` 传递参数 {path:"/login/:userName",component:loginTemplate} ] }) // props:[] 通过props来接收参数 var loginTemplate = { props:["userName"], template:`<div>用户名:{{userName}}</div>` } var myRouter = new VueRouter({ // routes 路由数组 routes:[ // 通过 `/:参数名` 传递参数 // 如果props设置为true,route.params 将会被设置为组件属性 template中props才能接受到数据 { path:"/login/:userName", component:loginTemplate, props:true } ] }) // 还有一种情况,我们可以将props设置为对象,那么就直接将对象的数据传递给组件进行使用 const login = { props: ["userName", "userPwd"], template: `<div> <p> <label> 用户名:{{$route.params.userName}}</label> <input type='text' id="account" name="account" v-model="userName"> </p> <p> <label> 密 码:{{$route.params.userPwd}}</label> <input type='text' id="pwd" name="pwd" v-model="userPwd"> </p> </div>` } const myRouter = new VueRouter({ routes: [ { path: '/login', component: login, props: { userName: 'xiaoge', userPwd: 123456 } } ] }) // 如果想要获取传递的参数值还想要获取传递的对象数据,那么props应该设置为函数形式。 const login = { props: ["userName", "userPwd"], template: `<div> <p> <label> 用户名:</label> <input type='text' id="account" name="account" v-model="userName"> </p> <p> <label> 密 码:</label> <input type='text' id="pwd" name="pwd" v-model="userPwd"> </p> </div>` } const myRouter = new VueRouter({ routes: [ { path: '/login', component: login, // props: (function () { // return { // userName: "xiaoge", // userPwd: 1234567 // } // })() props: (route) => { return { userName: "xiaoge", userPwd: 1234567 } } } ] })
/:参数名传递参数
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script src="./vue-router.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
h1 {
height: 100px;
line-height: 100px;
}
#app {
text-align: center;
}
.link {
padding: 0 20px;
}
p {
height: 50px;
}
button {
padding: 0 20px;
}
</style>
</head>
<body>
<div id="app">
<h1>{{about}}</h1>
<p>
<router-link class="link" to="/login">Go to Login</router-link>
</p>
<router-view></router-view>
</div>
</body>
</html>
<script>
const login = {
props: ["userName", "userPwd"],
template: `<div>
<p>
<label> 用户名:{{$route.params.userName}}</label>
<input type='text' id="account" name="account" v-model="userName">
</p>
<p>
<label> 密 码:{{$route.params.userPwd}}</label>
<input type='text' id="pwd" name="pwd" v-model="userPwd">
</p>
</div>`
}
const myRouter = new VueRouter({
routes: [
{
path: '/login/:userName/:userPwd/',
component: login,
props: true
}
]
})
const vm = new Vue({
el: "#app",
router: myRouter,
data () {
return {
id: 123,
about: "动态路由 Vue-router",
}
}
})
</script>
6.3、命名路由
命名路由就是给路由取别名。通过name属性实现。命名路由的作用就是方便管理,当我们有很多个路由的时候可以通过命名来辨别。
const myRouter = new VueRouter({
routes: [
{
path: ‘/login’
component: login,
name:loginpage
}
]
})
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script src="./vue-router.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
h1 {
height: 100px;
line-height: 100px;
}
#app {
text-align: center;
}
.link {
padding: 0 20px;
}
p {
height: 50px;
}
button {
padding: 0 20px;
}
</style>
</head>
<body>
<div id="app">
<h1>{{about}}</h1>
<p>
<router-link class="link" to="/login">Go to Login</router-link>
</p>
<router-view></router-view>
</div>
</body>
</html>
<script>
const login = {
props: ["userName", "userPwd"],
template: `<div>
<p>
<label> 用户名:</label>
<input type='text' id="account" name="account" v-model="userName">
</p>
<p>
<label> 密 码:</label>
<input type='text' id="pwd" name="pwd" v-model="userPwd">
</p>
</div>`
}
const myRouter = new VueRouter({
routes: [
{
path: '/login',
component: login,
name: "loginindex",
props: (route) => {
return {
userName: "xiaoge",
userPwd: 1234567
}
}
}
]
})
const vm = new Vue({
el: "#app",
router: myRouter,
data () {
return {
id: 123,
about: "动态路由 Vue-router",
}
}
})
</script>
6.4、编程式导航
调用js的api方法实现导航
- this.$router.push(“hash地址”)
- this.$router.push(“/login”)
- this.$router.push({name:“login”,params:{userName:‘xiaoge’,pwd:123456}})
- this.$router.push({path:“/login”})
- this.$router.push({path:“/login”,query:{userName:“xiaoge”}})
- this.$router.go(0)
- this.$router.go(1)
- this.$router.go(-1)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script src="./vue-router.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
h1 {
height: 100px;
line-height: 100px;
}
#app {
text-align: center;
}
.link {
padding: 0 20px;
}
p {
height: 50px;
}
button {
height: 30px;
padding: 0 20px;
}
</style>
</head>
<body>
<div id="app">
<h1>{{about}}</h1>
<p>
<router-link class="link" to="/">Go to Index</router-link>
<router-link class="link" to="/home">Go to Home</router-link>
<router-link class="link" to="/about">Go to About</router-link>
<router-link class="link" to="/login">Go to Login</router-link>
</p>
<router-view></router-view>
</div>
</body>
</html>
<script>
// 路由模板
const Index = { template: '<div>this is Index page </div>' }
const Home = { template: '<div>this id Home page</div>' }
const About = { template: '<div>this is About page</div>' }
const Login = {
data () {
return {
about: "This is Login page"
}
},
template: `<div>
<h1>{{about}}</h1>
<hr>
<p>
<router-link to="/login/account">Go to Account</router-link>
<router-link to="/login/phone">Go to Phone</router-link>
</p>
<router-view></router-view>
</div>`
}
// 嵌套路由
const Account = {
data () {
return {
user: {
userName: "xiaoge",
userPwd: "123456"
}
}
},
template: `<div>
<p>
<label> 用户名:</label>
<input type='text' id="account" name="account" v-model="user.userName">
</p>
<p>
<label> 密 码:</label>
<input type='text' id="pwd" name="pwd" v-model="user.userPwd">
</p>
<p>
<button @click="funcRouterChange">提交</button>
</p>
</div>`,
methods: {
funcRouterChange: function () {
console.log(this.user.userName, this.user.userPwd)
this.$router.push("/home")
}
},
}
const Phone = {
template: `<div>
<img src="" width="100px" height="100px" style="border:1px solid red;">
</div>`
}
const myRouter = new VueRouter({
routes: [
{ path: '/', component: Index },
{ path: '/home', component: Home },
{ path: '/about', component: About },
{
path: '/login',
component: Login,
children: [
{ path: '/login/account', component: Account },
{ path: '/login/phone', component: Phone },
]
},
]
})
const vm = new Vue({
el: "#app",
router: myRouter,
data () {
return {
about: "Vue-router 路由",
}
}
})
</script>
7、重定向
当打开某个路由地址之后想要默认的跳转到某个地址的时候可以使用重定向
// 访问 跟路径('/')的时候会自动重定向到 ('/page-a')
{
path:'/',
redirect: '/index'
},
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>IndexPage</title>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script src="./js/vue-router.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
h1 {
height: 100px;
line-height: 100px;
}
#app {
text-align: center;
}
.link {
padding: 0 20px;
}
p {
height: 50px;
}
button {
height: 30px;
padding: 0 20px;
}
</style>
</head>
<body>
<div id="app">
<h1>{{about}}</h1>
<p>
<router-link class="link" to="/">Go to Index</router-link>
<router-link class="link" to="/home">Go to Home</router-link>
<router-link class="link" to="/about">Go to About</router-link>
<router-link class="link" to="/login">Go to Login</router-link>
</p>
<router-view></router-view>
</div>
</body>
</html>
<script>
// 路由模板
const Index = { template: '<div>this is Index page </div>' }
const Home = { template: '<div>this id Home page</div>' }
const About = { template: '<div>this is About page</div>' }
const Login = {
data () {
return {
about: "This is Login page"
}
},
template: `<div>
<h1>{{about}}</h1>
<hr>
<p>
<router-link to="/login/account">Go to Account</router-link>
<router-link to="/login/phone">Go to Phone</router-link>
</p>
<router-view></router-view>
</div>`
}
// 嵌套路由
const Account = {
data () {
return {
user: {
userName: "xiaoge",
userPwd: "123456"
}
}
},
template: `<div>
<p>
<label> 用户名:</label>
<input type='text' id="account" name="account" v-model="user.userName">
</p>
<p>
<label> 密 码:</label>
<input type='text' id="pwd" name="pwd" v-model="user.userPwd">
</p>
<p>
<button @click="funcRouterChange">提交</button>
</p>
</div>`,
methods: {
funcRouterChange: function () {
console.log("login:" + this.user.userName, this.user.userPwd)
this.$router.push("/")
}
},
}
const Phone = {
template: `<div>
<img src="./img/vue-login.jpg" width="100px" height="100px" style="border:1px solid red;">
</div>`
}
// 在配置单个路由中 redirect 和 meta 没有同时存在的必要 当我们使用重定向后 会重定向到新页面 meta 不会映射到重定向的路由中生效
// 重定向的用途主要用于父路由指定默认显示的子路由地址
const myRouter = new VueRouter({
routes: [
{
path: '/',
component: Index,
redirect: "IndexPage",
},
{
path: '/home',
component: Home,
meta: {
title: "HomePage"
},
},
{
path: '/about',
component: About,
meta: {
title: "AboutPage"
}
},
{
path: '/login',
component: Login,
redirect: "/login/account",
children: [
{
path: '/login/account',
component: Account,
meta: {
title: "LoginPage"
}
},
{ path: '/login/phone', component: Phone },
]
},
]
})
myRouter.beforeEach((to, from, next) => {
var title = to.meta.title;// 从即将要进入的路由对象中获取title
if (title) {
document.title = title;// 动态设置当前的title
}
next();// 必须调用
});
const vm = new Vue({
el: "#app",
router: myRouter,
data () {
return {
about: "Vue-router 路由 redirect 重定向",
}
}
})
</script>
8、路由修改标题
由于vue是单页面的应用,所以当进行界面跳转的时候无法正常的进行网页标题修改。但是我们可以借助
导航守卫
来动态的修改title
语法:
const myRouter = new VueRouter({ routes: [{ path: '/about', component: About, meta: { title: "LoginPage"// 通过路由修改标题 设置标题名称 } },] }) //注册一个全局导航守卫 /* 全局守卫的钩子函数将会在路由地址发生改变的时候进行调用,其有三个参数 1. to:即将要进入的路由对象 2. from:即将要离开的路由对象 3. next:进入下一个钩子的函数。必须调用 */ myRouter.beforeEach((to, from, next) => { var title = to.meta.title;// 从即将要进入的路由对象中获取title if (title) { document.title = title;// 动态设置当前的title } next();// 必须调用 });
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Vue</title>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script>
<script src="./vue-router.js"></script>
<style>
* {
margin: 0;
padding: 0;
}
h1 {
height: 100px;
line-height: 100px;
}
#app {
text-align: center;
}
.link {
padding: 0 20px;
}
</style>
</head>
<body>
<div id="app">
<h1>{{about}}</h1>
<p>
<!-- 设置跳转连接 -->
<router-link class="link" to="/">Go to Index</router-link>
<router-link class="link" to="/home">Go to Home</router-link>
<router-link class="link" to="/about">Go to About</router-link>
<router-link class="link" to="/login">Go to Login</router-link>
</p>
<!-- 设置路由出口 没有路由出口子模板中内容不会显示 相当于一个iframe窗口中显示的html换成了模块 -->
<router-view></router-view>
</div>
</body>
</html>
<script>
// 路由模板
const Index = { template: '<div>this is Index page </div>' }
const Home = { template: '<div>this id Home page</div>' }
const About = { template: '<div>this is About page</div>' }
const Login = {
data () {
return {
about: "This is Login page"
}
},
template: `<div>
<h1>{{about}}</h1>
<hr>
<p>
<router-link to="/login/account">Go to Account</router-link>
<router-link to="/login/phone">Go to Phone</router-link>
</p>
<router-view></router-view>
</div>`
}
// 嵌套路由
const Account = {
data () {
return {
user: {
userName: "xiaoge",
userPwd: "123456"
}
}
},
template: `<div>
<p>
<label> 用户名:</label>
<input type='text' id="account" name="account" v-model="user.userName">
</p>
<p>
<label> 密 码:</label>
<input type='text' id="pwd" name="pwd" v-model="user.userPwd">
</p>
</div>`
}
const Phone = {
template: `<div>
<img src="" width="100px" height="100px" style="border:1px solid red;">
</div>`
}
const myRouter = new VueRouter({
routes: [
{ path: '/', component: Index },
{ path: '/home', component: Home },
{
path: '/about',
component: About,
meta: {
title: "LoginPage"
}
},
{
path: '/login',
component: Login,
children: [
{ path: '/login/account', component: Account },
{ path: '/login/phone', component: Phone },
]
},
]
})
//注册一个全局导航守卫
/*
全局守卫的钩子函数将会在路由地址发生改变的时候进行调用,其有三个参数
1. to:即将要进入的路由对象
2. from:即将要离开的路由对象
3. next:进入下一个钩子的函数。必须调用
*/
myRouter.beforeEach((to, from, next) => {
var title = to.meta.title;// 从即将要进入的路由对象中获取title
if (title) {
document.title = title;// 动态设置当前的title
}
next();// 必须调用
});
const vm = new Vue({
el: "#app",
router: myRouter,
data () {
return {
about: "Vue-router 路由",
}
}
})
</script>