微信授权后还能通过浏览器返回键回到授权页
在导航守卫中可以在 next({}) 中设置 replace: true 来重定向到改路由,跟 router.replace() 相同
router.beforeEach((to, from, next) => { if (getToken()) { ... } else { // 储存进来的地址,供授权后跳回 setUrl(to.fullPath) next({ path: '/author', replace: true }) } })
路由切换时页面不会自动回到顶部
const router = new VueRouter({ routes: [...], scrollBehavior (to, from, savedPosition) { return new Promise((resolve, reject) => { setTimeout(() => { resolve({ x: 0, y: 0 }) }, 0) }) } })
ios系统在微信浏览器input失去焦点后页面不会自动回弹
初始的解决方案是input上绑定 onblur 事件,缺点是要绑定多次,且有的input存在于第三方组件中,无法绑定事件。
后来的解决方案是全局绑定 focusin 事件,因为 focusin 事件可以冒泡,被最外层的body捕获。
util.wxNoScroll = function() { let myFunction let isWXAndIos = isWeiXinAndIos() if (isWXAndIos) { document.body.addEventListener('focusin', () => { clearTimeout(myFunction) }) document.body.addEventListener('focusout', () => { clearTimeout(myFunction) myFunction = setTimeout(function() { window.scrollTo({top: 0, left: 0, behavior: 'smooth'}) }, 200) }) } function isWeiXinAndIos () { let ua = '' + window.navigator.userAgent.toLowerCase() let isWeixin = /MicroMessenger/i.test(ua) let isIos = /\(i[^;]+;( U;)? CPU.+Mac OS X/i.test(ua) return isWeixin && isIos } }
在子组件中修改父组件传递的值时会报错
vue中的props是单向绑定的,但如果props的类型为数组或者对象时,在子组件内部改变props的值控制台不会警告。因为数组或对象是地址引用,但官方不建议在子组件内改变父组件的值,这违反了vue中props单向绑定的思想。所以需要在改变props值的时候使用 $emit ,更简单的方法是使用 .sync 修饰符。
// 在子组件中 this.$emit('update:title', newTitle) //在父组件中 <text-document :title.sync="doc.title"></text-document>使用微信JS-SDK上传图片接口的处理
首先调用 wx.chooseImage() ,引导用户拍照或从手机相册中选图。成功会拿到图片的 localId ,再调用 wx.uploadImage() 将本地图片暂存到微信服务器上并返回图片的服务器端ID,再请求后端的上传接口最后拿到图片的服务器地址。
chooseImage(photoMustTake) { return new Promise(resolve => { var sourceType = (photoMustTake && photoMustTake == 1) ? ['camera'] : ['album', 'camera'] wx.chooseImage({ count: 1, // 默认9 sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有 sourceType: sourceType, // 可以指定来源是相册还是相机,默认二者都有 success: function (res) { // 返回选定照片的本地ID列表,localId可以作为img标签的src属性显示图片 wx.uploadImage({ localId: res.localIds[0], isShowProgressTips: 1, success: function (upRes) { const formdata={mediaId:upRes.serverId} uploadImageByWx(qs.stringify(formdata)).then(osRes => { resolve(osRes.data) }) }, fail: function (res) { // alert(JSON.stringify(res)); } }); } }); }) }
聊天室断线重连的处理
由于后端设置了自动断线时间,所以需要 socket 断线自动重连。
在 data 如下几个属性, beginTime 表示当前的真实时间,用于和服务器时间同步, openTime 表示 socket 创建时间,主要用于分页,以及重连时的判断, reconnection 表示是否断线重连。
data() { return { reconnection: false, beginTime: null, openTime: null } }
初始化 socket 连接时,将 openTime 赋值为当前本地时间, socket 连接成功后,将 beginTime 赋值为服务器返回的当前时间,再设置一个定时器,保持时间与服务器一致。
发送消息时,当有多个用户,每个用户的系统本地时间不同,会导致消息的顺序错乱。所以需要发送 beginTime 参数用于记录用户发送的时间,而每个用户的 beginTime 都是与服务器时间同步的,可以解决这个问题。
聊天室需要分页,而不同的时刻分页的数据不同,例如当前时刻有10条消息,而下个时刻又新增了2条数据,所以请求分页数据时,传递 openTime 参数,代表以创建socket的时间作为查询基准。
// 创建socket createSocket() { _that.openTime = new Date().getTime() // 记录socket 创建时间 _that.socket = new WebSocket(...) } // socket连接成功 返回状态 COMMAND_LOGIN_RESP(data) { if(10007 == data.code) { // 登陆成功 this.page.beginTime = data.user.updateTime // 登录时间 this.timeClock() } } // 更新登录时间的时钟 timeClock() { this.timer = setInterval(() => { this.page.beginTime = this.page.beginTime + 1000 }, 1000) }
当socket断开时,判断 beginTime 与当前时间是否超过60秒,如果没超过说明为非正常断开连接不做处理。