距上一篇博客發布已經過去整整2個月。這兩個月中發生了一些事情,比如離職,面試,入職等等,感觸頗多。其實一次好的面試,即使沒有成功入職也會有很多收獲。
這次面試面了三家公司,拿了兩家公司的offer,但是最讓我中意的面試卻沒拿到offer,原因是下午去面試,精神狀況不太好,有點疲倦並且反應有點遲鈍,導致整個面試很糟糕。不過面試官還是很nice的,給我梳理了一下頭緒,拓展了一下思維,並且在后來的交流中給了我一些建議。准確的說這其實是一次成功的面試,長進很多。
最近一個月有點懶,說着努力進步的話做着混吃等死的事。因此給自己定了一個目標,每個月保證有20天晚上堅持學習,一周至少一篇博客,完成之后給自己一個小獎勵,比如一雙喜歡的AJ11之類的。
入職新公司20來天吧,跟進了一個項目,pc端的運營后台和移動端的混合開發app,算是現在項目組同時在做pc和移動端的唯一一個吧,有時候很懵逼,打開編輯器第一反應是看看這是哪一端的代碼。在這兩端的項目中幫同事改了幾個bug。
1.改進自己寫過的一個城市選擇組件
我以前寫過一篇博客《獨立完成一個城市選擇組件(阿里前端題目,內附知識點、思路)》,並且將這個組件的代碼分享在了github上,地址是https://github.com/lunlunshiwo/ChooseCity。在這個項目中我引入了一個比較出色的插件better-scroll為我提供滾動事件,其中有一段代碼是這樣的:
// pos為位置參數 this.scroll.on('scroll', (pos) => { this.$emit('distance', Math.abs(pos.y)) this.$emit('scrollStore', true) })
上面這段代碼我的用意是觸發滾動事件時應該向我返回滾動的位置,我在下面這段代碼中用到了這個pos.y這個變量為我的組件在滾動時提供一個指示,比如點擊右邊的navList的A時,城市列表會滾動到A處,此時會有一個懸浮的卡片展示A。
// 滾動到相應的dom節點 singleLetter (dom) { this.$refs.suggest.scrollToElement(dom, 200, false, false) }, // 根據滑動距離顯示字母牌上的字 distance (val) { for (let i = 0, len = this.arrHeight.length; i < len; i++) { if (val < this.arrHeight[i]) { this.flagText = this.cityIndexList[i] return false } } }
以上為以前的代碼,scrollToElement是組件提供的事件。
理想很豐滿,現實很骨感。直到端午節放假下班回家時的一天,一個人加了我的微信,給我說了一個bug:一定幾率下,從上往下點擊時會出現點擊了E,列表滾動到E但是懸浮卡片只顯示D的情況存在,而從下往上點擊時不會存在。后來也得到了證實的確幾率性的存在。但是作為我第一個發到github上的作品,我希望它是完美的。因此我花了端午假期在研究問題的所在,直到前幾天偶爾想到了原因。我們在觸發一下類似與mousemove的事件時,理想中應該一個像素觸發一次,但是因為機器的性能的原因並不會這樣。 “觸發”這個行為,從硬件發中斷,然后OS,產生消息,這個過程中,鼠標硬件本身判斷自己移動了多少距離時產生硬件信號,800dpi之類的。主板上中斷芯片的處理速度也會影響。也許每個版本的系統+硬件本身,這個時間片長短都不定。而程序本身由於GetMessage函數本身消耗的時間,與捕獲 鼠標移動消息(switch分支的判斷) 所需要的時間也不太確定。當你鼠標移動的比較慢時,可能每一個像素觸發一次。鼠標比較快時,可能發現移動了n個像素才觸發一次。
這也就導致了上面bug的產生,當從上往下點擊navList時,可能滾動到E這個列表的前10個像素時觸發了一次,而滾動到E列表時也就有可能因為時間太短未觸發,此時位置像素值實在D的最后10個像素上,忠誠的邏輯代碼也就會因為這10個像素的誤差不給我返回E這個字母。那我們要做的就是在滾動完成時讓列表繼續產生一個滾動事件,繼續滾動一個像素即可。
幸運的是同樣是上面那個滾動事件scrollToElement為我提供了一個參數
scrollToElement(el, time, offsetX, offsetY, easing)
- 參數:返回值:無
- {DOM | String} el 滾動到的目標元素, 如果是字符串,則內部會嘗試調用 querySelector 轉換成 DOM 對象。
- {Number} time 滾動動畫執行的時長(單位 ms)
- {Number | Boolean} offsetX 相對於目標元素的橫軸偏移量,如果設置為 true,則滾到目標元素的中心位置
- {Number | Boolean} offsetY 相對於目標元素的縱軸偏移量,如果設置為 true,則滾到目標元素的中心位置
- {Object} easing 緩動函數,一般不建議修改,如果想修改,參考源碼中的 ease.js 里的寫法
- 作用:滾動到指定的目標元素。
我們可以將上面的函數改為:
// 滾動到相應的dom節點 singleLetter (dom) { this.$refs.suggest.scrollToElement(dom, 200, false, 1) }
滾動到相關dom節點后繼續向下滾動一個像素,再次觸發一次滾動事件,解決。
相關代碼已更新,請放心使用,https://github.com/lunlunshiwo/ChooseCity,求個star。
2.vue2.0s中eventBus的綁定與解綁
在移動端項目中,有兩個頁面共用了一個我封裝的列表組件,並且這兩個頁面都會有一個上拉獲取更多的功能,因此,我做這個組件時使用eventBus作為兄弟組件傳值的轉接站。當頁面滾動至底部並且觸發上拉事件時向列表組件傳遞一個事件,在列表頁面綁定一個獲取更多的事件,並觸發。代碼如下:
//滾動組件 pullup(event) { Bus.$emit('getMore'); } //列表組件 created() { Bus.$on('getMore', this.getMoreList); }, methods: { getMoreList() { // // // } }
很不幸的是,這兩個列表組件我共用了一個組件,導致了下面這個問題:當這兩個列表切換幾次之后,上拉刷新時會觸發多次getMoreList事件,並且切換多少次就會出發多少次。百思不得騎姐之后我想到Bus.$on('getMore', this.getMoreList)比較類似原生Js的事件監聽:
//偽代碼 相關列表組件.addEventListener("getMore",getMoreList); function getMoreList(){ alert("hello world!"); }
在上述的問題中,假如事件getMore與組件中的getMoreList綁定,即使組件銷毀了,但是這個綁定關系還是存在的。等再次渲染組件時,created生命周期又會綁定一次事件,並且以前的綁定關系還是存在的,現在組件中有兩個綁定關系,而且相同。因此,在組件銷毀時,我們應清除組件中的這個綁定關系:
destroyed() { Bus.$off('getMore', this.getMoreList); }
3.路由前進后退時的切換動態
打開手機app頁面,當頁面前進時,切換效果一般為從右向左滑動。當后退時,我們會希望他是從左向右退出的,但是vue提供的過渡效果只允許我們有一種的效果的存在,除非根據路由的切換來改變過渡效果綁定的name值。在實現這個效果的時候,我對原有的方法進行改進。我首先想到改寫router.back()這個事件,但是因為覺得這樣不太好,因此對這個進行了一層封裝:
//router文件 Router.prototype.goBack = function () { store.commit("changeIsBack",true) this.back(-1) } //vuex文件 const state = { isBack:false } const mutations = { changeIsBack(state, flag) { state.isBack = flag } } export default { state, mutations }
這個封裝中的this.back(-1)就是this.$router.back(-1)。在router中引入vuex的store文件,使用commit改變state的值。
//pageMain.vue文件 methods: { ...mapMutations([ 'changeIsBack' ]) } beforeRouteUpdate (to, from, next) { let isBack = this.$store.state.routerState.isBack if (isBack) { this.transitionName = 'enter-right' } else { this.transitionName = 'enter-left' } this.changeIsBack(false) next() } //其余單頁返回上一級 this.$router.goback()
在頁面展示頁使用beforeRouteUpdate這個鈎子函數檢測store中isBack的值。當頁面返回時調用this.$router.goback()這個方法,此時會改變store中isBack的值。當路由更新時,檢測isBack是否為true,如果是則為返回的頁面,此時更新過渡transition的name,達到更新的目的。方案地址:https://github.com/lunlunshiwo/pageChange。
以上就是最近遇到的問題與改進解決思路。
當初因為覺得很酷炫選擇了這條路,就要好好地走下去,晚安。
掘金地址:https://juejin.im/post/5b304c65f265da59702de4c8。