vue常见问题(不断更新中)!

1、setInterval路由跳转继续运行并没有销毁

如果你在一个组件中使用setInterval定时器,路由跳转时未清除定时器,它不会销毁,还回在后台不断的运行,如果运算量大的话会造成卡顿。

解决方法:

在组件生命周期beforeDestroy中停止setInterval,正好也说下为什么好多会把定时器变量定义在data中,很多时候我们可能用到定时器这个变量标识,在data中定义用起来更加方便。。。

export default {
	name: "first",
	data(){
		return{
			timer:null
			
		}
	},
	mounted(){
		this.timer = setInterval(()=>{
			console.log("1")
		},1000)
	},
	beforeDestroy(){
		clearInterval(this.timer)
	}
};

2、滚动行为

在vue文档中有详细的说明,我在重复一遍:

如果不加 scrollBehavior 方法 ,切换导航时,滚动条会记录原先的位置,不会发生改变!!!通常在开发时,我们都希望从一个页面切换到另一个页面时,页面都是置顶的,为解决这个问题你可以在router实例中配置 scrollBehavior 方法:

const router = new VueRouter({
  routes: [...],
  scrollBehavior (to, from, savedPosition) {
    if(savedPosition){
        return savedPosition
    }else{
        return {x:0,y:0}
    }
  }
})

to :  新路由地址 对象

from : 原先路由地址   对象 

savedPosition : 滚动条的位置此参数,只有 通过浏览器的 前进 后退 按钮触发时才能触发可用。。。

{ x:0,y:0 } : 路由切换时, 让页面滚动到顶部;也就是路由切换时定义滚动条的x轴y轴的位置。

 

3、拦截路由跳转,询问是否要切换导航

为防止用户突然切换导航,而未保存已输入的信息。

使用beforeRouteLeave  守卫

beforeRouteLeave(to,from,next){
    if(用户已输入的信息){
        alert("您确定要退出吗")
    }
    next()
},

实际应用:

多个路由同时复用一个组件时,比如登录和注册页,可复用组件用props接收来自父组件传来的不同内容,渲染不同页面,这里边,登录页和注册页的 账户 和 密码框 都是一样的,如果用户在登录页输入完信息,直接切换到注册页,那么注册页会显示用户在登录页输入的 账号和密码,这样是肯定不行的!!!

所以我们可以使用beforeRouteLeave  守卫来判断,当用户在登录页输入完信息 且 用户直接切换到了注册页,那么我们直接清空输入框的内容,或者不让跳转也行,看自己的需求。

下边我是直接清空输入框跳转到注册页 或登录页:

export default {
  name: 'Login',
  beforeRouteLeave(to,from,next){
    // 切换到注册页面,如果登录页面
    if(to.fullPath === '/login/reg'){
      if(this.$refs.sonLogin.$data.userName || this.$refs.sonLogin.$data.userPassword){
        alert("您输入的信息将要被清空,确定要离开吗")
        this.$refs.sonLogin.$data.userName = ""
        this.$refs.sonLogin.$data.userPassword = ""
      }
    }else if(to.fullPath === '/login/log'){
      if(this.$refs.sonLogin.$data.userName || this.$refs.sonLogin.$data.userPassword || this.$refs.sonLogin.$data.repeatPassword || this.$refs.sonLogin.$data.verityCount){
        alert("您输入的信息将要被清空,确定要离开吗")
        this.$refs.sonLogin.$data.userName = ""
        this.$refs.sonLogin.$data.userPassword = ""
        this.$refs.sonLogin.$data.repeatPassword = ""
        this.$refs.sonLogin.$data.verityCount = ""
      }
    }
    next()
  }
}

 

 

4、校验用户登录时,使用全局守卫,死循环问题

 

 校验用户是否登录,你可能会这样写:

router.beforeEach((to,from,next)=>{
    if("登录"){
        next()
    }else{  
        next({path:"/login"})
    }
}

判断是否登录过,否则直接跳转到登录页面;看似没有什么问题,但是执行的时候,浏览器直接进入死循环了!原因在于:

当没有登陆进入else时,它直接会跳转到登录页面, 而当进入登录页面时,还会执行全局前置守卫,这个时候还是未登录状态,会再次执行else代码块,直接进入了一个死循环,所以浏览器直接卡死了!!!

解决方法:

先说下我的思路,只要有token,那么我就让你跳转到任何页,否则,再加一层判断,用户是否是导航到登录页面,是的话next(),否则 next( { path :" /login " } )自动跳转到 登录页。

这样就不会涉及到死循环的问题了

router.beforeEach((to,from,next)=>{
    if(token){
        next()
    }else{
        if(to.name == "play"){
            next()
        }else{
            next({path:"/play"})
        }
    }
})

 

5、可复用组件

在可复用组件中,我们如何观测到期变化呢?下边我介绍三种方法

1、使用组件内守卫—— beforeRouteUpdate( to,from,next ) =>{ }

2、使用 watch:{ '$route'( to,from ) { } } 来观测变化

3、在路由出口 <router-view :key="$route.fullPath"/> 标签上动态添加key,因为每次切换路由 $route.fullPath 的路径都会不一样,组件间的状态会变成 不断销毁 与不断创建的过程。。。(生命周期钩子也将执行)

 

6、关于组件内守卫beforeRouteEnter

 这几天做项目,有个需求是这样的:

登录和注册页面是渲染的同一组件,子组件通过props接受父组件传来的不同内容,以便渲染登录页面还是注册页面,本来想通过下边watch 来监听路径的变化,从而传递不同的内容,但是watch只会监听可复用组件间的切换,如果从一个普通组件切换到可复用组件(比如:从首页------>登录页),不会触发watch:

watch:{
  '$route'(to,from){
      if(to.fullPath == '/login'){
         // ···
      }else{
         // ···
      }
  }
},

后来又想了想,在 组件内守卫—— beforeRouteUpdate( to,from,next ) =>{ }也不行,因为它也是只有可复用组件切换时才触发,最后想到可以在 组件内守卫—— beforeRouteEnter( to,from,next ) =>{ } 来判断,不管是从普通组件----->登录页,还是登录页与注册页之间的切换,都会执行beforeRouteEnter( to,from,next ) =>{ }这个守卫,下边使用next中的回调函数解决此问题,判断切换到的是注册页还是登录页面,渲染不同内容:

export default {
  name: 'Login',
  data(){
    return{
      style:{},
      veritycount:""
    }
  },
  beforeRouteEnter(to,from,next){
    next((_this)=>{
      if(_this.$route.fullPath == '/login/log'){
        _this.style = {
          title:'用户登录',
          ishow:"none",
          buttonContent:"登录",
          isshowverity:"none"
        }
      }else{
        _this.style = {
          title:'用户注册',
          ishow:"block",
          buttonContent:"注册",
          isshowverity:"block"
        }
      }
    })
  }
}

------------>  

 

7、在created中请求后台数据,在mounted中获取不到

vue的生命周期钩子时同步执行的,而created请求的后台数据是异步请求,mounted中必然取不到,如果想操作获取到的数据,使用promise或 async await;当然你也可以使用watch来监听:

created() {
    this.status = true
    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve({name: 'lxc'})
      }, 3000)
    }).then((res) => {
      this.name = res.name
    }).finally(() => {
      this.status = false
    })
}

在watch中监听:

created() {
    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve({name: 'lxc'})
      }, 3000)
    }).then((res) => {
      this.name = res.name
    })
},
watch:{
    name() {
      this.name = 'xc'
    }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值