这里有新鲜出炉的微信小程序入门,程序狗速度看过来!
微信小程序(weixinxiaochengxu),简称小程序,缩写 XCX,英文名 mini program,是一种不需要下载安装即可使用的应用,它实现了应用 "触手可及" 的梦想,用户扫一扫或搜一下即可打开应用。
这篇文章主要介绍了微信小程序 在 Chrome 浏览器上运行以及 webStorm 的使用的相关资料, 需要的朋友可以参考下
「微信小程序」的开发框架体验起来,还不错——自带了 UI 框架。但是问题是他的 IDE,表现起来相当的糟糕——其实主要是因为,我当时买 WebStorm License 买了好多年。所以,我觉得他的 IDE 真不如我这个付费好用。
而且,作为一个拥护自由和开源的 「GitHub 中国区首席 Markdown 程序员」。微信在「微信小程序」引导着 Web 开向封闭,我们再也不能愉快地分享我们的代码了。
如果我们放任下去,未来的 Web 世界令人堪忧。
好了,废话说完了:
文章太长不想看,可以直接看 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 文件:
- 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 得到了几个功能组件:
于是,我就用上面的组件来定义不同的位置好了。当我们触发自定义的 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 一些方法,如:
然后把 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/
来源: http://www.phperz.com/article/17/0712/331569.html