1. SPA(Single Page Application)
- 比后端渲染有更好的性能
- Ajax 前端渲染,不支持浏览器的前进、后退操作
- SPA 单页面应用程序:整个系统只有一个页面,内容的变化是通过 Ajax 异步请求实现的局部刷新,同时支持浏览器地址栏的前进、后退操作
- 基于 URL 的 hash,是 SPA 的实现原理
- 前端路由是也 SPA 实现的基础
2. Vue-Router 的基本使用
代码实例
<!--1-1. 先引入 vue.js 文件 -->
<script src="js/vue.js"></script>
<!--1-2. 再引入 vue-router.js 文件 -->
<script src="js/vue-router.js"></script>
<div id="app">
<!--2. 添加路由链接 -->
<router-link to="/user">User</router-link>
<router-link to="/register">Register</router-link>
<!--3. 添加路由填充占位符 -->
<router-view></router-view>
</div>
<script>
// 4-1. 定义路由组件 --User 组件
const User = {template: '<h1>User 组件 </h1>'}
// 4-2. 定义路由组件 --Register 组件
const Register = {template: '<h1>Register 组件 </h1>'}
// 5. 创建 Vue-Router 组件对象并配置路由规则
const pathRouter = new VueRouter({
routes: [{path: '/user', component: User},
{path: '/register', component: Register}
]
});
const vm = new Vue({
el: '#app',
data: { },
// 6. 将 VueRouter 实例对象挂载到 Vue 实例对象上
router: pathRouter
});
</script>
2-1.Vue-Router 使用步骤:
- 引入
vue.js
和vue-router.js
文件,<script src="js/vue.js"></script>
要先于<script src="js/vue-router.js"></script>
引入,因为 Vue-Router 依赖 Vue - 使用
<router-link>
标签,添加路由连接,<router-link to="/user">User</router-link>
,Vue 默认情况下会把<router-link>
替换成<a>
,并且把to="/user"
替换成href="#/user"
- 使用
<router-view>
,Vue 会把<router-link>
的to
属性值对应的内容显示在<>router-view>
所在的位置处 - 根据 Vue 组件的声明语法,定义路由组件
- 创建 VueRouter 路由实例对象,并把第 4 步定义的路由组件配置到路由实例对象中
- 将 VueRouter 实例对象挂载到 Vue 实例对象上
2-2.Vue-Router 路由重定向功能
通过重定向功能,我们可以配置页面在首次打开时需要展示的内容,是在 2 -1.Vue-Router 使用步骤中第 4 步的定义路由组件中进行配置。如下添加:
// 创建 Vue-Router 组件对象
const pathRouter = new VueRouter({
routes: [{path: '/', redirect: '/user'}, // 路由重定向配置 将访问路径 '/' 的请求重定向到路径 /user' 上
{path: '/user', component: User},
{path: '/register', component: Register}
]
});
3.Vue-Router 路由嵌套
路由嵌套是指在一个路由组件渲染的页面中还有路由组件,实现代码示例
<script src="js/vue.js"></script>
<script src="js/vue-router.js"></script>
<div id="app">
<router-link to="/userLogin">User Login</router-link>
<router-link to="/register">User Register</router-link>
<router-view></router-view>
</div>
<script>
const userLogin = {template: '<h1> 用户登录 </h1>'}
const userRegister = {
template: `
<div>
<h1> 用户注册 </h1>
<hr/>
<router-link to="/register/link1">Link1</router-link>
<router-link to="/register/link2">Link2</router-link>
<router-view />
</div>
`
}
const link1 = {template: '<h3>link1</h3>'}
const link2 = {template: '<h3>link2</h3>'}
const pathRouter = new VueRouter({
routes: [{path: '/user', component: userLogin},
{path: '/register', component: userRegister, children: [{path: '/register/link1', component: link1},
{path: '/register/link2', component: link2}
]}
]
});
var vm = new Vue({
el: '#app',
data: { },
router: pathRouter
});
</script>
在路由定义规则中使用 children
来指定子路由的路由规则
{path: '/register', component: userRegister,
children: [{path: '/link1', component: link1},
{path: '/link2', component: link2}
]
}
3-1. 多级路由嵌套
如果有多级嵌套,可以继续嵌套,三级嵌套代码如下:
<script>
const userLogin = {template: '<h1> 用户登录 </h1>'}
const userRegister = {
template: `
<div>
<h1> 用户注册 </h1>
<hr/>
<router-link to="/register/link1">Link1</router-link>
<router-link to="/register/link2">Link2</router-link>
<router-view />
</div>
`
}
const link1 = {
template: `
<div>
<h3>link1</h3>
<hr/>
<router-link to="/register/link1/link1-1">Link1-1</router-link>
<router-link to="/register/link1/link1-2">Link1-2</router-link>
<router-view />
</div>`
}
const link2 = {template: '<h3>link2</h3>'}
const link1_1 = {template: '<h5>link1-1</h5>'}
const link1_2 = {template: '<h5>link1-2</h5>'}
const pathRouter = new VueRouter({
routes: [{path: '/user', component: userLogin},
{path: '/register', component: userRegister, children: [
{path: '/register/link1', component: link1, children: [{path: '/register/link1/link1-1', component: link1_1},
{path: '/register/link1/link1-2', component: link1_2}
]},
{path: '/register/link2', component: link2}
]}
]
});
</script>
在路由规则定义的代码出我们看到三级路由嵌套的代码:
routes: [{path: '/user', component: userLogin},
{path: '/register', component: userRegister,
children: [
{path: '/register/link1', component: link1,
children: [{path: '/register/link1/link1-1', component: link1_1},
{path: '/register/link1/link1-2', component: link1_2}
]
},
{path: '/register/link2', component: link2}
]
}
]
4.Vue-Router 动态路由匹配
有多个路径对应同一个路径组件的情况,Vue 提供了动态路由的功能,实现多个路径与一个路由组件的对应关系,代码如下:
<script src="./js/vue.js"></script>
<script src="./js/vue-router.js"></script>
<div id="app">
<router-link to="/page/1">Page1</router-link>
<router-link to="/page/2">Page2</router-link>
<router-link to="/page/3">Page3</router-link>
<router-link to="/query">Query</router-link>
<router-view></router-view>
</div>
<script>
var pageCom = {
template: `
<h1>Page {{$route.params.pid}}</h1>
`
}
var queryCom = {
template: `
<div>
<h1>Query Page</h1>
<hr/>
<router-link to="/query/1">Query 1</router-link>
<router-link to="/query/2">Query 2</router-link>
<router-view></router-view>
</div>
`
}
var queryPage = {template: '<h3>Query Page{{ $route.params.qid}}</h3>'
}
var router = new VueRouter({
routes: [{path: '/page/:pid', component: pageCom},
{path: '/query', component: queryCom,
children: [{path: '/query/:qid', component: queryPage}
]
}
]
});
var vm=new Vue({
el:'#app',
data:{},
methods:{},
router
});
</script>
对于路径 <router-link to="/page/1">Page1</router-link>
、<router-link to="/page/2">Page2</router-link>
和<router-link to="/page/3">Page3</router-link>
对应的路由组件是:
var pageCom = {
template: `
<h1>Page {{$route.params.pid}}</h1>
`
}
因此可以在 VueRouter 实例的路由规则中进行动态路由配置:
routes: [{path: '/page/:pid', component: pageCom},
...
}
在路由规则中的 :pid
是动态参数,根据路径不同,参数的取值也有所不同。对应的路由组件中 {{$route.params.pid}}
,其中 $route.params
是从 Vue-Router 获取参数的固定内容,.pid
要与路由规则中的动态参数名保持一致。
5. Vue-Router 参数传递
动态路由是有多个路径对应同一个路由组件,也就是对于路由组件来说,路径中有可变参数,而在路由组件中获取到路径中的可变参数是需要 {{route.params.[参数名]}}
来获取的。除了通过动态路由传递参数,Vue-Router 还提供了以下几种方式进行参数传递:
- 通过路由规则 props 属性值为布尔类型传递参数
- 通过路由规则 props 属性值为对象类型传递参数
- 通过路由规则 props 属性值为函数类型传递参数
5-1. props 属性值为布尔类型
代码示例
<script src="./js/vue.js"></script>
<script src="./js/vue-router.js"></script>
<div id="app">
<router-link to="/item/1"> 商品 1 </router-link>
<router-link to="/item/2"> 商品 2 </router-link>
<router-link to="/item/3"> 商品 3 </router-link>
<router-link to="/query"> 商品查询 </router-link>
<router-view></router-view>
</div>
<script>
var itemCom = {props: ['id'],
template: `
<div>
<h1> 商品{{id}}</h1>
</div>
`
}
var queryCom = {template: '<h1> 商品查询 </h1>'}
var router = new VueRouter({
routes: [{path: '/item/:id', component: itemCom, props: true},
{path: '/query/', component: queryCom}
]
});
var vm=new Vue({
el:'#app',
data:{},
methods:{},
router
});
</script>
上述代码中实现参数传递的主要配置是在路由规则里添加props: true
,同时需要在组件声明中添加props: ['id']
`
5-2. props 属性值为对象类型
代码示例
<div id="app">
<router-link to="/item/1"> 测试商品 1 </router-link>
<router-link to="/item/2"> 测试商品 2 </router-link>
<router-link to="/item/3"> 测试商品 3 </router-link>
<router-view></router-view>
</div>
<script>
const itemCom = {props: ['id', 'name', 'price'],
template: `
<div>
商品页面 <br>
商品 ID:{{id}} -- 商品名称:{{name}} -- 商品价格:{{price}} 元
</div>
`
}
const router = new VueRouter({
routes: [{path: '/item/:id', component: itemCom, props: {name: '测试商品 1', price: 20}}
]
});
var vm=new Vue({
el:'#app',
data:{},
methods:{},
router
});
</script>
通过布尔类型的 props 配置,可以把动态路由的参数传递到组件中。如果要传递其他参数,就需要将 props 指定为对象类型,即: {path: '/item/:id', component: itemCom, props: {name: '测试商品 1', price: 20}}
,同时也需要在路由组件声明中添加 props: ['id', 'name', 'price']
。在这里共有两种类型阐参数,一个:id
表示的动态路径传递参数,另一个是 name price
表示通过 props 属性传递的参数。对应 id 只能通过 {{$route.params.id}}
方式获取
5-3. props 属性值为函数类型
代码实例
<div id="app">
<router-link to="/item/1"> 商品 1 </router-link>
<router-link to="/item/2"> 商品 2 </router-link>
<router-link to="/item/3"> 商品 3 </router-link>
<router-view></router-view>
</div>
<script>
const itemCom = {props: ['id', 'name', 'price'],
template: `
<div>
<h3> 商品详情 </h3>
商品 ID:{{id}}-- 商品名称:{{name}}-- 商品价格:{{price}}
</div>
`
}
const router = new VueRouter({
routes: [{path: '/item/:id', component: itemCom, props: route => ({id: route.params.id, name:'测试商品', price: 30})}
]
});
var vm=new Vue({
el:'#app',
data:{},
methods:{},
router
});
</script>
为了实现在路由组件中获取参数形式的一致,我们使用 props 属性的函数类型,通过在路由规则中配置props: route => ({id: route.params.id, name:'测试商品', price: 30})}
,就可以在路由组件中以{{id}}
、{{name}}
、{{price}}
一致的形式获取到可变路径参数和路由规则配置参数。
6. Vue-Router 命名路由
路由规则的定义配置中提供了 name
属性,用来给路由规则命名
<script src="./js/vue.js"></script>
<script src="./js/vue-router.js"></script>
<div id="app">
<router-link :to='{name:"item", params:{id: 1, name:" 商品 1", price: 30}}'> 商品 1 </router-link>
<router-link :to='{name:"item", params:{id: 2, name:" 商品 2", price: 40}}'> 商品 2 </router-link>
<router-link :to='{name:"item", params:{id: 3, name:" 商品 3", price: 10}}'> 商品 3 </router-link>
<router-view></router-view>
</div>
<script>
const itemCom = {props: ['id', 'name', 'price'],
template: `
<div>
<h3> {{name}} </h3>
<hr>
商品 ID:{{id}} -- 商品名称:{{name}} -- 商品价格:{{price}}
</div>
`
}
const router = new VueRouter({
routes: [{path: '/item/:id', name: 'item', component: itemCom, props: true}
]
})
var vm=new Vue({
el:'#app',
data:{},
methods:{},
router
});
</script>
- 定义路由规则时可以通过
name
属性来给路由规则命名:{path: '/item/:id', name: 'item', component: itemCom, props: true}
。在<router-link>
标签中做如下配置<router-link :to='{name:"item", params:{id: 2, name:" 商品 2", price: 40}}'> 商品 2 </router-link>
,name
属性值要和路由规则的name
属性值保持一致。 - 在
<router-link>
的to
属性中我们还可以通过params
配置项传递参数。要实现该参数的传递需要在路由规则定义中添加props: true
,同时to
属性还需要由v-bind:(简写 :)
绑定,这样才能在路由组件中获取到传递的参数。
7. Vue-Router 编程式导航和声明式导航
- 声明式导航
通过 <router-link>
来定义连接信息,实现页面跳转的,导航方式
- 编程式导航
通过 Vue 提供的 API,实现页面跳转的导航方式
Vue 提供了 this.$router.push(url)
和 this.$router.go(n)
可以实现页面的跳转。
7-1. 编程式导航示例
<script src="./js/vue.js"></script>
<script src="./js/vue-router.js"></script>
<div id="app">
<router-link v-bind:to="{name:'user', params: {id: 1, name:' 用户 1', age: 16}}"> 用户 1 </router-link>
<router-link :to="{name:'user', params: {id: 2, name:' 用户 2', age: 25}}"> 用户 2 </router-link>
<router-link :to="{name:'user', params: {id: 3, name:' 用户 3', age: 24}}"> 用户 3 </router-link>
<router-link :to="{name:'reg'}"> 用户注册 </router-link>
<router-view></router-view>
</div>
<script>
const userCom = {props: ['id', 'name', 'age'],
template: `<div>
<h1> {{name}} </h1>
用户 ID:{{id}} -- 用户名:{{name}} -- 用户年龄:{{age}}
<hr/>
<button @click="userRegister">User Register</button>
</div>`,
methods: {userRegister() {this.$router.push("/register");
}
}
}
const registerCom = {
template: `
<div>
<h1>User Register</h1>
<button @click="back"> 后退 </button>
</div>
`,
methods: {back() {console.log("aaaa");
this.$router.go(-1);
}
}
}
const router = new VueRouter({
routes: [{path: '/user/:id', name: 'user', component: userCom, props: true},
{path: '/register', name: 'reg', component: registerCom}
]
})
var vm=new Vue({
el:'#app',
data:{},
methods:{},
router
});
</script>
this.$router.push()
方法的参数一个要跳转到的页面的 URL,this.$router.go(n)
,n 为整数,n 为负数表示回退到 n 步;n 为整数表示前进 n 步。this.$router.go(1)
等同于 history.forward()
,this.$router.go(-1)
等同于history.back()
7-2. 编程式导航参数传递
this.$router.push()
参数类型:
- 字符串
this.$router.push("/register");
- 对象类型
this.$router.push({path: "/register");
- 命名路由
this.$router.push({name: 'reg', params: {name: 'Jack'}})
- 指定查询参数
this.$router.push({path: 'search', query: {name: 'Jack'}})
该配置会被 VUe 翻译为/search?name=Jack
** 说明
如果提供了 path,params 会被忽略,router.push({path: '/user', params: { userId}}) // -> /user
,上述配置不会把 userId 参数及参数值传递到目标页面。但是仅限于 params
配置项,query
配置项指定的参数可以传递
**