讓你的「微信小程序」運行在Chrome瀏覽器上,讓咱們使用WebStorm

「微信小程序」的開發框架體驗起來,還不錯——自帶了UI框架。可是問題是他的IDE,表現起來至關的糟糕——其實主要是由於,我當時買WebStorm License買了好多年。因此,我以爲他的IDE真不如我這個付費好用。javascript

並且,做爲一個擁護自由和開源的 「GitHub 中國區首席Markdown程序員」。微信在「微信小程序」引導着Web開向封閉,咱們不再能愉快地分享咱們的代碼了。css

若是咱們聽任下去,將來的Web世界使人堪憂。html

好了,廢話說完了:java

文章太長不想看,能夠直接看Demo哈哈:c++

GitHub: https://github.com/phodal/weapp-webdemo
預覽:http://weapp.phodal.com/git

真實世界下的MINA三基本元素

「微信小程序」的背後運行的是一個名爲MINA框架。在以前的幾篇文章裏,咱們介紹得差很少了。如今讓咱們來做介紹pipeline:程序員

Transform wxml和wxss

當咱們修改完WXML、WXSS的時候,咱們須要從新編譯項目才能在瀏覽器上看到效果。這時候後臺就會執行一些transform動做:github

  1. wcc來轉換wxml爲一個genrateFun,執行這個方法將會獲得一個virtual domweb

  2. wxss就會轉換wxss爲css——這一點有待商榷。json

wcc和wxss,能夠從vendor目錄下獲取到,在「微信web開發者工具」下敲入help,你就會獲得下面的東東:

圖片描述

運行openVendor(),你就會獲得上面的wcss、wxss、WAService.js、WAWebview.js四個文件了。

Transform js文件

對於js文件來講,則是一個拼裝的過程,以下是咱們的app.js文件:

App({
onLaunch: function () { }
})

它在轉換後會變成:

define("app.js", function(require, module){var window={Math:Math}/*兼容babel*/,location,document,navigator,self,localStorage,history,Caches;
        App({
            onLaunch: function () {

            }
        })
});
require("app.js");

我僞裝你已經知道這是什麼了,反正我也不想、也不會解釋了~~。同理於:

define("pages/index/index.js", function(require, module){var window={Math:Math}/*兼容babel*/,location,document,navigator,self,localStorage,history,Caches;
        Page({
            data: {
                text: initData
            }
        });
    require("pages/index/index.js");

至於它是如何replace或者apend到html中,我就不做解釋了。

MINA如何運行?

爲了運行一個Page,咱們須要有一個virtual dom,即用wcc轉換後的函數,如:

/*v0.7cc_20160919*/
        var $gwxc
        var $gaic={}
        $gwx=function(path,global){
            function _(a,b){b&&a.children.push(b);}
            function _n(tag){$gwxc++;if($gwxc>=16000){throw 'enough, dom limit exceeded, you don\'t do stupid things, do you?'};return {tag:tag.substr(0,3)=='wx-'?tag:'wx-'+tag,attr:{},children:[]}}
            function _s(scope,env,key){return typeof(scope[key])!='undefined'?scope[key]:env[key]}
            function _wl(tname){console.warn('template `' + tname + '` is being call recursively, will be stop.')}
            function _ai(i,p,e,me){var x=_grp(p,e,me);if(x)i.push(x);else{console.warn('path `'+p+'` not found from `'+me+'`')}}
            function _grp(p,e,me){if(p[0]!='/'){var mepart=me.split('/');mepart.pop();var ppart=p.split('/');for(var i=0;i<ppart.length;i++){if( ppart[i]=='..')mepart.pop();else if(!ppart[i])continue;else mepart.push(ppart[i]);}p=mepart.join('/');}if(me[0]=='.'&&p[0]=='/')p='.'+p;if(e[p])return p;if(e[p+'.wxml'])return p+'.wxml';}
//如下省略好多字。

而後在咱們的html中加一個script,如

document.dispatchEvent(new CustomEvent("generateFuncReady", {
        detail: {
            generateFunc: $gwx('index.wxml')
        }
    }))

就會湊發這個事件了。我簡單的拆分了WXWebview.js獲得了幾個功能組件:

  • define.js,這裏就是定義AMD模塊化的地方

  • exparser.js,用於轉換WXML標籤到HTML標籤

  • exparser-behvaior.js,定義不一樣標籤的一些行爲

  • mobile.js,應該是一個事件庫,好像我並不關心。

  • page.js,核心代碼,即Page、App的定義所在。

  • report.js,你所說的一切都可以用做爲你的呈堂證供

  • virtual_dom.js,一個virtual dom實現結合wcc使用,裏面應該還有component.css,也多是叫weui

  • wa-wx.js,定義微信各類API以及WebView和Native的地方,和下面的WX有衝突。

  • wx.js,同上,可是略有不一樣。

  • wxJSBridge.js,Weixin JS Bridge

因而,我就用上面的組件來定義不一樣的位置好了。當咱們觸發自定義的generateFuncReady事件時,將由virtual_dom.js來接管此次Render:

document.addEventListener("generateFuncReady", function (e) {
    var generateFunc = e.detail.generateFunc;
    wx.onAppDataChange && generateFunc && wx.onAppDataChange(function (e) {
        var i = generateFunc((0, d.getData)());
        if (i.tag = "body", e.options && e.options.firstRender){
            e.ext && ("undefined" != typeof e.ext.webviewId && (window.__webviewId__ = e.ext.webviewId), "undefined" != typeof e.ext.downloadDomain && (window.__downloadDomain__ = e.ext.downloadDomain)), v = f(i, !0), b = v.render(), b.replaceDocumentElement(document.body), setTimeout(function () {
                wx.publishPageEvent(p, {}), r("firstRenderTime", n, Date.now()), wx.initReady && wx.initReady()
            }, 0);
        } else {
            var o = f(i, !1), a = v.diff(o);
            a.apply(b), v = o, document.dispatchEvent(new CustomEvent("pageReRender", {}));
        }
    })
})

所以,這裏就是負責DOM初始化的地方了,這裏獲得的Dom結果是這樣的:

<wx-view class="btn-area">
    <wx-view class="body-view">
        <wx-text><span style="display:none;"></span><span></span></wx-text>
        <wx-button>add line</wx-button>
        <wx-button>remove line</wx-button>
    </wx-view>
</wx-view>

而咱們寫的wxml是這樣的:

<view class="btn-area">
  <view class="body-view">
    <text>{{text}}</text>
    <button bindtap="add">add line</button>
    <button bindtap="remove">remove line</button>
  </view>
</view>

很明顯view會被轉換爲wx-view,text會被轉換爲wx-text等等,以此類推。這個轉換是在virtual dom.js中調用的,調用的方法就是exparser。

遺憾的是我如今困在 data初始化上面了~~,這裏面有兩套不一樣的事件系統,有一些困擾。其中有一個是:WeixinJSBridge、還有一個是app engine中的事件系統,兩個好像不能互調。。。

使用WebStorm開發

在瀏覽器上運行以前,咱們須要簡單的mock一些方法,如:

  • window.webkit.messageHandlers.invokeHandler.postMessage

  • window.webkit.messageHandlers.publishHandler.postMessage

  • WeixinJSCore.publishHandler

  • WeixinJSCore..invokeHandler

而後把 config.json中的一些內容變成__wxConfig,如:

__wxConfig = {
    "debug": true,
    "pages": ["index"],
    "window": {
        "backgroundTextStyle": "light",
        "navigationBarBackgroundColor": "#fff",
        "navigationBarTitleText": "WeChat",
        "navigationBarTextStyle": "black"
    },
    "projectConfig": {
    
    },
    "appserviceConfig": {
       
    },
    "appname": "fdfafafafafafafa",
    "appid": "touristappid",
    "apphash": 2107567080,
    "isTourist": true,
    "userInfo": {}
}

如這裏咱們的appname是哈哈哈哈哈哈哈——我家在福建。

而後在咱們的html中引入各個js文件,啦啦。

咱們還須要一個自動化的glup腳原本watch wxml和wxss的修改,而後編譯,如:

exec('./vendor/wcc -d ' + inputPath + ' > ' + outputFileName, function(err, stdout, stderr) {
            console.log(stdout);
            console.log(stderr);
});

說了這麼多,你還不如去看代碼好了:

GitHub: https://github.com/phodal/weapp-webdemo
預覽:http://weapp.phodal.com/

相關文章
相關標籤/搜索