13518219792

建站动态

根据您的个性需求进行定制 先人一步 抢占小程序红利时代

微信小程序架构分析(中)

【引自第九程序的博客】本文探讨一下小程序的 view 模块和 service 模块是如何构成的。

成都创新互联公司主要从事网站制作、网站建设、网页设计、企业做网站、公司建网站等业务。立足成都服务浦口,十多年网站建设经验,价格优惠、服务专业,欢迎来电咨询建站服务:13518219792

打开微信 web 开发者工具,然后输入 openVendor() 便会打开 WeappVendor这个目录,这里包含了 view 模块和 service 模块使用的几个核心文件:

view 页面详解

view 页面的 template 如下:

 
 
 
 
  1.  
  2.  
  3.  
  4.    
  5.    
  6.    
  7.  
  8.    
  9.  
  10.    
  11.  
  12.    
  13.  
  14.    
  15.  
  16.    
  17.  
  18.    
  19.  
  20.    
  21.  
  22.    
  23.  
  24.    
  25.  
  26.    
  27.  
  28.    
  29.  
  30.    
  31.  
  32.    
  33.  
  34.    
  35.  
  36.  
  37.  
  38.   
     
  39.  
  40.  
  41.   

其中 会在 dev 模式开启后被替换为一个时间锚点,例如:

 
 
 
 
  1.  

会被 WAWebview.js 内代码替换

之间暂时没有被使用到

会被 wcc 命令生成后的 js 代码替换

除了上面这些,页面上还会被插入页面和应用的 style 标签,如:

 
 
 
 
  1.  

这里的 wxss 文件包含的是原始 wxss 文件转换后的 css

以及生成 DOM 的启动脚本:

 
 
 
 
  1.   

WAWebview.js 文件中的各个模块(行号为 jsbeautify 之后代码行号,开发者工具版本:092300):

从页面 data 到 dom 的主要流程如下:

 
 
 
 
  1. var vtree 
  2. var rootNode 
  3.  
  4. document.addEventListener("generateFuncReady", function(e) { 
  5.   var generateFunc = e.detail.generateFunc; 
  6.   wx.onAppDataChange(function(obj) { 
  7.     // 合并 data 到现有 data 
  8.     DataStore.setData(obj.data) 
  9.     // 生成 virtual dom 的 javascript plain object 
  10.     var props = generateFunc(DataStore.getData()) 
  11.  
  12.     // ***次渲染 
  13.     if (obj.options.firstRender) { 
  14.       vtree = createVirtualTree(props, true) 
  15.       rootNode = vtree.render() 
  16.       rootNode.replaceDocumentElement(document.body) 
  17.       wx.initReady() 
  18.     } else { 
  19.       var other_vtree = createVirtualTree(props, false) 
  20.       var patches = vtree.diff(other_vtree) 
  21.       patches.apply(rootNode) 
  22.       vtree = other_vtree 
  23.       document.dispatchEvent(new CustomEvent("pageReRender", {})); 
  24.     } 
  25.   }) 
  26. })  

上面的 DataStore 对象提供合并和获取当前页面 data 对象的功能,其实现如下:

 
 
 
 
  1. var DataStore = (function() { 
  2.   var data = {} 
  3.   return { 
  4.     getData: function() { 
  5.       return data 
  6.     }, 
  7.     setData: function(e) { 
  8.       for (var t in e) { 
  9.         for (var n = (0, parsePath)(t), o = data, a = void 0, s = void 0, c = 0; c < n.length; c++) Number(n[c]) === n[c] && Number(n[c]) % 1 === 0 ? Array.isArray(o) || (a[s] = [], o = a[s]) : "[object Object]" !== Object.prototype.toString.call(o) && (a[s] = {}, o = a[s]), s = n[c], a = o, o = o[n[c]]; 
  10.         a && (a[s] = e[t]) 
  11.       } 
  12.     } 
  13.   } 
  14. })() 
  15.  
  16. // 解析 key 为 data 内对象的路径字符串 
  17. function parsePath(e) { 
  18.   for (var t = e.length, n = [], i = "", r = 0, o = !1, a = !1, s = 0; s < t; s++) { 
  19.     var c = e[s]; 
  20.     if ("\\" === c) s + 1 < t && ("." === e[s + 1] || "[" === e[s + 1] || "]" === e[s + 1]) ? (i += e[s + 1], s++) : i += "\\"; 
  21.     else if ("." === c) i && (n.push(i), i = ""); 
  22.     else if ("[" === c) { 
  23.       if (i && (n.push(i), i = ""), 0 === n.length) throw new Error("path can not start with []: " + e); 
  24.       a = !0, o = !1 
  25.     } else if ("]" === c) { 
  26.       if (!o) throw new Error("must have number in []: " + e); 
  27.       a = !1, n.push(r), r = 0 
  28.     } else if (a) { 
  29.       if (c < "0" || c > "9") throw new Error("only number 0-9 could inside []: " + e); 
  30.       o = !0, r = 10 * r + c.charCodeAt(0) - 48 
  31.     } else i += c 
  32.   } 
  33.   if (i && n.push(i), 0 === n.length) throw new Error("path can not be empty"); 
  34.   return n 

可以看到,每次 data 变化之后,小程序就会开始整个页面的 diff patch 过程。

对于原生实现的组件, exparser 会在监视到数据变化后发送对应事件到 WeixinJSBridge。

service 页面详解

service 页面会被被拼接为以下的样子:

 
 
 
 
  1.  
  2.  
  3.  
  4.    
  5.    
  6.    
  7.    
  8.    
  9.    
  10.    
  11.    
  12.    
  13.  
  14.  
  15.  
  16.    
  17.  
  18.  
  19.   

除了配置和开发者编写的页面、app.js,页面还在加载了 asdebug.js 和 WAService.js 两个文件。

asdebug.js 文件位于 nwjs 项目目录下,路径为app/dist/weapp/appservice/asdebug.js。 它包含了两个部分,一个是 WeixinJSBridge 针对 service 模块的实现,另一块是一些方便命令使用的接口, 例如:help() 会告诉你一些可用的函数:

该文件只会在开发者工具内被引入,如果小程序在微信内运行,应该会由微信底层提供 WeixinJSBridge。

WAService 负责 service 模块的一些核心逻辑,它包含以下部分 (行号为 jsbeautify 之后代码行号,开发者工具版本:092300):

现在的 WAService 还有有很多地方依赖 window 对象,所以很有可能它在微信中和开发者工具内一样,依然运行于 webview 标签之内。 


分享题目:微信小程序架构分析(中)
URL网址:http://cdbrznjsb.com/article/dhjdiig.html

其他资讯

让你的专属顾问为你服务