一、router-link的replace属性
1、作用:控制路由跳转时操作浏览器历史记录的模式
2、浏览器的历史记录有两种写入方式:分别为push和replace,push是追加历史记录,replace是替换当前记录。路由跳转时候默认为push
3、如何开启replace模式:<router-link replace .......>News</router-link>
push是默认模式,可以前进后退,相当于指针指前面还是后面,而replace是指针指哪个就把它之前那个抹掉,就不能后退了。
如果about是push模式,home也是push、news和message是replace模式,我点了about之后再点home,about不会被划掉;我再点news和message都会划掉他们之前的,所以当我处于message页面时,我点返回返回的是about
二、编程式路由导航
作用:不借助<router-link>
实现路由跳转,让路由跳转更加灵活
router-link最终实现的不是a标签吗,只有用户点击链接才能实现跳转,那么我怎么实现不用router-link来跳转呢
1.设计两个按钮实现push和replace API
message写两个按钮实现push和replace
<button @click="pushShow(m)">push查看</button>
<button @click="replaceShow(m)">replace查看</button>
methods:{
pushShow(m){
this.$router.push({
//不要去找route,route是一个规则,router是路由器,让干啥干啥
name:'xiangqing',
query:{
id:m.id,
title:m.title
}
})
},
replaceShow(m){
this.$router.replace({
//不要去找route,route是一个规则,router是路由器,让前进就前进
name:'xiangqing',
query:{
id:m.id,
title:m.title
}
})
}
}
2.设计三个按钮实现前进后退和go
在banner里面设计按钮:
<button @click="back">后退</button>
<button @click="forward">前进</button>
<button @click="go">测试一下go</button>
methods: {
back() {
this.$router.back();
},
forward() {
this.$router.forward();
},
go(){
this.$router.go();
//填一个数字,正数的话就是前进x步,负数就是后退x步
}
},
三、缓存路由组件
实现news后面有一个input表单,输入东西之后点击message保单内的内容保留
在news里写完input之后,然后就不用在里面写东西了,因为我们最终是展现在home的组件里的,在它的<router-view></router-view>是控制news组件的
<keep-alive include="myNews">
<!-- 只有myNews可以保留缓存 -->
<router-view></router-view>
</keep-alive>
keep-alive可以保留缓存,include控制保留哪个的,因为也不是里面所有的组件都保留缓存,谁有需求包括谁,不缓存的话切换就重新挂载
注意:include后面的名字指的是组件名,在它自己组件的script 里面的export default 的name
include多个组件:
<keep-alive :include="['myNews','myMessage']">
四、两个新的生命周期钩子
实现news下面一行字透明度一直变,那么定时器的回调一直在执行,我切换到message我就不想让他再执行了,关掉keep-active?那input表单里的字也没了啊,用activeted和deactivated代替mountde和beforeDestory。
1、activated
:路由组件被激活时触发(从没有出现在你面前–>组件出现在你眼前)。 相当于mounted
2、deactivated
:路由组件失活时触发。类似于beforeDestroy
3.作用:路由组件所独有
的两个钩子,用于捕获路由组件的激活状态。
<template>
<ul>
<li :style="{ opacity: opacity }">欢迎来到90年代</li>
<li>news001 <input type="text" /></li>
<li>news002 <input type="text" /></li>
<li>news003 <input type="text" /></li>
</ul>
</template>
<script>
export default {
name: "myNews",
data() {
return {
opacity: 1,
};
},
// beforeDestroy() {
// clearInterval(this.timer);
// },
// mounted() {
// this.timer = setInterval(() => {
// console.log("定时器执行");
// this.opacity -= 0.01;
// if (this.opacity <= 0) this.opacity = 1;
// }, 16);
// },
activated() {
this.timer = setInterval(() => {
console.log("定时器执行");
this.opacity -= 0.01;
if (this.opacity <= 0) this.opacity = 1;
}, 16);
},
deactivated() {
clearInterval(this.timer);
},
};
</script>
五、路由守卫
作用:对路由进行权限控制(我想让你看哪个,不想让你看哪个)
分类:全局守卫、独享守卫、组件内守卫
1.全局路由守卫
(1)全局前置守卫
实现只有学校atguigu才能查看message和news,让router去查看学校,
export default new VueRouter({
routes:
这样写是创建了对象然后立马把route暴露出去了,在暴露之前得跟router商量一下
//全局前置路由守卫
//暴露之前加一个路由守卫,指定路由切换之前、初始化的时候调用的一个函数
router.beforeEach((to, from, next) => {
//不调next啥都给你拦住
//学校名atguigu才放
if (to.path == 'myHome/myNews' || to.path == 'myHome/myMessage') {
if (localStorage.getItem('school') == 'atguigu') {
//要是去news或者message不让你看
next()
}else{
alert('学校不对!')
}
}else{
next()
}
})
export default router
beforeEach三个参数to是到哪里去,from从哪儿来,next()继续往下进行
我们自己一点一点的判断name,其实可以直接写在route里,比如写peiqi:true,下面if判断to.peiqi为true往下走,但是那里面的配置项不能自定义,自定义的东西写在meta里
children: [
{
path: 'myNews',
component: myNews,
meta:{isAuth:false}//是否授权,不用的那些写都不用写
//一级路由下的孩子路径就不用加/了
},
{
name: 'xiaoxi',
path: 'myMessage',
component: myMessage,
meta:{isAuth:false},
if (to.meta.isAuth) {//判断是否有权限
if (localStorage.getItem('school') == 'atguigu') {
//要是去news或者message不让你看
next()
}else{
alert('学校不对!')
}
}else{
next()
}
(2)全局后置守卫
先来加一个功能,比如点击home,当前页面的标题就是主页,设置meta:title,前置里面放document的title
meta:{title:'关于'}
router.beforeEach((to, from, next) => {
document.title=to.meta.title
这样写有bug:1.在什么都不点的情况下它的标题就vue_test,我们可以这样设置
document.title=to.meta.title||'硅谷'
这样写在刚一进来的时候是由vue_test刷新到硅谷,因为在index.html里我们写的title是连接package-json读取项目名称作为title,把html的改成硅谷跟前置的一样就行
2.这样改完之后,我们学校不对的情况下点击message、news内容确实不展现但是title变了?!
写在每次放行next之前才行,写两次
router.beforeEach((to, from, next) => {
//不调next啥都给你拦住
//学校名atguigu才放
if (to.meta.isAuth) {//判断是否有权限
if (localStorage.getItem('school') == 'atguigu') {
//要是去news或者message不让你看
document.title = to.meta.title || '硅谷'
next()
} else {
alert('学校不对!')
}
} else {
document.title = to.meta.title || '硅谷'
next()
}
})
这样还得写两次,其实他就是后置的功能,要切换的时候加上,所以直接写后置就行
router.beforeEach((to, from, next) => {
//不调next啥都给你拦住
//学校名atguigu才放
if (to.meta.isAuth) {//判断是否有权限
if (localStorage.getItem('school') == 'atguigu') {
//要是去news或者message不让你看
next()
} else {
alert('学校不对!')
}
} else {
next()
}
})
//全局后置路由守卫指定路由切换之后、初始化的时候调用的一个函数
router.afterEach((to, from) => {
//它没有next,前置是切换前调用next我就往下走,后置切换完成了不需要next
console.log(to,from)
document.title = to.meta.title || '硅谷'
})
3.独享路由守卫(只有前置)
某一个路由所单独享用的,独享只有前置但是可以和全局的后置搭配一起使用(你要修改title啥的)
我们现在给news写一个独享路由守卫,写在要鉴权的路由配置里面
name: 'xiaoxi',
path: 'myMessage',
component: myMessage,
beforeEnter: (to, from, next) => {
if (to.meta.isAuth) {//判断是否有权限
if (localStorage.getItem('school') == 'atguigu') {
next()
} else {
alert('学校不对!')
}
} else {
next()
}
},
跟前置的区别就是beforeEnter,Each是每个就是全局的意思
4.组件内路由守卫
以about为例,这儿也有个beforeRouteEnter和beforeRouteLeave,但是跟前后置不太一样,我从home来到about,先调一次前置进来了再调一次后置;
但是beforeRouteEnter是我进入about组件之前就调用然后就没有然后了;
我要是从about走了,再调用beforeRouteLeave
注意:beforeRouteLeave和Enter的使用前提是通过路由规则,离开/进入该组件时被调用,不是通过路由规则的可不会调用,通过路由规则进去就是点击组件进去,不通过路由规则还可以直接在页面引入然后<myAbout/>调用呢,这样的就不行
<script>
export default {
name:'myAbout',
beforeRouteEnter (to, from, next) {
// 通过路由规则,进入该组件时被调用
console.log('组件内路由守卫', to, from);
if (to.meta.isAuth) { //判断是否需要鉴权
if (localStorage.getItem('school') === 'hznu') {
next();
} else {
alert('学校名不对!');
}
} else {
next(); //放行
}
},
beforeRouteLeave (to, from, next) {
// 通过路由规则,离开该组件时被调用
next()//得放行啊
//注意那个document的title可不能在这儿写,那是后置的
}
}
</script>
5.组件从前置路由守卫到失活的执行流程
1.全局前置路由守卫 =>
2.组件内路由守卫beforeRouteEnter =>
3.全局后置路由守卫 =>
4.mounted挂载组件 =>
5.activated激活 =>
6.组件内路由守卫beforeRouteLeave =>
7.deactivated失活
六、路由器的两种工作模式
1.hash模式
路径的#是哈希值(hash),#后面的东西都不传给服务器
默认的开启哈希模式
特点:
1、地址中永远带着#号,不美观 。
2、若以后将地址通过第三方手机app分享,若app校验严格,则地址会被标记为不合法。
3、兼容性较好。
2.history模式
有历史记录的意思,如果想更改的话就在创建路由器的时候更改
const router = new VueRouter({
mode:'history',
我们写完前端打包给后端的时候不是给人家vue、js文件,需要在终端输入npm run build命令,然后生成了一个dist文件夹
1、地址干净,美观 。
2、兼容性和hash模式相比略差。
3、应用部署上线时需要后端人员支持,解决刷新页面服务端404的问题。
3.解决history刷新报错的问题
打包出来的文件必须放在服务器上部署,接下来搭建一个node 用上express的微型服务器
history刷新就报错,如果你点到了news,一刷新他就去找服务器要home/news,根本没这个啊,但是hash就不是找服务器要资源(#后面的都不给服务器)
history模式上线解决:
终端输入npm i connect-history-api-fallback,然后use一下(必须得在静态资源之前use)
七、Vue UI组件库
1.移动端常用UI组件库
(1) Vant https://youzan.github.io/vant
(2) Cube UI https://didi.github.io/cube-ui
(3)Mint Ul http://mint-ui.github.io
2.PC端常用UI组件库
(1)Element Ul https://element.eleme.cn
(2) IView UI http://mint-ui.github.io