知识点1:
transition和router-view可以结合使用。因为router-view满足transition的条件。
<!-- App.vue文件 -->
<template>
<div id="container">
<div class="row">
<div class="col-xs-12 col-sm-8 col-sm-offset-2 col-md-6 col-md-offset-3">
<h1>Routing</h1>
<hr>
<router-view name="header-top"></router-view>
<transition name="fade" mode="out-in">
<router-view></router-view>
</transition>
</div>
</div>
</div>
</template>
<script>
import Herder from './components/header'
export default {
components: {
'app-header': Herder,
}
}
</script>
<style>
.fade-enter{
opacity: 0;
}
.fade-enter-to{
opacity: 1;
}
.fade-enter-active{
transition: opacity 1s;
}
.fade-leave{
opacity: 1;
}
.fade-leave-to{
opacity: 0;
}
.fade-leave-active{
transition: opacity 1s;
}
</style>
![v2-6f47e985b38ae858900b524e55f8ed17_b.gif](https://i-blog.csdnimg.cn/blog_migrate/1a38b4f1e04091fc55d60553d6a06ea2.gif)
知识点2:
锚点
需求: 在编辑页面上写一个button按钮(锚点),让别人定位到这里。
如果是在单页面,写一个a标签,href中写锚点id即可,或者在浏览器中写锚点id也行。
<template>
<div>
<p>请在此处编辑...</p>
<p>{{ $route.query.a }}</p>
<p>{{ $route.query.a }}</p>
<a href="#btn">去锚点</a>
<div style="height: 1000px"></div>
<button class="btn btn-primart" id="btn">锚点</button>
</div>
</template>
<style scoped>
p {
color: #0c8918;
}
</style>
![v2-de8f87b570daeebeaaba1889d71f08ca_b.gif](https://ss.csdn.net/p?https://pic3.zhimg.com/v2-de8f87b570daeebeaaba1889d71f08ca_b.gif)
如果是在用户详情页面中跳转的时候锚点,该怎么做?
在路由配置中写一个滚动行为scrollBehavior。
scrollBehavior有三个参数: to from savePostion,return一个包含x和y的坐标或者选择器selector,如果定义在路由配置中,则全局中组件切换都会触发该函数。
to: 到哪里去
from: 从哪里来
savePostion: 记录浏览器滚动条上次的位置,使用浏览器前进后退按钮有效
import Vue from 'vue'
import Router from 'vue-router'
import Home from './components/home'
import User from './components/user'
import userStart from './components/user/userStart'
import userDetail from './components/user/userDetail'
import userEdit from './components/user/userEdit'
import Header from './components/header'
Vue.use(Router)
export default new Router({
mode: 'history',
routes: [
{
path: '/',
components: {
default: Home, // 匹配到'/' 没有命名使用这个
'header-top': Header, // 匹配到'/' 使用该命名的使用这个
},
name: 'home',
},
{
path: '/user',
component: User,
children: [{
path: "",
component: userStart,
},{
path: ":id",
component: userDetail,
},{
path: ":id/edit",
component: userEdit,
name: "userEdit"
}]
},{
path: "*",
redirect: "/user" // 重定向
}
],
scrollBehavior(to, from, savePostion) {
console.log(to)
console.log(from)
return {
// x: 0,
// y:200,
selector: "#btn"
}
}
// 这个行为配置在全局,全局中只要有组件切换都会触发
})
![v2-2676a4a12dd5d84d1b78fc47e5c574b4_b.gif](https://i-blog.csdnimg.cn/blog_migrate/37b0e21d8d693a345f8fdf047a758213.gif)
缺点: 任意两个路由跳转都会跳到这里(有滚动条的时候)。
解决: 写点逻辑,只有to页面才能锚点
scrollBehavior(to, from, savePostion) {
// console.log(to)
// console.log(from)
console.log(savePostion)
if(to.hash){
return {
selector: "#btn"
}
}
}
savePostion示范:
![v2-2438d55f5cf1b8faae29a712dcbea4f3_b.gif](https://ss.csdn.net/p?https://pic4.zhimg.com/v2-2438d55f5cf1b8faae29a712dcbea4f3_b.gif)
知识点3:
3个进入之前的守卫,2个走之前的守卫
进入之前守卫
- 全局守卫: 获取vue实例,使用beforEach方法
beforEach: 在每一次进入路由之前都会执行该函数(拦截器),有to, from, next三个形参。
to和from不说了,next方法调用才会执行跳转。
![v2-2b96a502446093fceb9446ed78bd1b38_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/d865c5f3adb96f27b9489d0f5f4574ac.jpeg)
![v2-eb57560f201fdf26134f78d6d1038a76_b.gif](https://ss.csdn.net/p?https://pic3.zhimg.com/v2-eb57560f201fdf26134f78d6d1038a76_b.gif)
![v2-7c5250b7291dcdb886af2e24ac02bec9_b.gif](https://ss.csdn.net/p?https://pic2.zhimg.com/v2-7c5250b7291dcdb886af2e24ac02bec9_b.gif)
next的三种情况
next(false): 跟无next一样
next(): 真实跳转
next("/user"): 可以重定向,适合用户验证失效。可以写成对象: path、query等
2. 局部守卫
beforeEnter
![v2-00aa10d5df5cdf487b8539fad3c8d866_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/ae81c790b2ab5ba0dd5a8f1cbc4aefba.jpeg)
![v2-ef8f7f5b179e4b234ceaefbc1e52fea1_b.gif](https://ss.csdn.net/p?https://pic2.zhimg.com/v2-ef8f7f5b179e4b234ceaefbc1e52fea1_b.gif)
3. 组件守卫
beforeRouteEnter
![v2-b19abf07f5d27eddfbe38c09b4dd0171_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/d8a5f7168ce78ee051d431c79aa5eee8.jpeg)
![v2-7535ea099dc866e8e5be93eb936c49cc_b.gif](https://i-blog.csdnimg.cn/blog_migrate/7474e4f59320fd4ea16a778e58608c90.gif)
如果要使用这种方法改变数据,请使用vm来做vue实例的this。然后通过回调函数执行。
![v2-b30d6110e36f82aef98ef3bb96801e1f_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/e62c6918e393eff911a361a765894a73.jpeg)
![v2-9c7e25e6a06c86b3fc99afe1413b63d5_b.gif](https://ss.csdn.net/p?https://pic2.zhimg.com/v2-9c7e25e6a06c86b3fc99afe1413b63d5_b.gif)
走之前守卫
- beforeLeave
没有next走不出去。
![v2-1b840edc6478679c4d4759f965137fbd_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/70860533191eafc92095511e1ee52ab9.jpeg)
![v2-10036bd0f460a21e8dcbae87b735e3b7_b.gif](https://ss.csdn.net/p?https://pic4.zhimg.com/v2-10036bd0f460a21e8dcbae87b735e3b7_b.gif)
<template>
<div>
<p>请在此处编辑...</p>
<p>{{ $route.query.a }}</p>
<p>{{ $route.query.a }}</p>
<button class="btn btn-primary" @click="confirm=true">保存</button>
<div style="height: 1000px"></div>
<button class="btn btn-primary" id="btn">锚点</button>
</div>
</template>
<script>
export default {
data() {
return {
confirm: false,
}
},
beforeRouteEnter(to, from, next) {
console.log("组件守卫")
console.log(this)
next(vm => {
console.log(vm)
})
},
beforeRouteLeave(to, from, next) {
if(this.confirm){
next()
}else{
if(confirm("提示: 你的数据未保存,直接离开将丢失")) {
next()
}else{
next(false)
}
}
}
}
</script>
<style scoped>
p {
color: #0c8918;
}
</style>
![v2-eb1b7a867c890de4527a31c8f7ae9d2f_b.gif](https://ss.csdn.net/p?https://pic4.zhimg.com/v2-eb1b7a867c890de4527a31c8f7ae9d2f_b.gif)
知识点4: (小项目不需要)
软加载
由于webpack把所有js文件打包到了一起,如果遇上大型项目,加载将会变慢,我们把所有的路由打包成不同的js文件。
代码分离思想:不使用import,写成函数,在切换组件的时候才执行。
import Vue from 'vue'
import Router from 'vue-router'
import Home from './components/home'
const User = () => import('./components/user')
const userStart = () => import('./components/user/userStart')
const userDetail = () => import('./components/user/userDetail')
const userEdit = () => import('./components/user/userEdit')
const Header = () => import('./components/header')
// import User from './components/user'
// import userStart from './components/user/userStart'
// import userDetail from './components/user/userDetail'
// import userEdit from './components/user/userEdit'
// import Header from './components/header'
Vue.use(Router)
const router = new Router({
mode: 'history',
routes: [
{
path: '/',
components: {
default: Home, // 匹配到'/' 没有命名使用这个
'header-top': Header, // 匹配到'/' 使用该命名的使用这个
},
name: 'home',
},
{
path: '/user',
component: User,
children: [{
path: "",
component: userStart,
},{
path: ":id",
component: userDetail,
beforeEnter(to, from, next) {
console.log("局部路由")
next()
}
},{
path: ":id/edit",
component: userEdit,
name: "userEdit"
}]
},{
path: "*",
redirect: "/user" // 重定向
}
],
scrollBehavior(to, from, savePostion) {
// console.log(to)
// console.log(from)
// console.log(savePostion)
if(to.hash){
return {
selector: "#btn"
}
}
}
// 这个行为配置在全局,全局中只要有组件切换都会触发
})
router.beforeEach((to, from, next) => {
next()
})
export {router}
// 在main.js中也需要用命名方式引入
![v2-1f3c5b1a5362a723a5a5a7da63d2456a_b.gif](https://ss.csdn.net/p?https://pic3.zhimg.com/v2-1f3c5b1a5362a723a5a5a7da63d2456a_b.gif)
为什么一开始就加载了1.js,2.js,3.js文件,因为开启了预加载功能。
![v2-b2eddeb50625c457c84d1c62a151c7af_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/310087e3e7b6fbbde2ec41210c1072e5.jpeg)