小程序学习3

从map组件说起

在今天公布的开发文档里,我们知道使用一个地图组件的时候是这样子的:

 

<map longitude="23.099994" latitude="113.324520" markers="{{markers}}" covers="{{covers}}" style="width: 375px; height: 200px;"></map>

在之前的文件里,我们提到过这个文件是wxml文件,然后我们要用wxcc将其转换为virtual dom中的方法,如:


它就会返回一个js的方法,如:


插播一句:上面有一个count,很有意思$gwxc > 16000,这个就是dom数的count。超了就来个异常:enough, dom limit exceeded, you don't do stupid things, do you?,中文意思就是:你个愚蠢的人类,你是一个前端开发人员吗?

随后,在浏览器里调试一下:


在微信中是要这样调用的:


就会返回下面的结果:


看来这个名为wx-map的标签就是微信下的map标签,它是wx-page的children。然后让我们在WAWebview中搜索一下,就会发现一个很有意思的代码:


它的behaviors中有一句:wx-native,这莫非就是传说中的native组件:


顺便再看一个video是不是也是一样的:


好了,你那么聪明,我就这么说一半好了,剩下你自己去猜。

可以肯定的是:

  • map标签在开发的时候会变成HTML + CSS

  • map标签在微信上可以使用类似于Cordova的形式调用 Native组件

再接着说,virtual dom的事,回到示例代码里的map.js:


js里只放置了data,剩下的都是依据上面的值变动的observer,如:

  • _updatePosition

  • _hiddenChanged

  • latitudeChanged

  • longitudeChanged

  • scaleChanged

  • coversChanged

  • ...

这种代码的感觉比React更进了一步的节奏,本来你还需要编码来观察state,现在只需要state变动了就可以了。。。23333....,你们这些程序员都会被fire的。

好了,这里差不多就这样了~~。

重新审视WXWebview.js

于是,我重新逛逛WXWebview.js,发现这个文件里面不只有component的内容,还有:

  • reportSDK

  • webviewSDK ??

  • virtual_dom

  • exparser

  • wx-components.js

  • wx-components.css

等等,你是不是已经猜到我在说什么了,上一篇中我们说到了PageFrame:


在之前的想法里,我觉得我必须要集齐上面的SDK,才能招唤中神龙。后来,我看到了这句:


如果不是开发环境就使用WAWebview.js,在开发环境中使用使用xxSDK,那么生产环境是怎么回事?如果是在开发环境会去下载最新的SDK,好像不对~~,哈哈。。

我猜这部分,我需要一个内测id,才能猜出这个答案。

有意思的是,IDE会对比version.json,然后去获取最新的,用于预览或者区分对待开发者?


上面已经解释清楚了WAWebview的功能了,那么WAService.js呢——就是封装那些API的,如downloadFile


这一点上仍然相当有趣,在我们开发的时候仍然是WAWebview做了相当多的事,而它和WAService的打包是分离的。

那么,我们从理论上来说,只需要有WAWebview就可以Render页面了。

「微信小程序」的开发框架体验起来,还不错——自带了UI框架。但是问题是他的IDE,表现起来相当的糟糕——其实主要是因为,我当时买WebStorm License买了好多年。所以,我觉得他的IDE真不如我这个付费好用。


而且,作为一个拥护自由和开源的 「GitHub 中国区首席Markdown程序员」。微信在「微信小程序」引导着Web开向封闭,我们再也不能愉快地分享我们的代码了。

如果我们放任下去,未来的Web世界令人堪忧。

好了,废话说完了,本文只是一个Demo的介绍。文章太长不想看,可以直接看Demo哈哈:

GitHub: https://github.com/phodal/weapp-webdemo
预览:http://weapp.phodal.com/

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

「微信小程序」的背后运行的是一个名为MINA框架。在之前的几篇文章里,我们介绍得差不多了。现在让我们来作介绍pipeline:

Transform wxml和wxss

当我们修改完WXML、WXSS的时候,我们需要重新编译项目才能在浏览器上看到效果。这时候后台就会执行一些transform动作:

  1. wcc来转换wxml为一个genrateFun,执行这个方法将会得到一个virtual dom

  2. wxss就会转换wxss为css——这一点有待商榷。

wcc和wxss,可以从vendor目录下获取到,在“微信web开发者工具”下敲入help,你就会得到下面的东东:


运行openVendor(),你就会得到上面的wcss、wxss、WAService.js、WAWebview.js四个文件了。

Transform js文件

对于js文件来说,则是一个拼装的过程,如下是我们的app.js文件:


它在转换后会变成:


我假装你已经知道这是什么了,反正我也不想、也不会解释了~~。同理于:


至于它是如何replace或者apend到html中,我就不作解释了。

MINA如何运行?

为了运行一个Page,我们需要有一个virtual dom,即用wcc转换后的函数,如:


然后在我们的html中加一个script,如


就会凑发这个事件了。我简单的拆分了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:


因此,这里就是负责DOM初始化的地方了,这里得到的Dom结果是这样的:


而我们写的wxml是这样的:


很明显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,如:


如这里我们的appname是哈哈哈哈哈哈哈——我家在福建。

然后在我们的html中引入各个js文件,啦啦。

我们还需要一个自动化的glup脚本来watch wxml和wxss的修改,然后编译,如:

Virtual Dom的表现形式

为了将真实的DOM转换为Virtual DOM,我们需要将DOM以一定的形式保存下来,如MINA的:

<map longitude="23.099994" latitude="113.324520" markers="{{markers}}" covers="{{covers}}" style="width: 375px; height: 200px;"></map>

如:


又或者是React中的:


当然我们也可以自己实现一个比较简单的DOM转为Virtual DOM,如将


转换为接近原生的:

原生的Parser

我会假装你已经知道了浏览器相关的很多细节,我也假装我已经对这些细节很清晰。下图一份Webkit浏览器的早期架构图:

如果我们使用JS实现一个将WXML将换为DOM JSON,我们就需要间接通过JavaScript Engine(即JSCore )来转换这个JSON文件。当有大量的DOM的时候,这就不是一件轻松的事了。所以,在WCC的生成代码里对DOM的数量限制为16000

我们可以用原生的接口来将WX DOM转换为JSON,但是我们没有办法用原生的接口来将DOM JSON转换DOM——毕竟我们还有大量的数据和绑定函数。

而这一点对于混合应用来说,就特别有帮助:

如果这个插件可以用在Cordova上,那么它将改善混合应用的性能。

数据绑定

当我们触发了generateFunc方法的时候:


我们调用下面的方法去初始化我们的DOM,并把数据传输进去:

函数绑定

MINA的函数绑定机制是由函数名来决定的,如:


对于其他类型的绑定则是:


PS:我突然就不想看这个if else经过minify以后的代码了,太恶心了。。。

如,我们的wxml:

<map longitude="23.099994" latitude="113.324520" markers="{{markers}}" covers="{{covers}}" style="width: 375px; height: 200px;"></map>

我们的propKey是bindtap,我们的propValue是bindViewTap,随后我们就会根据当前的函数名去创建相应的事件。

 

在「微信小程序」带领Web走向封闭之前,让我们创造一个Neo的种子。如果有可能的话,那么有一天,它终将成为Neo。


从微信小程序开始内测时,很多人(也包括我)都在考虑这样的问题:「微信小程序」正在让Web走向封闭。我的第一反应是:创建一个兼容「微信小程序」的Web框架——它即可以在微信上运行,也可以在Web上,还有作为一个混合应用运行。

在微信web开发者工具里,它封装了足够多的细节。我们只需要写一些我们不知道它们是如何真正工作的代码,流量都这样被截胡了。虽然,我们无法改变这个即将发生的事实,但是我们可以向那些愿意走向开放的人一个更好的解决方案。

因为「微信小程序」的框架是叫MINA,所以让我们称呼这个框架为WINV。

设计构思

基本的设计点有:

  • 兼容微信小程序的语法——它并没有多少复杂的语法。只是简单的Virtual DOM操作,以及事件绑定

  • 尽可能兼容大部分的微信API,兼容所有的微信API几乎是不可能的。

  • 提供一个Virtual DOM转换的混合应用插件。

在之前的文章里,我们提到了MINA框架的基本原理,也差不多就是组件:

  • WXML转JSON Virtual DOM组件

  • Virtual DOM组件,并在这其中提供双向绑定

  • UI组件转换器,即将WXML转换为Web浏览器中的标签

  • UI组件,需要有一套UI组件,最好是和小程序保持一致,如WEUI

  • AMD组件,提供模块化需求

  • APP引擎,需要有Page模块和APP模块,来处理页面逻辑,还有Route。

一个WINV框架的Demo

计划了好几天的Demo,终于写完了,并且可以出来溜溜了~~。

这份代码在GitHub上,欢迎试玩:https://github.com/phodal/winv

并创建一个更好的出来,毕竟国庆要和我们家 ‘花仲巴’出去玩。

好了,看我们的代码,这还只是一个丑陋的原型,但是差不多可以解释了。

var App = winv.App;var Page = winv.Page;
App({    
    onLaunch: function() {        
       console.log('On Launch');
    }
});Page({
    data: {
        motto: 'hello, world'
    },    
    onLoad: function() {        
       console.log('On Load');
    }
});
winv.setTemplate('<view class="container"><text class="user-motto">{{motto}}</text></view>')
winv.appRun();

它在页面上的运行结果就是,输出一个 hello, world。顺便吐槽一句,微信小程序自带的hello world不是标准的hello world。Wiki上说:

但是需要注意的是,Hello World的标准程序是“hello, world”,没有感叹号,全部小写,逗号后面有空格,与现在流行的写法并不一致。

出于原型的原因考虑,没有像MINA一样,使用大量的事件来触发,只是简单的Run:

var domJson = this.stringToDomJSON(this.template)[0];
var dom = this.jsonToDom(domJson);
document.getElementById('app').appendChild(dom);
for (var event in window.eventPool) {
  window.eventPool[event]();
}

第一步,将上面的Template转化为JSON格式的Template,由DOMParser将其转换为DOM,并在这个时候添加一个Page标签。然后在转换的时候,顺便做一些更新的数据操作。
第二步,这个JSON DOM在转换成真实的DOM的时候,应该要添加事件绑定,只是还没有实现。
第三步,上面的DOM会被放到app ID里,结果就变成了

<winv-div class="page">
    <winv-div class="page__hd">
        <winv-view class="container">
            <winv-text class="user-motto">hello, world</winv-text>
        </winv-view>
    </winv-div> 
</winv-div>

一看就知道还有好多坑要填。

第四步,则是调用上面的on方法,写得比较简单、粗暴。

至于,对事件和数据的判断还是和MINA一致:

if('on' === option.slice(0, 2))

简单,而又粗暴。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值