摘要:在如下幾個(gè)屬性,表示當(dāng)前的真實(shí)時(shí)間,用于和服務(wù)器時(shí)間同步,表示創(chuàng)建時(shí)間,主要用于分頁,以及重連時(shí)的判斷,表示是否斷線重連。初始化連接時(shí),將賦值為當(dāng)前本地時(shí)間,連接成功后,將賦值為服務(wù)器返回的當(dāng)前時(shí)間,再設(shè)置一個(gè)定時(shí)器,保持時(shí)間與服務(wù)器一致。
vue項(xiàng)目前端知識(shí)點(diǎn)整理 微信授權(quán)后還能通過瀏覽器返回鍵回到授權(quán)頁
在導(dǎo)航守衛(wèi)中可以在next({})中設(shè)置replace: true來重定向到改路由,跟router.replace()相同
router.beforeEach((to, from, next) => { if (getToken()) { ... } else { // 儲(chǔ)存進(jìn)來的地址,供授權(quán)后跳回 setUrl(to.fullPath) next({ path: "/author", replace: true }) } })路由切換時(shí)頁面不會(huì)自動(dòng)回到頂部
const router = new VueRouter({ routes: [...], scrollBehavior (to, from, savedPosition) { return new Promise((resolve, reject) => { setTimeout(() => { resolve({ x: 0, y: 0 }) }, 0) }) } })ios系統(tǒng)在微信瀏覽器input失去焦點(diǎn)后頁面不會(huì)自動(dòng)回彈
初始的解決方案是input上綁定onblur事件,缺點(diǎn)是要綁定多次,且有的input存在于第三方組件中,無法綁定事件。
后來的解決方案是全局綁定focusin事件,因?yàn)?b>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 } }在子組件中修改父組件傳遞的值時(shí)會(huì)報(bào)錯(cuò)
vue中的props是單向綁定的,但如果props的類型為數(shù)組或者對(duì)象時(shí),在子組件內(nèi)部改變props的值控制臺(tái)不會(huì)警告。因?yàn)閿?shù)組或?qū)ο笫堑刂芬?,但官方不建議在子組件內(nèi)改變父組件的值,這違反了vue中props單向綁定的思想。所以需要在改變props值的時(shí)候使用$emit,更簡單的方法是使用.sync修飾符。
// 在子組件中 this.$emit("update:title", newTitle) //在父組件中使用微信JS-SDK上傳圖片接口的處理
首先調(diào)用wx.chooseImage(),引導(dǎo)用戶拍照或從手機(jī)相冊(cè)中選圖。成功會(huì)拿到圖片的localId,再調(diào)用wx.uploadImage()將本地圖片暫存到微信服務(wù)器上并返回圖片的服務(wù)器端ID,再請(qǐng)求后端的上傳接口最后拿到圖片的服務(wù)器地址。
chooseImage(photoMustTake) { return new Promise(resolve => { var sourceType = (photoMustTake && photoMustTake == 1) ? ["camera"] : ["album", "camera"] wx.chooseImage({ count: 1, // 默認(rèn)9 sizeType: ["original", "compressed"], // 可以指定是原圖還是壓縮圖,默認(rèn)二者都有 sourceType: sourceType, // 可以指定來源是相冊(cè)還是相機(jī),默認(rèn)二者都有 success: function (res) { // 返回選定照片的本地ID列表,localId可以作為img標(biāo)簽的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)); } }); } }); }) }聊天室斷線重連的處理
由于后端設(shè)置了自動(dòng)斷線時(shí)間,所以需要socket斷線自動(dòng)重連。
在data如下幾個(gè)屬性,beginTime表示當(dāng)前的真實(shí)時(shí)間,用于和服務(wù)器時(shí)間同步,openTime表示socket創(chuàng)建時(shí)間,主要用于分頁,以及重連時(shí)的判斷,reconnection表示是否斷線重連。
data() { return { reconnection: false, beginTime: null, openTime: null } }
初始化socket連接時(shí),將openTime賦值為當(dāng)前本地時(shí)間,socket連接成功后,將beginTime賦值為服務(wù)器返回的當(dāng)前時(shí)間,再設(shè)置一個(gè)定時(shí)器,保持時(shí)間與服務(wù)器一致。
發(fā)送消息時(shí),當(dāng)有多個(gè)用戶,每個(gè)用戶的系統(tǒng)本地時(shí)間不同,會(huì)導(dǎo)致消息的順序錯(cuò)亂。所以需要發(fā)送beginTime參數(shù)用于記錄用戶發(fā)送的時(shí)間,而每個(gè)用戶的beginTime都是與服務(wù)器時(shí)間同步的,可以解決這個(gè)問題。
聊天室需要分頁,而不同的時(shí)刻分頁的數(shù)據(jù)不同,例如當(dāng)前時(shí)刻有10條消息,而下個(gè)時(shí)刻又新增了2條數(shù)據(jù),所以請(qǐng)求分頁數(shù)據(jù)時(shí),傳遞openTime參數(shù),代表以創(chuàng)建socket的時(shí)間作為查詢基準(zhǔn)。
// 創(chuàng)建socket createSocket() { _that.openTime = new Date().getTime() // 記錄socket 創(chuàng)建時(shí)間 _that.socket = new WebSocket(...) } // socket連接成功 返回狀態(tài) COMMAND_LOGIN_RESP(data) { if(10007 == data.code) { // 登陸成功 this.page.beginTime = data.user.updateTime // 登錄時(shí)間 this.timeClock() } } // 更新登錄時(shí)間的時(shí)鐘 timeClock() { this.timer = setInterval(() => { this.page.beginTime = this.page.beginTime + 1000 }, 1000) }
當(dāng)socket斷開時(shí),判斷beginTime與當(dāng)前時(shí)間是否超過60秒,如果沒超過說明為非正常斷開連接不做處理。
_that.socket.onerror = evt => { if (!_that.page.beginTime) { _that.$vux.toast.text("網(wǎng)絡(luò)忙,請(qǐng)稍后重試") return false } // 不重連 if (this.noConnection == true) { return false } // socket斷線重連 var date = new Date().getTime() // 判斷斷線時(shí)間是否超過60秒 if (date - _that.openTime > 60000) { _that.reconnection = true _that.createSocket() } }發(fā)送音頻時(shí)第一次授權(quán)問題
發(fā)送音頻時(shí),第一次點(diǎn)擊會(huì)彈框提示授權(quán),不管點(diǎn)擊允許還是拒絕都會(huì)執(zhí)行wx.startRecord(),這樣再次調(diào)用錄音就會(huì)出現(xiàn)問題(因?yàn)樯弦粋€(gè)錄音沒有結(jié)束), 由于錄音方法是由touchstart事件觸發(fā)的,可以使用touchcancel事件捕獲彈出提示授權(quán)的狀態(tài)。
_that.$refs.btnVoice.addEventListener("touchcancel" ,function(event) { event.preventDefault() // 手動(dòng)觸發(fā) touchend _that.voice.isUpload = false _that.voice.voiceText = "按住 說話" _that.voice.touchStart = false _that.stopRecord() })組件銷毀時(shí),沒有清空定時(shí)器
在組件實(shí)例被銷毀后,setInterval()還會(huì)繼續(xù)執(zhí)行,需要手動(dòng)清除,否則會(huì)占用內(nèi)存。
mounted(){ this.timer = (() => { ... }, 1000) }, //最后在beforeDestroy()生命周期內(nèi)清除定時(shí)器 beforeDestroy() { clearInterval(this.timer) this.timer = null }
watch監(jiān)聽對(duì)象的變化
watch: { chatList: { deep: true, // 監(jiān)聽對(duì)象的變化 handler: function (newVal,oldVal){ ... } } }后臺(tái)管理系統(tǒng)模板問題
由于后臺(tái)管理系統(tǒng)增加了菜單權(quán)限,路由是根據(jù)菜單權(quán)限動(dòng)態(tài)生成的,當(dāng)只有一個(gè)菜單的權(quán)限時(shí),會(huì)導(dǎo)致這個(gè)菜單可能不顯示,參看模板的源碼:
{{generateTitle(item.children[0].meta.title)}} {{generateTitle(item.meta.title)}} {{generateTitle(child.meta.title)}}
其中v-if="hasOneShowingChildren(item.children) && !item.children[0].children&&!item.alwaysShow"表示當(dāng)這個(gè)節(jié)點(diǎn)只有一個(gè)子元素,且這個(gè)節(jié)點(diǎn)的第一個(gè)子元素沒有子元素時(shí),顯示一個(gè)特殊的菜單樣式。而問題是item.children[0]可能是一個(gè)隱藏的菜單(item.hidden === true),所以當(dāng)這個(gè)表達(dá)式成立時(shí),可能會(huì)渲染一個(gè)隱藏的菜單。參看最新的后臺(tái)源碼,作者已經(jīng)修復(fù)了這個(gè)問題。
methods: { hasOneShowingChild(children = [], parent) { const showingChildren = children.filter(item => { if (item.hidden) { return false } else { // Temp set(will be used if only has one showing child) this.onlyOneChild = item return true } }) // When there is only one child router, the child router is displayed by default if (showingChildren.length === 1) { return true } // Show parent if there are no child router to display if (showingChildren.length === 0) { this.onlyOneChild = { ... parent, path: "", noShowingChildren: true } return true } return false } }動(dòng)態(tài)組件的創(chuàng)建
有時(shí)候我們有很多類似的組件,只有一點(diǎn)點(diǎn)地方不一樣,我們可以把這樣的類似組件寫到配置文件中,動(dòng)態(tài)創(chuàng)建和引用組件
var vm = new Vue({ el: "#example", data: { currentView: "home" }, components: { home: { /* ... */ }, posts: { /* ... */ }, archive: { /* ... */ } } })動(dòng)態(tài)菜單權(quán)限
由于菜單是根據(jù)權(quán)限動(dòng)態(tài)生成的,所以默認(rèn)的路由只需要幾個(gè)不需要權(quán)限判斷的頁面,其他的頁面的路由放在一個(gè)map對(duì)象asyncRouterMap中,
設(shè)置role為權(quán)限對(duì)應(yīng)的編碼
export const asyncRouterMap = [ { path: "/project", component: Layout, redirect: "noredirect", name: "Project", meta: { title: "項(xiàng)目管理", icon: "project" }, children: [ { path: "index", name: "Index", component: () => import("@/views/project/index"), meta: { title: "項(xiàng)目管理", role: "PRO-01" } },
導(dǎo)航守衛(wèi)的判斷,如果有token以及store.getters.allowGetRole說明用戶已經(jīng)登錄,routers為用戶根據(jù)權(quán)限生成的路由樹,如果不存在,則調(diào)用store.dispatch("GetMenu")請(qǐng)求用戶菜單權(quán)限,再調(diào)用store.dispatch("GenerateRoutes")將獲取的菜單權(quán)限解析成路由的結(jié)構(gòu)。
router.beforeEach((to, from, next) => { if (whiteList.indexOf(to.path) !== -1) { next() } else { NProgress.start() // 判斷是否有token 和 是否允許用戶進(jìn)入菜單列表 if (getToken() && store.getters.allowGetRole) { if (to.path === "/login") { next({ path: "/" }) NProgress.done() } else { if (!store.getters.routers.length) { // 拉取用戶菜單權(quán)限 store.dispatch("GetMenu").then(() => { // 生成可訪問的路由表 store.dispatch("GenerateRoutes").then(() => { router.addRoutes(store.getters.addRouters) next({ ...to, replace: true }) }) }) } else { next() } } } else { next("/login") NProgress.done() } } })
store中的actions
// 獲取動(dòng)態(tài)菜單菜單權(quán)限 GetMenu({ commit, state }) { return new Promise((resolve, reject) => { getMenu().then(res => { commit("SET_MENU", res.data) resolve(res) }).catch(error => { reject(error) }) }) }, // 根據(jù)權(quán)限生成對(duì)應(yīng)的菜單 GenerateRoutes({ commit, state }) { return new Promise(resolve => { // 循環(huán)異步掛載的路由 var accessedRouters = [] asyncRouterMap.forEach((item, index) => { if (item.children && item.children.length) { item.children = item.children.filter(child => { if (child.hidden) { return true } else if (hasPermission(state.role.menu, child)) { return true } else { return false } }) } accessedRouters[index] = item }) // 將處理后的路由保存到vuex中 commit("SET_ROUTERS", accessedRouters) resolve() }) },項(xiàng)目的部署和版本切換
目前項(xiàng)目有兩個(gè)環(huán)境,分別為測試環(huán)境和生產(chǎn)環(huán)境,請(qǐng)求的接口地址配在srcutilsglobal.js中,當(dāng)部署生產(chǎn)環(huán)境時(shí)只需要將develop分支的代碼合并到master分支,global.js不需要再額外更改地址
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/109467.html
摘要:寫在前面金三銀四又到了一年一度的跳槽季相信大家都在準(zhǔn)備自己面試筆記我也針對(duì)自己工作中所掌握或了解的一些東西做了一個(gè)目錄總結(jié)方便自己復(fù)習(xí)詳細(xì)內(nèi)容會(huì)在之后一一對(duì)應(yīng)地補(bǔ)充上去有些在我的個(gè)人主頁筆記中也有相關(guān)記錄這里暫且放一個(gè)我的面試知識(shí)點(diǎn)目錄大家 寫在前面: 金三銀四, 又到了一年一度的跳槽季, 相信大家都在準(zhǔn)備自己面試筆記, 我也針對(duì)自己工作中所掌握或了解的一些東西做了一個(gè)目錄總結(jié),方便自...
摘要:寫在前面金三銀四又到了一年一度的跳槽季相信大家都在準(zhǔn)備自己面試筆記我也針對(duì)自己工作中所掌握或了解的一些東西做了一個(gè)目錄總結(jié)方便自己復(fù)習(xí)詳細(xì)內(nèi)容會(huì)在之后一一對(duì)應(yīng)地補(bǔ)充上去有些在我的個(gè)人主頁筆記中也有相關(guān)記錄這里暫且放一個(gè)我的面試知識(shí)點(diǎn)目錄大家 寫在前面: 金三銀四, 又到了一年一度的跳槽季, 相信大家都在準(zhǔn)備自己面試筆記, 我也針對(duì)自己工作中所掌握或了解的一些東西做了一個(gè)目錄總結(jié),方便自...
摘要:注本文章是在工作過程中所接觸的知識(shí)點(diǎn)的整理,涉及的東西比價(jià)雜亂,如有錯(cuò)誤之處,歡迎糾錯(cuò)與指導(dǎo)一,頁面的錨鏈接定義錨點(diǎn)錨點(diǎn)鏈接。類似于我們閱讀書籍時(shí)的目錄頁碼或章回提示。 *注:本文章是在工作過程中所接觸的知識(shí)點(diǎn)的整理,涉及的東西比價(jià)雜亂,如有錯(cuò)誤之處,歡迎糾錯(cuò)與指導(dǎo) 一, 頁面的錨鏈接 1,定義:錨點(diǎn),錨點(diǎn)鏈接。常常用于那些內(nèi)容龐大繁瑣的網(wǎng)頁,通過點(diǎn)擊命名錨點(diǎn),不僅讓我們能指向文檔,還...
摘要:注本文章是在工作過程中所接觸的知識(shí)點(diǎn)的整理,涉及的東西比價(jià)雜亂,如有錯(cuò)誤之處,歡迎糾錯(cuò)與指導(dǎo)一,頁面的錨鏈接定義錨點(diǎn)錨點(diǎn)鏈接。類似于我們閱讀書籍時(shí)的目錄頁碼或章回提示。 *注:本文章是在工作過程中所接觸的知識(shí)點(diǎn)的整理,涉及的東西比價(jià)雜亂,如有錯(cuò)誤之處,歡迎糾錯(cuò)與指導(dǎo) 一, 頁面的錨鏈接 1,定義:錨點(diǎn),錨點(diǎn)鏈接。常常用于那些內(nèi)容龐大繁瑣的網(wǎng)頁,通過點(diǎn)擊命名錨點(diǎn),不僅讓我們能指向文檔,還...
摘要:前言一直混跡社區(qū)突然發(fā)現(xiàn)自己收藏了不少好文但是管理起來有點(diǎn)混亂所以將前端主流技術(shù)做了一個(gè)書簽整理不求最多最全但求最實(shí)用。 前言 一直混跡社區(qū),突然發(fā)現(xiàn)自己收藏了不少好文但是管理起來有點(diǎn)混亂; 所以將前端主流技術(shù)做了一個(gè)書簽整理,不求最多最全,但求最實(shí)用。 書簽源碼 書簽導(dǎo)入瀏覽器效果截圖showImg(https://segmentfault.com/img/bVbg41b?w=107...
摘要:前言本文主要是有關(guān)前端方面知識(shí)按照目前的認(rèn)知進(jìn)行的收集歸類概括和整理,涵蓋前端理論與前端實(shí)踐兩方面。 前言:本文主要是有關(guān)前端方面知識(shí)按照 XX 目前的認(rèn)知進(jìn)行的收集、歸類、概括和整理,涵蓋『前端理論』與『前端實(shí)踐』兩方面。本文會(huì)告訴你前端需要了解的知識(shí)大致有什么,看上去有很多,但具體你要學(xué)什么,還是要 follow your heart & follow your BOSS。 初衷...
閱讀 2584·2021-11-22 09:34
閱讀 959·2021-11-19 11:34
閱讀 2813·2021-10-14 09:42
閱讀 1497·2021-09-22 15:27
閱讀 2396·2021-09-07 09:59
閱讀 1745·2021-08-27 13:13
閱讀 3440·2019-08-30 11:21
閱讀 783·2019-08-29 18:35