摘要:歡迎體驗(yàn)提墨瞳漫畫(huà)這里踩的坑主要是組件的重用。這樣可以防止圖和圖片大小不一樣引起的頁(yè)面跳動(dòng)繼而導(dǎo)致的加載圖片時(shí)機(jī)錯(cuò)誤??缬驎r(shí),會(huì)先發(fā)送一個(gè)空的請(qǐng)求來(lái)查看接口是不是支持跨域,再發(fā)送一次真實(shí)請(qǐng)求。
前言
博主也是vuejs萌新,公司僅我一個(gè)前端,收到做h5的需求后,馬上想到要用下vuejs,于是說(shuō)服領(lǐng)導(dǎo),開(kāi)始慢慢鉆研,現(xiàn)在記錄一下踩到的坑。這些坑主要是在一些組件的使用上,其它的只要好好看官方文檔就好了,vue,vue-router, vuex的文檔相當(dāng)重要。
歡迎體驗(yàn)提bug 墨瞳漫畫(huà) m.cm233.com
vue-routerrouter這里踩的坑主要是組件的重用。構(gòu)建單頁(yè)面大型應(yīng)用的話,肯定要開(kāi)啟組件的緩存的,因?yàn)橐话銜?huì)要求后退的時(shí)候不要重新加載頁(yè)面,而且要記住原始的滾動(dòng)位置。
首先,引入router-view的地方要加上keep-alive
然后開(kāi)啟html5 history模式,并開(kāi)啟位置紀(jì)錄
const router = new Router({ history: true, // use history=false when testing saveScrollPosition: true })
開(kāi)啟keep-alive以后,當(dāng)要求一個(gè)組件的內(nèi)容發(fā)生變化時(shí),比如 漫畫(huà)詳情頁(yè)面是一個(gè)路由帶參數(shù)的組件,當(dāng)參數(shù)變化時(shí),router會(huì)重用這個(gè)組件,而不是重新請(qǐng)求數(shù)據(jù),這顯然是不符合要求的,所以正確的姿勢(shì)是:
首先,用一個(gè)字段保存這個(gè)路由參數(shù),
用router的鉤子函數(shù)data獲取路由變化參數(shù),保存到字段里
route:{ data: function(transition){ this.bookId = transition.to.params.id; } }
寫(xiě)一個(gè)watcher來(lái)拉取數(shù)據(jù)并填充模版,因?yàn)樵赿ata鉤子函數(shù)中,我們已經(jīng)修改了相應(yīng)字段,所以當(dāng)路由參數(shù)更改時(shí)會(huì)直接觸發(fā)這個(gè)watcher
watch: { "bookId" : function(val){ //do something } }
如果是多個(gè)參數(shù)的,可以把這些參數(shù)放到一個(gè)對(duì)象里,watcher采用深監(jiān)測(cè)
route:{ data: function(transition){ this.watcher.type = transition.to.params.type; this.watcher.id = transition.to.query.id; } }, watch : { "watcher" : { handler: function(val){ //do something window.scrollTo(0,0);// 不使用緩存時(shí),不使用記錄好的用戶位置,滑倒頂部 }, deep: true } }
一開(kāi)始沒(méi)有用這種方法出了很多的bug,改了以后,路由和緩存方面的邏輯瞬間就變得清晰了,組件的切換也更加流暢了。
第二個(gè)坑就是關(guān)于緩存頁(yè)面瀏覽位置的紀(jì)錄,router是通過(guò)html5 history的pushState來(lái)紀(jì)錄當(dāng)前滾動(dòng)位置的,切換路由的時(shí)候,把當(dāng)前位置push進(jìn)去,用戶后退時(shí),會(huì)觸發(fā)onpopstate事件,這個(gè)時(shí)候再把位置取出來(lái)并滾動(dòng)到指定位置,但是!某些瀏覽器本身也設(shè)置了一些奇怪的位置滾動(dòng),vue-router的滾動(dòng)就失效了,所以需要延遲執(zhí)行一下
window.addEventListener("popstate",function(e){ setTimeout(()=>{ window.scrollTo(0,e.state.pos.y);//通過(guò)打log,發(fā)現(xiàn)了位置紀(jì)錄在這個(gè)變量里了 },300) },false);
然而,瀏覽器只能記錄一個(gè)位置,所以會(huì)有這樣的情況: 從m.cm233.com 到 m.cm233.com/book,再返回到m.cm233.com,這時(shí)瀏覽器跳到了當(dāng)時(shí)記錄的位置,但是再前進(jìn)到/book時(shí),瀏覽器還是會(huì)停在首頁(yè)的那個(gè)位置上,這個(gè)bug暫時(shí)還沒(méi)有解決,好在用戶場(chǎng)景不是很多。所以告訴我們,子頁(yè)面路由參數(shù)變化的時(shí)候,要把滾動(dòng)條人工弄到最上面,要不然就會(huì)滾動(dòng)到入口頁(yè)面的瀏覽位置。也就是watcher里還要加一句如上的滾動(dòng)。
頁(yè)面標(biāo)題也是要手動(dòng)更改的,所以每個(gè)頁(yè)面要放一個(gè)專門的title變量存一下,然后在data鉤子函數(shù)(用于組件緩存時(shí)) 和 路由參數(shù)的watcher(用于組件更新時(shí)) 里 都改變title
route:{ data: function(transition){ this.title = "hiahia"; document.title = this.title; } }, watch : { "id" : function(val){ this.title = "hiahia"; document.title = this.title; } }
通常頁(yè)面的標(biāo)題不是固定的,用變量存儲(chǔ)title,主要是為了記住上一次組件被用的時(shí)候的title,以便于重用的時(shí)候更換。
然而,ios微信不會(huì)監(jiān)測(cè)document.title的變化,所以要寫(xiě)一個(gè)專門針對(duì)它的hack,通過(guò)創(chuàng)建iframe
//全局函數(shù) window.isWeiXin = function(){ var ua = window.navigator.userAgent.toLowerCase(); if(ua.match(/MicroMessenger/i) == "micromessenger"){ return true; }else{ return false; } } window.weiXinChange = function(title){ if(window.isWeiXin()){ document.title = title; var iframe = document.createElement("iframe"); iframe.src = "./favicon.ico"; iframe.style.display = "none"; iframe.onload = function(){ setTimeout(function() { document.body.removeChild(iframe); }, 0); } document.body.appendChild(iframe); } } //組件中 route:{ data: function(transition){ this.title = "墨瞳漫畫(huà)"; document.title = this.title; window.weiXinChange(this.title); } }, watch : { "id" : function(val){ this.title = "墨瞳漫畫(huà)"; document.title = this.title; window.weiXinChange(this.title); } }vue-infinite-scroll (directive)
(為什么不自己寫(xiě)?。?/p>
組件地址 https://github.com/ElemeFE/vue-infinite-scroll 餓了么出品
使用方法
main.js
import Scroll from "vue-infinite-scroll" Vue.use(Scroll)
組件中
其中busy這個(gè)變量比較重要,他控制著這個(gè)指令是否繼續(xù)執(zhí)行,當(dāng)沒(méi)有下一頁(yè)數(shù)據(jù)的時(shí)候,應(yīng)該把busy置為true來(lái)關(guān)閉滾動(dòng)加載。正在讀取下一頁(yè)數(shù)據(jù)時(shí),要先把busy置為true,數(shù)據(jù)返回時(shí)在置為false
loadmore(){ this.busy = true; someApi.someFunction().then((data) => {this.busy = false;}) }
但是這個(gè)組件在路由切換的時(shí)候會(huì)出問(wèn)題,routerView被移除時(shí),組件會(huì)觸發(fā)加載(大概是因?yàn)轫?yè)面高度突然塌陷),而且會(huì)一直加載到我們自己設(shè)置的停止條件(busy=true)。所以離開(kāi)頁(yè)面的時(shí)候,需要在路由的deactivate鉤子函數(shù)里把滾動(dòng)關(guān)掉,再次進(jìn)入頁(yè)面的時(shí)候再開(kāi)啟(路由無(wú)變化在data鉤子函數(shù)里開(kāi)啟,有變化的話在watcher里開(kāi)啟,如果不需要在路由改變時(shí)向子組件延時(shí)傳遞參數(shù)也可以都在data鉤子函數(shù)里開(kāi)啟)
route:{ deactivate: function(transition){ this.busy = true; transition.next(); }, data: function(transition){ if(){ this.busy = false; }//這里輸入組件路由參數(shù)沒(méi)有變化的條件 } }lazyload
(為什么不自己寫(xiě)!)
網(wǎng)上找了幾個(gè)lazyload的組件,都不太好使,就自己改了一個(gè),是改了一個(gè),原組件叫vue-lazyload, 毛病還挺多的,寫(xiě)這個(gè)組件的人估計(jì)沒(méi)有真正在大項(xiàng)目中用過(guò)就匆匆發(fā)布在npm了,es6版本也寫(xiě)的不倫不類的 - -,不過(guò)還是很厲害,自己寫(xiě)的話毛病肯定會(huì)更多。我改后的放在https://github.com/Ganother/blog/blob/master/lazyload.js了,是個(gè)較為穩(wěn)定的版本。其中過(guò)渡動(dòng)畫(huà)寫(xiě)在img-loaded這個(gè)class里
/*簡(jiǎn)單的透明度漸入,圖片加載完成后會(huì)刪掉這個(gè)class,以防router切換緩存頁(yè)面時(shí)再次引起動(dòng)畫(huà)*/ .img-loaded { animation: loaded .2s ease-in-out; } @keyframes loaded { 0%{ opacity: 0; } 100%{ opacity: 1; } }
let loadingJpg = require("assets/loading.jpg");//這里引入一張loading圖,會(huì)被轉(zhuǎn)成base64 Vue.use(VueLazyload, { preLoad: 1.3, //圖片頂端距窗口頂端1.3個(gè)屏幕高度時(shí)開(kāi)始加載 loading: loadingJpg, error: loadingJpg })
自適應(yīng)的圖片:如果服務(wù)端傳過(guò)來(lái)的圖片帶了寬高信息,可以在img外層包一個(gè)class為img-bar的元素,圖片過(guò)來(lái)的時(shí)候先設(shè)置一個(gè)min-height為響應(yīng)高,組件在圖片加載后會(huì)自動(dòng)取掉這個(gè)min-height。這樣可以防止loading圖和圖片大小不一樣引起的頁(yè)面跳動(dòng)繼而導(dǎo)致的加載圖片時(shí)機(jī)錯(cuò)誤。
vue-resource跨域時(shí),會(huì)先發(fā)送一個(gè)空的options請(qǐng)求來(lái)查看接口是不是支持跨域,再發(fā)送一次真實(shí)請(qǐng)求。還不是很了解這種方式的好處,當(dāng)接口較多時(shí),請(qǐng)求數(shù)量多了一倍也是有點(diǎn)尷尬的,所以要設(shè)置一下。而且如果接口每次都打印空參數(shù)的log的話。。。嗯。
Vue.http.options.emulateJSON = true; Vue.http.options.headers={ "Content-Type":"application/x-www-form-urlencoded; charset=UTF-8" };結(jié)構(gòu)目錄
vue-cli直接構(gòu)建的,src里的目錄如下
api 放一些ajax請(qǐng)求接口的函數(shù)
assets 放一些靜態(tài)資源,圖片,公共sass
directives 放一些指令js,比如改動(dòng)后的lazyload
pages 頁(yè)面入口組件,用在router中
components 小組件們
vuex vuex
app.vue
main.js
另外,可以修改下生成的靜態(tài)文件,vue-cli默認(rèn)聲稱的靜態(tài)文件時(shí)間戳是加在文件名上的,如app.fefdfd7s8f78sd7.js,這樣版本迭代很快后會(huì)使服務(wù)器上積壓過(guò)多無(wú)用文件,我們希望這樣加時(shí)間戳 app.js?t=32j32ih4u32h 所以改一下webpack.prod.conf.js就好了,如下
output: { path: config.build.assetsRoot, filename: utils.assetsPath("js/[name].js?t=[chunkhash]"), chunkFilename: utils.assetsPath("js/[id].js") } new ExtractTextPlugin(utils.assetsPath("css/[name].css?t=[contenthash]")),
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/80434.html
摘要:自適應(yīng)四宮格有這樣一張?jiān)O(shè)計(jì)稿,左右兩邊白色間距為,中間間距為,每一行的兩張圖是等寬的即平分去掉間距后的寬度有一種方法是和設(shè)計(jì)師商量,把所有的具體尺寸改為百分比尺寸。。 自適應(yīng)四宮格 有這樣一張?jiān)O(shè)計(jì)稿,左右兩邊白色間距為4px,中間間距為10px,每一行的兩張圖是等寬的(即平分去掉間距后的寬度) showImg(http://www.ganother.com/images/four-it...
摘要:自適應(yīng)四宮格有這樣一張?jiān)O(shè)計(jì)稿,左右兩邊白色間距為,中間間距為,每一行的兩張圖是等寬的即平分去掉間距后的寬度有一種方法是和設(shè)計(jì)師商量,把所有的具體尺寸改為百分比尺寸。。 自適應(yīng)四宮格 有這樣一張?jiān)O(shè)計(jì)稿,左右兩邊白色間距為4px,中間間距為10px,每一行的兩張圖是等寬的(即平分去掉間距后的寬度) showImg(http://www.ganother.com/images/four-it...
摘要:不過(guò)實(shí)踐中發(fā)現(xiàn)淘寶開(kāi)源的可伸縮布局方案效果更好且更容易使用。淘寶的方案總結(jié)為根據(jù)設(shè)備設(shè)備像素比設(shè)置的值,保持視口始終等于設(shè)備物理像素,接著根據(jù)屏幕大小動(dòng)態(tài)計(jì)算根字體大小,具體是將屏幕劃分為等分,每份為,就等于。 最近參與了APP內(nèi)嵌H5頁(yè)面的開(kāi)發(fā),這次使用vuejs替代了jQuery,僅僅把vuejs當(dāng)做一個(gè)庫(kù)來(lái)使用,效率提高之外代碼可讀性更強(qiáng),在此分享一下自己的一些開(kāi)發(fā)中總結(jié)的經(jīng)驗(yàn)。...
閱讀 1305·2021-11-24 09:39
閱讀 2686·2021-09-30 09:47
閱讀 1339·2021-09-22 15:15
閱讀 2433·2021-09-10 10:51
閱讀 1976·2019-08-30 15:55
閱讀 2987·2019-08-30 11:06
閱讀 906·2019-08-30 10:53
閱讀 848·2019-08-29 17:26