起因
事情是這樣的
一天早上組裡還早激烈的討論某個專案的可用性和發展前景,突然老大說了句,能不能做個小程式的版本呢?然後大家紛紛討論起來,有反對有支援,我就說了一句,剛出來的時候搞過一會。。。然後就把我推出來了(日了狗了~~)
這個專案大概一個星期之後就要推出去了,換句話說,我要一個星期內搞個小程式的版本出來,寶寶有點慌了~~
不過既然接手了還是要好好做的,首先的,完全自己搞肯定是來不及,專案的模組絕對要複用起來,思索下大概有3點需要搞
-
HTML
-
CSS
-
javascript module
CSS
其中CSS在小程式的叫做WXSS,基本和CSS語法類似了,也就需要將標籤選擇器改了,比如
table{
//XXX
}
//改成
.table{
}
還有就是WXSS的尺寸單位比較推薦使用rpx,但是這裡還是繼續使用px,當然在響應式方面還需要自己改改,工程量不是很大
JS
對於JS方面就比較棘手了一點,唯一慶幸的是,原專案是用vue來做框架搭建的,仔細觀察下小程式框架的語法結構,發現其實和vue很類似,都具備生命週期和各種事件繫結等等,所以在整體JS結構上面大概有幾點需要修改
-
生命週期函式
created: function () {
//xx
}
//改成
onLoad: function() {
}
-
資料繫結
this.container = ``;
//改成
this.setData({
"container": ``
});
剩下的就是模組的引用,小程式本身也支援ES6語法,但還是有缺陷,比如不支援promise,可以通過引入相應的polyfill 來解決,還能順便讓小程式本身的API也應用上promise
//util.js
import Promise from `./bluebird.min`;
export const wxPromise = function(fn) {
return function (obj = {}) {
return new Promise((resolve, reject) => {
obj.success = function(res) {
resolve(res);
}
obj.fail = function(err) {
reject(err);
}
fn(obj)
})
}
}
可以在需要呼叫的地方引入,或者直接在APP.js裡面封裝原API,然後掛載在全域性上面
import {wxPromise} from `../../utils/util`;
let login = wxPromise(wx.login);
let getUserInfo = wxPromise(wx.getUserInfo);
login()
.then((res) => {
console.log(res);
return getUserInfo();
})
.then((res) => {
console.log(res);
})
.catch((res) => {
console.log(res);
})
原專案裡面的模組還呼叫了window物件的屬性,比如localstorage、innerWidth、innerHeight等等,在開發工具裡面輸出console.log(window)直接甩了我一個大大undefined,呵呵,都快崩潰了,後來想想,也不是完全沒有辦法,小程式也有類似的API來實現這些方法和屬性,我要做的就是造一個window物件給它就可以了,老樣子,直接掛載全域性就行
App({
window: {},
location: {
href: `http://localhost/index.html?clear`
},
onLaunch: function() {
let _this = this;
getSystemInfo()
.then((res)=>{
_this.window.innerWidth = res.windowWidth;
_this.window.innerHeight = res.windowHeight;
})
_this.window.localStorage = {};
_this.window.localStorage.setItem = wx.setStorageSync;
_this.window.localStorage.getItem = wx.getStorageSync;
_this.window.localStorage.clear = wx.removeStorageSync;
}
})
//注入到頁面或者模組
let {window, location} = app;
HTML
最後一個難題就是HTML了,首先HTML直接套在WXML上面是行不通的,結果是可以編譯顯示出來,但是完全失去了HTML各個標籤的意義,比如div塊級標籤所具備的屬性都不存在了,當然你可以通過WXSS新增屬性來相容,比如
div, p {
display:blcok
}
我個人並不贊同這種做法,因為在HTML中img、canvas等等並沒有要求閉合標籤,但是WXML是嚴格要求每個標籤都要有閉合,就是說你想通過新增WXSS屬性來相容的話,首先要手動加img和canvas的閉合標籤(在小程式中img標籤應該是image,不然還是無法顯示圖片),其次就是怕官方下次更新迭代突然加入div這個元件,然後又要改版,煩~~
那麼唯一的出路就是將HTML轉成符合小程式的WXML出來,作為一個程式設計師,手動改也太掉價了。。。直接上工具,google查下,發現網上也有類似的工具出來,工具的轉換原理是這樣的話,首先HTML先轉換成json物件,然後注入到模版,由模版生成。
但是有2個問題
1、轉換出來的WXML是依賴模版渲染的,首先小程式的模版是不支援遞迴呼叫的,就是說,假如你的標籤有6層巢狀的話,那麼你需要複製6份模版出來,然後tmp1巢狀tmp2…temp6,這樣的話你只能祈禱工具帶來的模版有巢狀了足夠多。
2、無法實現資料繫結,比如
<div>{{text}}</div>
//轉換後原樣輸出了{{text}}
<view>{{text}}</view>
既然模版輸出這條路走不通,那就只能藉助node動態的輸出WXML,思路和上面差不多,也是HTML生成json dom,然後遞迴渲染wxml節點,最後輸出一份wxml檔案,工具的實現在這裡,細節就不多說了,目前還沒有做canvas、audio、video標籤的轉換,有BUG的話直接提issue,最後求star
總結
沒事別BB