美團小程式框架mpvue踩坑總結編一
第一次接觸小程式大概是17年初,當時小程式剛剛內側,當時就被各種限制折騰的死去活來的,單向繫結,
沒有promise,請求數限制,包大小限制,各種反人類,...反正我是感受到了滿滿的惡意.
最近接到一個工程類的小程式專案,做技術選型的時候,又把以前的東西撿起來看了看,重新熟悉了一下,
感覺小程式還是有在努力的,支援大部分es6語法了,還出了一個類Vue的mvvm框架wepy,還支援redux狀態管理,
就大致建了個demo,跑了起來,趕緊雖然沒有vue那麼酸爽,但是還是挺ok的,至少比原生的小程式語法親民很多.
然後就開始用wepy搭專案,寫靜態頁面(由於公司的開發模式是先寫靜態頁面,
等待後端的同學介面出來了再繫結資料),雖然wepy用起來比原生的順手,
但是還是有很多坑的,這裡就不列舉了.....
就在我們靜態頁面快寫完的時候,某天晚上論壇的時候看到一條訊息, 美團出了個小程式框架mpVue
(不知道為什麼,每次看到這個名字,我只想到3個字,沒朋友,哈哈),
大致看了一下官方的介紹,主要有一下亮點:
- 跟vue一樣的開發體驗,包括vuex
- H5程式碼轉換編譯成小程式目的碼的能力
也就是說,不但可以用我們熟悉的vue語法開發,還有可能直接把你的h5頁面編譯成小程式.
該專案到目前位置,開源不到20天,已經收到將近7000個star,可見天下苦秦已久。
建了個demo,跑了一下,感覺簡直就是開發界的良心之作啊.順便把之前寫的wepy的靜態頁面程式碼複製過來看了一下,
發現只要改動一點點,就可以順利從wepy切換到mpvue上來(整個專案的切換時間在半天左右).
說做就做,當天就切到mpvue.一直到現在專案接近尾聲了,整個開發過程,真是令人愉悅.
Bug....我今天好像不是來給mpvue做廣告的,我是來找茬的..
下面就盤點一下我最近用mpvue開發,遇到的一些需要需要注意的細節.(或者說跟vue不同的地方)
一, 這個個人感覺是最大的坑,除了缺少檔案會報錯外,其他的程式碼語法錯誤等,
控制檯大部分時間都是安靜的(偶爾也會報一個xxx is undefined)
比較經常碰到的是這樣 this.xxx =5 有些情況下會報錯,而有些情況下則沒有任何反應,
具體什麼情況下會,什麼情況下不會,我現在還沒摸出規律來..
有一次我把
this.dataObject.map(() => { ...這裡省略... })
結果map前面的 . 不小心給露掉了,實際程式碼變成
this.dataObjectmap(() => { ...這裡省略... })
結果找了半天沒找到問題的原因
二, 這個也是比較難受的地方,就是模板的資料繫結裡面,沒辦法在模板語法裡面呼叫methods方法
(或者說沒辦法呼叫computed以外的函式),有人也許會說,那可以用computed屬性,那如果我想給函式傳參怎麼辦?
看下面程式碼:
<template>
<view v-for="item in costList" >
{{formatCost(item)}}
</view>
</template>
<script>
export default {
data(){
return{
costList:[]
}
},
methods: {
formatCost(item){
return item.toFixed(2)
},
getData(){
let arr = [3.255,4.1,5,15]
this.costList = arr
}
}
</script>
這個時候 {{formatCost(item)}}
裡面的內容,會渲染成空字串,理由就是因為不支援函式,而且這中情況,
也無法使用computed屬性,除非你想為每個陣列元素寫一個computed
這種情況,我的解決方案是在在獲取到資料的時候,就先把資料改了.如上面的例子,我們可以在 getData方法裡面這樣寫
let arr = [3.255,4.1,5,15]
// 遍歷陣列裡面的元素,然後格式化一下,新增到 costList裡去
arr.map(item => {
this.costList.push = this.formatCost(item)
})
三, 所有頁面裡面的created生命週期函式 都會在小程式載入的時候,
一次性執行,而不是每進入一個頁面執行一次,如,我有3個頁面
pageA
...省略一些程式碼...
creatted(){
console.log('pageA 的 created函式執行')
}
pageB
...省略一些程式碼...
creatted(){
console.log('pageB 的 created函式執行')
}
pageC
...省略一些程式碼...
creatted(){
console.log('pageC 的 created函式執行')
}
然後,啟動小程式,不進入這3個頁面,假設我現在有一個index頁面,我們開啟這個頁面,會有一下輸出
pageA 的 created函式執行
pageB 的 created函式執行
pageC 的 created函式執行
這個其實很好解決,用mounted或者onLoad或者onReady代替,說到這幾個函式,那就順便提一下,
這裡的created和mounted是vue(mpvue)的生命週期,而onLoad、onReady是小程式的生命週期,mpvue官方給的說明是:
除了 Vue 本身的生命週期外,mpvue 還相容了小程式生命週期,這部分生命週期鉤子的來源於微信小程式的
Page, 除特殊情況外,不建議使用小程式的生命週期鉤子。
但是官方給的生命週期圖示裡面,也表明了,小程式的onLoad、onReady比created、mounted執行的早,
也就是說如果我們在和onLoad onReady裡面去請求資料的話,會相對的減少白屏時間(這裡說的白屏是指資料未渲染的介面),
而且官方沒說明為什麼不建議使用小程式的生命週期,我們也嘗試了,用小程式的生命週期,沒發現生命問題,
所以我們還是比較傾向優先使用小程式的生命週期,畢竟使用者體驗才是王道。
四、掛載在Vue.prototype上的屬性,在模板語法裡面是undefined,必須經過computed計算過一下才能用。
在用vue的時候,我喜歡把圖片的伺服器路徑存到vue的原型裡面:
import config from './config'
Vue.prototype.$serverPath = config.serverPath
然後 我們在頁面裡面這樣用
<img :src="$serverPath + 'logo.png'" />
這樣 就可以避免在每個頁面匯入config檔案,後期如果我們釋出正式版的時候,只要在這邊修改一下config配置檔案就可以了
然額,這樣寫在mpvue裡面,實際渲染出來的會是
<image src="undefinedlogo.png" ></image>
要想在每個頁面裡面使用,只能乖乖在每個頁面裡面匯入,或者在computed裡面返回this.$serverPath
五、用 v-for迴圈的時候,如果要給當前項指定一個索引,在vue下,為了省事,我通常喜歡這樣做
v-for="item,index in list"
因為多打一對括號真的是很煩人。但是在mpvue下面卻不行,你必須老老實實這樣寫,否則會報錯。
v-for="(item,index) in list"
六、單獨為每個頁面的設定頁面頭部資訊,有提供這個功能,不過文件不是很詳細,幾經嘗試,才試出來。
我們的入口檔案main.js(延續vue的叫法,暫且這麼稱呼吧,其實我覺得應該叫配置檔案)裡面可以這樣配置,
官方文件大概也是這麼說的
這部分內容來源於 app 和 page 的 entry 檔案,通常習慣是 main.js,你需要在你的入口檔案中
export default { config: {} },這才能被我們的 loader 識別為這是一個配置,需要寫成 json 檔案。
import Vue from 'vue';
import App from './app';
const vueApp = new Vue(App);
vueApp.$mount();
// 這個是我們約定的額外的配置
export default {
// 這個欄位下的資料會被填充到 app.json / page.json
config: {
pages: ['static/calendar/calendar', '^pages/list/list'], // Will be filled in webpack
window: { // 頂部欄的統一配置
backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#455A73',
navigationBarTitleText: '美團汽車票',
navigationBarTextStyle: '#fff'
}
}
};
同時,這個時候,我們會根據 entry 的頁面資料,自動填充到 app.json 中的 pages 欄位。
pages 欄位也是可以自定義的,約定帶有 ^ 符號開頭的頁面,會放到陣列的最前面。
我們看到,可以在config.window下面配置全域性的頂部欄樣式,但是如果我們想為每個頁面指定一個樣式呢?事實上,
以上方法只適合配置app.json裡面的內容,如果你想要為你的每個頁面都新增一種樣式,那麼應該這樣做:
在頁面所屬的入口檔案(main.js)裡面新增以下內容,比如我想為 userCenter/index頁面設定一個標題,
應該在userCenter/main.js裡面加入
export default {
config: {
navigationBarTitleText: '個人中心',
}
}
注意 這裡跟上面那個全域性配置不同的是,配置內容navigationBarTitleText是config的屬性,
而全域性配置裡,則是config.window的屬性
七、元件的命名問題,有一次,我寫了一個區域性的元件,為什麼叫區域性的元件呢,因為我只在某個頁面裡面使用,
所以為了簡單化,我給這個元件取了個名字叫list.vue
,然後在父元件引用:
<template>
<!-- 省略其他程式碼 -->
<list />
</template>
<script>
import list from './components/list'
export default {
components: {list},
// 省略其他程式碼
}
</script>
元件能正常顯示,樣式也沒問題,一切看上去都是那麼的正常,然而元件裡面的邏輯就是不會執行。
加上本文第一點提到的,不會報錯,讓我一頓好找啊...
經過排查發現,跟元件的引入名稱有關,應該是跟微信的關鍵字同名了。
<template>
<!-- 省略其他程式碼 -->
<listA />
</template>
<script>
import listA from './components/list'
export default {
components: {listA},
// 省略其他程式碼
}
</script>
這樣就能正常執行,出了list,我目前踩到的還有tabbar,搞得我現在命名的時候,看到一些疑似關鍵的字眼,心理都有點陰影。。
這個應該是微信的問題吧,總之遇到了,就一塊寫出來。
八、元件第一次載入的時候不能執行onShow裡面的內容,只有在隱藏又顯示後,才會顯示,而頁面卻每次進入都會顯示
例如我們在一個元件裡有一下程式碼
onLoad () {
console.log('onLoad')
},
onShow () {
console.log('onShow')
},
mounted () {
console.log('mounted')
},
頁面載入的時候,我們期望列印出來的是
onLoad
onShow
mounted
然後實際上,只列印出
onLoad
mounted
這個問題,我已給官方提Issue,不過目前還沒得到迴應
說到這裡,我們順便看看小程式的頁面跳轉方式,小程式在一個頁面跳轉(呼叫wx.navigateTo)到另一個頁面的時候,
並不會銷燬原來的頁面,而是轉到後臺去,並且執行原頁面裡面的onHide裡的程式碼,
這也是為什麼小程式的頁面路徑最多隻能十層,因為你訪問過的頁面,正常都會儲存在記憶體裡,相當於vue裡的keep-alive,
如果允許跳轉非常多頁面的話,很容易導致記憶體使用過高。
當然,我們也可以使用wx.navigateBack wx.redirectTo wx.reLaunch 來銷燬頁面,這3個方法,會呼叫頁面的onUnload函式
九、canvas放在scroll-view不會隨著頁面滾動,看起來好像是fixed固定在某個位置的,但是在普通的view裡面卻可以正常滾動。
這個問題其實是微信的問題,官方文件裡面是有說明這點,不過我遇見問題的時候,沒想到會是微信官方出的問題,各種百度谷歌,
都沒找到這跟這個問題有關的,甚至我很懷疑是我自己程式碼的問題,於是新建了一個專案,然後直接考官方的示例程式碼,也是一樣的效果。
後面就準備放棄,想其他解決方案了,沒想到今天在官方文件 -scroll-view元件
的介紹的最底部的 小字 裡看到了
tip: 請勿在 scroll-view 中使用 textarea、map、canvas、video 元件
進一步檢視了canvas元件
的文件,發現也有類似的提示
tip: 請勿在 scroll-view、swiper、picker-view、movable-view 中使用 canvas 元件。
之所以把這一點也算進來,一是為這個問題坑了我好幾天,我都在想其他方案了,二是這幾天各種百度谷歌,
是有搜到幾個類似的問題,但是都沒人回答,我就在這邊記錄一下,希望後面踩到這個坑的童鞋能搜到。
十、同一個子元件,在2個不同的地方引用,會導致2個地方的樣式都載入不了,而如果只在一個地方引用卻沒問題,
為什麼把這個問題放到最後? 因為這只是前幾個版本的腳手架有這個問題,後面的應該就沒有這個問題了。
這個問題我也給官方提過Issue,官方給的回答是用新版本的腳手架重新生成專案,但是專案都快做完了,
這個時候重新生成,然後拷貝程式碼,感覺心太累了,所以抱著不折騰不罷休的態度,終於找到原因,是因為早期版本的腳手架,
缺少了 webpack-mpvue-asset-plugin 這個外掛,新版的cli裡面會自動新增這個外掛。具體看Issue #180
還有一些官方明確指出的問題,這裡就不一一列舉了,有興趣的童鞋可以直接檢視mpvue官方文件
另外,最近正在做一個mpvue的基礎教程,有興趣的童鞋請前往我的
github mpvue-tutorials,
您的一個Star,就是我最大的動力了。
相關文章
- mpvue小程式以及微信直播踩坑總結Vue
- [小程式] mpVue 踩坑Vue
- 美團小程式框架mpvue蹲坑指南框架Vue
- mpvue小程式踩坑之旅Vue
- 美團小程式框架mpvue入門教程框架Vue
- 美團小程式框架mpvue(花名:沒朋友)蹲坑指南框架Vue
- 微信小程式mpvue(沒朋友)踩坑指南微信小程式Vue
- mpvue開發微信小程式踩坑筆記Vue微信小程式筆記
- 小程式開發-mpvue構建小程式專案-1-踩坑Vue
- mpvue“踩坑”指南Vue
- mpVue 踩坑記Vue
- mpvue開發小程式總結Vue
- 小程式開發總結一:mpvue框架及與小程式原生的混搭開發Vue框架
- mpvue開發音訊類小程式踩坑和建議Vue音訊
- mpvue實戰開發美團外賣小程式Vue
- 使用mpvue開發github小程式總結VueGithub
- Mpvue 小程式轉 Web 實踐總結VueWeb
- 小程式踩坑日記 (一)
- 小程式踩坑
- 小程式踩坑填坑
- 使用setInterval與clearInterval踩的小坑總結
- mpvue 小程式框架 入門Vue框架
- 微信小程式踩坑指南【一】微信小程式
- 小程式踩坑(2)
- 第一個mpvue小程式開發完了,來總結下吧Vue
- Vue + TypeScript 踩坑總結VueTypeScript
- 小程式實戰踩坑之B2B商城專案總結
- c語言踩坑總結C語言
- mpvue & 小程式開發過程中的坑Vue
- Taro 小程式 踩坑記錄
- 小程式實踐小坑小結(一)
- mpvue框架搭建採坑記錄Vue框架
- stylelint 接入實戰踩坑總結
- Kafka SASL ACL配置踩坑總結Kafka
- 微信小程式框架wepy踩坑記錄(與vue對比)微信小程式框架Vue
- iOS 小坑總結iOS
- 微信小程式踩坑記錄微信小程式
- wepy小程式踩過的坑(1)