补充
1.main.js入口文件注册过router,会有 r o u t e r , router, router,route俩个属性
<template> <div><TabBar v-if = "tabBarFlag"/></div> </template> export default{ watch: { // 监听 $route属性 $route:{ deep: true,// 开启深度监听 handler(){ // 处理函数 if( this.$route.name == 'detail') { this.tabBarFlag = false }else { this.tabBarFlag = true } } } } }
2.router-link
<!-- 使用vue内置提供的 router-link 组件来完成 -->
<router-link
:to=" item.path " tag = "li"
active-class = "active" //给当前点击的加类 active-class
>
<i class="fas" :class = "[ item.iconName ]"></i>
<span> {{ item.text }} </span>
</router-link>
3. 父传给子,子接收数据渲染时,可能会报错
如果数据存在渲染两次情况,其中一次时undefined/null,那么我们需要通过判断来排除undefined/null
export default {
props: ['resource'], // 接收属性
computed: {
list () { // 需要加一个计算属性重新计算,在拿这个属性渲染就不会报错
return this.resource && this.resource
}
}
}
4.其余(native修饰符,filter,绑定属性传值写法)
组件身上添加原生事件,要加native修饰符
1.@click.native = “addShopCar”
2.路由接参, r o u t e 是 一 个 属 性 , 在 结 构 里 面 可 以 直 接 访 问 route是一个属性,在结构里面可以直接访问 route是一个属性,在结构里面可以直接访问route,方法里面this.$route
3.js工具库,loadsh,原生方法封装库, https://www.lodashjs.com/
4.better-scroll 最适合移动端开发的前端 mvvm 框架是 Vue
5.Vue.filter(‘imgFilter’, val => { return val.replace(‘w.h’,‘128.180’)})
6.@import ‘~assets/stylesheets/border.styl’; 引入样式加~
7 支持这种传值
//封装
export const getStorage = ( name ) => {
return localStorage.getItem( name ) && JSON.parse(localStorage.getItem( name )) || []
}
export const saveStorage = ( name, value ) => {
localStorage.setItem( name,JSON.stringify(value) )
}
一、vue路由
守卫是异步解析执行
router.afterEach() ,全局后置守卫router.afterEach()
next [必须要写的]
1. next表示两者之间的连接
2. 取值
1. next() //默认连通
2. next( true ) // 表示连通
3. next( false ) // 不表示断开连接
4. next(路由路径)
1. next('/home')
2. next({ name: 'home', params: {},query: {} })
5. next( vm => { } ) // vm指的是目标组件
1.全局导航守卫
- 全局前置守卫router.beforeEach()
使用场景 -> 后台管理系统 || 社区app 登录拦截
接收三个参数,to,from,next
router.beforeEach((to,from,next) => {
next() // 默认不写参数是允许
next(error)
if ( to.path == '/home/hot' ) {
next()
}
})
demo,全局前置守卫,倒计时3s后判断要不要进入
router.beforeEach((to ,from , next) => {//全局守卫
if( token || to.path == '/login'){ // 判断token,或者进入的是login页面,要执行的语句
if(to.path == '/buyer') {
const toast = Toast.loading({
duration: 0, // 持续展示 toast
forbidClick: true,
message: '倒计时 3 秒进入购买页'
});
let second = 3;
const timer = setInterval(() => {
second--;
if (second) {
toast.message = `倒计时 ${second} 秒`;
} else {
clearInterval(timer);
// 手动清除 Toast
Toast.clear();
}
}, 1000); // 以上是组件带的,只有倒计时,现在要实现需要
setTimeout(() => { // 开一个延时定时器,3s判断要不要进入页面
next()
return // 终止掉,一定要加
})
}else{
next()
}
}else{
next('/login')
}
})
- 全局后置守卫router.afterEach()
全局后置守卫 - 建议不用
应用场景: 没有拦截这一个功能,只有提示功能
接收(to,from)
router.afterEach( to => {
if ( to.path == '/recommend' ) {
Notify({ type: 'success', message: '通知内容' }); // 提示内容
}
})
- 全局解析守卫也叫更新守卫
- 在 2.5.0+ router.beforeResolve
这和
router.beforeEach` 类似 - 区别: 是否完整遍历路由表
- 区别是在导航被确认之前,同时在所有组件内守卫和异步路由组件被解析之后,才被调用。
- 更新守卫要遍历完整路由表之后才跳转页面
- 在 2.5.0+ router.beforeResolve
2.路由独享守卫,beforeEnter
const List = () => import(/*webpackChunkName: "group1"*/ '@/views/list/index.vue')
const router = new VueRouter({
routes:[
{
path: '/list/:id',
// 动态路由组件配置 http://localhost:3000/list/001?a=1&b=2
component: List,
name: 'list',// 取一个别名
meta: {
include: 'List',
/** <keep-alive :include="$route.meta.include">
<router-view><router-view/> 来接收路由对应的组件
</keep-alive>
*/
},
beforeEnter:(to,from,next) => {
const token = getCookie('token')
if (token) {
next()
}else{ // 没token,要提醒
Toast.fail('您还没登录,无法查看')
next(false)
}
}
}
]
})
3.组件内守卫***
beforRouterEnter, beforeRouteUpdate, beforeRouteLeave
a. 组件前置守卫【 钩子 】beforRouterEnter ***********
拦截组件的进入
执行: 创建创建前执行,这个时候没有组件,没有this ,通过next((vm) => {vm.$set()})
功能
判断是否有token,然后是否进入当前页面
数据预载
- 进入组件前,提前得到数据,并将这个数据赋值给组件
demo1组件预加载
export default { // 数据预载 进入页面前先请求加载数据,但没有this
data () {
return {
cinemas: {}
}
},
async beforeRouteEnter (to,from,next) {
const result = await request({
url:'/ajax/search',
params: {
ke:'n'
}
})
next( vm => { // vm 就是当前组件 解决没有this的问题
// vm.cinemas = result.data.cinemas.list 这么写可行吗? 不行
// 对象的合并 Object.assign() -> Vue.set/this.$set( 属性,属性值 )
vm.$set( vm.cineams, JSON.stringfy(result.data.cinemas.list)) // 对象合并后进入
next()
})
}
}
demo2组件前置守卫,判断是否有token,是否允许进入
export default {
beforeRouteEnter(to, from, next){ // 无this
const token = getCookie('token')
if ( token ) {
next() // 允许进入
return
}
next( false )
}
}
b.组件后置守卫(钩子)
- 拦截组件离开
- 执行: 离开组件前,这时有组件,有this
export default {
beforeRouteLeave(to, from, next) {
if( this.username || this.password) {
if(confirm('还没提交,确定离开么')){
next()
return // 一定记得加
}else{
next(false)
return
}
}else{
next()
}
}
}
c.组件更新守卫 beforeRouteUpdate()
专用于动态路由
二、编程式导航路由
router.push
router.replace
router.go(n) 后退
- $router
- push vs replace
- push会将我们操作放入历史记录,点击浏览器返回会一层一层返回
- replace不会将我们的操作放入历史记录,点击浏览器返回反回2层
// 字符串
router.push('home')
// 对象
router.push({ path: 'home' })
// 命名的路由
router.push({ name: 'user', params: { userId: '123' }})
// 带查询参数,变成 /register?plan=private
router.push({ path: 'register', query: { plan: 'private' }})
如果提供了 path
,params
会被忽略 ,所以要注意params和query同时写的问题
const userId = '123'
router.push({ name: 'user', params: { userId }}) // -> /user/123
router.push({ path: `/user/${userId}` }) // -> /user/123
// 这里的 params 不生效
router.push({ path: '/user', params: { userId }}) // -> /user
三、其他有关路由
1.命名路由
路由表里面配置一个命名路由,name,起的别名,router-link链接到一个命名路由
<router-link :to = "{name: 'home',params: {userId: 123}}" >
</router-link>
// 这跟代码调用 router.push() 是一回事
// 点击一个事件触发,在事件里面可以取
this.$router.push({name:'home',params:{userId:123})
2.命名视图
同一个页面展示多个视图 ,而不是嵌套展示 ,router-view 没有名字就是默认为default
<router-view></router-view>
<router-view name = 'a'></router-view>
<router-view name = 'b'></router-view>
一个视图使用一个组件渲染 ,一个路由多个视图,要用components【s】一定要加上配置上,单个不加
const router = new VueRouter({
routes: [
{
path: '/',
components: { // s 多个组件渲染 一定记得加
default: Foo,
a: Bar,
b: Bar2
}
}
]
})