更新:2018年1月10日15:32:22
在ios8
及部分機型下會有樣式混亂的問題,經查找,原因是缺少瀏覽器前綴,需要加prefix
。
解決方案見鏈接:wepy-less-autoprefix
另外:如果直接引入了.wxss
文件,需要改成.less
。
再另:如果使用scss
,使用:wepy-plugin-autoprefixer
綜述
- 小程序開發有哪些痛點
- 什么是以及如何使用
wepy
wepy
使用注意事項- ......
一、小程序開發有哪些痛點
RT,這里給幾個我認為開發過程中不爽的幾個地方,拋磚引玉。
1) 頻繁調用 setData
及 setData
過程中頁面跳閃,張老師有篇寫的很好 Page和data
2) 組件化支持能力太弱(幾乎沒有)
3) 不能使用 less、jade
等
4) 無法使用 NPM
包及 ES
高級語法
5) request
並發次數限制
6) 一個頁面對應4個文件,看的眼花繚亂
......
P.S.如果你還不了解如何開發小程序,那么得抓緊看下小程序開發簡易教程了,兄得
二、什么是以及為什么使用 wepy
如果可以,請先花3、5分鍾看一下正經官方文檔。因為關於wepy
的一切,文檔肯定比我說的清楚。
現在,我們這樣寫小程序,是不是很嗨皮呢,(cou zi shu:
<style lang="less">
@color: #4D926F;
.userinfo {
color: @color;
}
</style>
<template lang="pug">
view(class='container')
view(class='userinfo' @tap='tap')
mycom(:prop.sync='myprop' @fn.user='myevent')
text {{now}}
</template>
<script>
import wepy from 'wepy';
import mycom from '../components/mycom';
export default class Index extends wepy.page {
components = { mycom };
data = {
myprop: {}
};
computed = {
now () { return +new Date(); }
};
async onLoad() {
await sleep(3);
console.log('Hello World');
}
sleep(time) {
return new Promise((resolve, reject) => setTimeout(() => resolve, time * 1000));
}
}
</script>
寫到這里我突然發現沒什么可寫的了,文檔都很清楚啊!MDZZ
三、wepy
使用注意事項
由於類Vue
的開發風格,使得開發效率變高了,一個頁面對應一個文件,后期維護變得更簡單了。然鵝,因為微信的種種限制以及wepy
的黑魔法,導致我們不能隨心所欲的管理應用。
3.1 數據管理問題
組件間的數據可以使用框架提供的 $emit
$broast
等方法,但頁面之間的數據,就需要我們手動管理,非常麻煩且易於出錯。
就目前來看,主要有四種方案可以選擇:
-
Gloabal
對象或Storage
使用微信提供的`getApp()`方法,可以在頁面間隨意訪問和改寫這個對象。
-
EventBus
通過訂閱/發布事件的方式,共享數據
-
Store
(臨時想到)創建一個存儲類來管理數據,本質上和`Storage`類似,但不能直接對數據進行修改而通過action觸發數據變更。
-
wepy-redux
其實官方還是提供了`redux`方案,但沒有在文檔中暴露出來,使用`wepy new demo --redux`創建。
在拼車小程序中,使用的是第二種方法,按下不表。代碼詳見
關於第三種Store
方案,原本我想使用mobx
來管理小程序的數據,嘗試后失敗了。但自己創建一個類來管理數據,總覺得有些地方不妥,真心希望你能給個意見。
Store.js ,代碼示例僅提供思路
class Store {
constructor (initState = {}) {
if (typeof initState !== 'object' || initState === null) {
throw new TypeError('[Store] Init state must be a object.')
}
const _state = this._state = deepclone(initState)
this.state = this._hookState(_state)
}
// 禁止直接修改
_hookState (_state) {
const state = {}
Object.keys(_state).forEach(key => {
if (typeof _state[key] === 'object' && _state[key] !== null) {
_state[key] = this._hookState(_state[key])
} else if (typeof _state[key] === 'function') {
throw new TypeError('[Store] state cannot save function.')
}
Object.defineProperty(state, key, {
enumerable: true,
configurable: true,
get () {
return _state[key]
},
set (newVal) {
throw new TypeError('[Store] mutate state failed. Use .mutate() to mutate state')
}
})
})
return state
}
mutate (fn) {
const newState = this._state = deepclone(
fn.apply(null, this._state)
)
this.state = this._hookState(newState)
}
}
module.exports = new Store({})
3.2 數據預加載優化
10-24更新
在使用
onPrefetch
預查詢數據時,要注意兩點:
- 必須在頁面層級上使用路由跳轉 =>
this.$navigate(url)
url
必須是相對路徑
背景:我在 page1 寫了一個倒計時,跳轉到 page2 后發現倒計時仍然在進行。這說明什么呢?
這表明在小程序內即便發生跳轉,頁面的 Javascript
數據並不會從內存中消失,和我們平常開發 H5 頁面有很大不同,是吧?
一般而言,我們請求數據是在onLoad
中進行,但是小程序的 page 1
跳轉到 page 2
,再到 page 2
的 onLoad
是存在一個 300ms ~ 400ms 的延時的(這點@張帥 的上篇文章也提到了),所以我們白白浪費了這個時間。
wepy
在這里做了很容易被忽略的優化——
-
預加載數據
用於 page1 主動傳遞數據給 page2,比如 page2 需要加載一份耗時很長的數據。我可以在 page1 閑時先加載好,進入 page2 時直接就可以使用。
-
預查詢數據
用於避免於 redirecting 延時,在跳轉時調用 page2 預查詢。
它擴展了頁面生命周期,添加了onPrefetch
事件,使得在 $redirect/$navigate
之時被主動調用。同時,給onLoad
事件添加了一個參數,用於接收預加載或者是預查詢的數據,如下:
// params
// data.from: 來源頁面,page1
// data.prefetch: 預查詢數據
// data.preload: 預加載數據
onLoad (params, data) {}
預加載數據示例:
// page1.wpy 預先加載 page2 需要的數據。
methods: {
tap () {
this.$redirect('./page2');
}
},
onLoad () {
setTimeout(() => {
this.$preload('list', api.getBigList())
}, 3000)
}
// page2.wpy 直接從參數中拿到 page1 中預先加載的數據
onLoad (params, data) {
data.preload.list.then((list) => render(list));
}
預查詢數據示例:
// page1.wpy 使用封裝的 redirect 方法跳轉時,會調用 page2 的 onPrefetch 方法
methods: {
tap () {
this.$redirect('./page2');
}
}
// page2.wpy 直接從參數中拿到 onPrefetch 中返回的數據
onPrefetch () {
return api.getBigList();
}
onLoad (params, data) {
data.prefetch.then((list) => render(list));
}
3.3 數據上報(並沒有做)
MTA是騰訊自家的數據分析平台,在小程序發布后MTA平台很快的就支持了小程序的數據上報。因此手機充值選擇MTA做為數據上報平台,具體步驟如下:
在MTA官網注冊應用;
在mp平台,小程序開發設置中,將https://pingtas.qq.com
添加為可信域名;
安裝 mta-analysis
模塊:npm install mta-analysis --save
;
在 app.wpy 中添加初始化代碼。
import wepy from 'wepy';
import mta from 'mta-analysis';
export default class extends wepy.app {
onLaunch() {
mta.App.init({
"appID":"xxxx", // 注冊后得到的appID
"eventID":"xxxx", // 注冊后得到的eventID
"statPullDownFresh":true, // 使用分析-下來刷新次數/人數,必須先開通自定義事件,並配置了合法的eventID
"statShareApp":true, // 使用分析-分享次數/人數,必須先開通自定義事件,並配置了合法的eventID
"statReachBottom":true // 使用分析-頁面觸底次數/人數,必須先開通自定義事件,並配置了合法的eventID
});
};
}
這樣就完成了MTA的初始化工作,在每個頁面的 onLoad 事件中加入 init 事件完成頁面的上報。
export default class Index extends wepy.page {
onLoad () {
mta.Page.init();
};
}
在 app.wpy 中加入報錯上報。
export default class extends wepy.app {
onError () {
mta.Event.stat("error",{});
};
}
以及在其它業務邏輯代碼上加入一些自定義事件上報,比如下單上報,支持上報等等。
mta.Event.stat("payed",{});
3.4 Integrating TypeScript
還是算求 D:
待續......