微信小程序 require机制详解及实例代码


Posted in Javascript onDecember 14, 2016

微信小程序 require机制详解

一, JS模块加载:一次性加载全部JS, 但并不一定立即执行.

先提一提微信小程序架构: 类浏览器 -> HTTP本地服务 -> 云端服务

微信小程序运行的架构,基本上是浏览器 -> HTTP本地服务 -> 云端服务, HTTP本地服务用来读取本地文件或者代理云端的文件资源。读取项目中JS文件, 是由HTTP本地服务取本地存储的脚本文件.

似乎比较简单,一个HTML 引用所有JS文件

既然采用了这种架构,那微信小程序就类似浏览器那样,借助一个HTML页面来引用加载所有的JS文件。(注:这同NODE.JS的方式区别)

在小程序开发开具的HTTP服务部分代码,可以看到这个服务干了这件事情:

微信小程序包目录下面所有.js文件, 会按<script src="../xxx.js"> 方式插入生成一个HTML文件,然后类似浏览器方式加载.

让HTTP本地服务配合,对JS文件作的包装手法

可是事情并未结束,这种方式一加载,所有js文件都会立即执行,乱糟糟生成一团,怎么可能..那require函数又拿来干什么呢?原来这儿,HTTP服务在返回.JS文件内容的,给脚本内容包装上了一层: define函数

代理服务部分代码:

(projectManager.js)
function getScripts(projInfo, callback) {
 ...
  fs.readFile(fname, 'utf8', function(err, scripts) {
    ....  
    scripts = 'define("' + moduleName + '", function(require, module, exports, ' + noBrowserStr +
    '){ ' + scripts + '\n});',
    needRequire && (scripts += 'require("' + moduleName + '")'), //page页面js文件,会添加上require自己,加载后立即初始化。
    .....
    callback(null, scripts) //scripts串内容作为HTTP GET的返回

define函数非常简单,大致如下:

......
  var 
  ......
  moduleList = {}; 
  define = function(moduleName, factory) { //define是全局函数,每个JS文件都默认会调用. 
    moduleList[moduleName] = { status: status1, factory: factory }
  };

从上面代码看出,,这样一来,每加载一个JS文件,只是将其文件名与脚本内容串加入了内存中的一个变量保存,并未执行。 注意,这就与普通的HTML 脚本引用加载立即执行完全不同了.

接下来,就轮到微信小程序的require函数出场了。

二, JS模块初始化:按需递归式require初始化

先看看微信小程序require函数的定义:

....
  require = function(moduleName) {    
    ....
    var module = moduleList[moduleName]; //define函数调用时为moduleList赋的值
    .....
    if (module.status === status1) { 
      //如果未初始化,则初始化
      var factory = module.factory, //这个factory就是这个JS文件的脚本.
      obj = { exports: {} }, u = void 0;
      factory && (u = factory(o(moduleName), obj, obj.exports)), module.exports = obj.exports || u, module.status = status2
    }
    return module.exports
  }

从上面可以看出, require函数只是通过模块名,从内存中获取脚本内容执行,并置标志以保证只执行一次.

再精简一下:

require --调用-> factory --->模块中可能再require另一个模块...

这样就是一个典型的递归结构。

三,补充一下:页面js 其实也是被require函数加载

所谓页面JS,,就是在app.json中注册的page的js, 它们并没有被其它JS require方式引用,

那么它们在什么时候初始化?

回到之前本地代理服务器的代码,留意下面一点:

代理服务部分代码:
(projectManager.js)
function getScripts(projInfo, callback) {
 ...
  fs.readFile(fname, 'utf8', function(err, scripts) {
    ....  
    //page页面js文件,needRequire值为TRUE,会添加上require自己
    needRequire && (scripts += 'require("' + moduleName + '")'), 
    .....

原来它们还是使用require函数初始化,而且是加载后立即执行。

目前通常微信小程序代码结构不会太复杂,但随着产品的发展,需求的增加, 代码结构可能越来越复杂,越来越注意模块化.同时,如何将旧有JS模块在微信小程序中重用,这也是个重要话题。 所以深入理解微信小程序的JS模块化机制也是很有价值的.

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!

Javascript 相关文章推荐
浏览器脚本兼容 文本框中,回车键触发事件的兼容
Jun 21 Javascript
文本框输入时 实现自动提示(像百度、google一样)
Apr 05 Javascript
15条JavaScript最佳实践小结
Aug 09 Javascript
JavaScript 命名空间 使用介绍
Aug 29 Javascript
详解JavaScript编程中正则表达式的使用
Oct 25 Javascript
jquery mobile界面数据刷新的实现方法
May 28 Javascript
JS解决IOS中拍照图片预览旋转90度BUG的问题
Sep 13 Javascript
jquery实现左右轮播图效果
Sep 28 jQuery
vue-cli 构建骨架屏的方法示例
Nov 08 Javascript
javascript实现摄像头拍照预览
Sep 30 Javascript
JS实现移动端可折叠导航菜单(现代都市风)
Jul 07 Javascript
vue通过接口直接下载java生成好的Excel表格案例
Oct 26 Javascript
js实现获取鼠标当前的位置
Dec 14 #Javascript
详解vue.js组件化开发实践
Dec 14 #Javascript
JavaScript Ajax实现异步通信
Dec 14 #Javascript
微信小程序 配置文件详细介绍
Dec 14 #Javascript
微信小程序 闭包写法详细介绍
Dec 14 #Javascript
微信小程序 wx.uploadFile无法上传解决办法
Dec 14 #Javascript
bootstrap日历插件datetimepicker使用方法
Dec 14 #Javascript
You might like
php中的MVC模式运用技巧
2007/05/03 PHP
php实时倒计时功能实现方法详解
2017/02/27 PHP
Extjs学习笔记之七 布局
2010/01/08 Javascript
从零开始学习jQuery (六) jquery中的AJAX使用
2011/02/23 Javascript
jquery $.getJSON()跨域请求
2011/12/21 Javascript
对于Form表单reset方法的新认识
2014/03/05 Javascript
jQuery中element选择器用法实例
2014/12/29 Javascript
ros::spin() 和 ros::spinOnce()函数的区别及详解
2016/10/01 Javascript
微信小程序 视图容器组件的详解及实例代码
2017/01/19 Javascript
js使用i18n实现页面国际化的方法
2017/05/09 Javascript
安装vue-cli报错 -4058 的解决方法
2017/10/19 Javascript
js中比较两个对象是否相同的方法示例
2019/09/02 Javascript
解决layui富文本编辑器图片上传无法回显的问题
2019/09/18 Javascript
[33:28]完美世界DOTA2联赛PWL S3 PXG vs GXR 第三场 12.19
2020/12/24 DOTA
Pyramid Mako模板引入helper对象的步骤方法
2013/11/27 Python
使用python获取CPU和内存信息的思路与实现(linux系统)
2014/01/03 Python
windows 下python+numpy安装实用教程
2017/12/23 Python
对python实时得到鼠标位置的示例讲解
2018/10/14 Python
Python3 Tkinkter + SQLite实现登录和注册界面
2019/11/19 Python
解决Python列表字符不区分大小写的问题
2019/12/19 Python
在python3中实现查找数组中最接近与某值的元素操作
2020/02/29 Python
Django用数据库表反向生成models类知识点详解
2020/03/25 Python
Python内置方法和属性应用:反射和单例(推荐)
2020/06/19 Python
python 制作python包,封装成可用模块教程
2020/07/13 Python
零基础学Python之前需要学c语言吗
2020/07/21 Python
DeinDesign德国:设计自己的手机壳
2019/12/14 全球购物
《三袋麦子》教学反思
2014/03/02 职场文书
银行办公室岗位职责
2014/03/10 职场文书
民族团结先进集体事迹材料
2014/05/22 职场文书
大学生党员自我批评思想汇报
2014/10/10 职场文书
首都博物馆观后感
2015/06/05 职场文书
白银帝国观后感
2015/06/17 职场文书
干货:我将这样书写我的演讲稿!
2019/05/09 职场文书
应届毕业生的自我评价
2019/06/21 职场文书
Oracle 触发器trigger使用案例
2022/02/24 Oracle
Ubuntu安装Mysql+启用远程连接的完整过程
2022/06/21 Servers