微信小程序 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 相关文章推荐
多广告投放代码 推荐
Nov 13 Javascript
Jquery ajax传递复杂参数给WebService的实现代码
Aug 08 Javascript
javascript和jquery修改a标签的href属性
Dec 16 Javascript
JS获取url链接字符串 location.href
Dec 23 Javascript
javascript比较两个日期相差天数的方法
Jul 24 Javascript
jquery解析json格式数据的方法(对象、字符串)
Nov 24 Javascript
jqGrid中文文档之选项设置
Dec 02 Javascript
jQuery设置Cookie及删除Cookie实例分析
Apr 15 Javascript
AngularJS入门教程之 XMLHttpRequest实例讲解
Jul 27 Javascript
完美实现js拖拽效果 return false用法详解
Jul 28 Javascript
vue element upload组件 file-list的动态绑定实现
Oct 11 Javascript
vue 实现特定条件下绑定事件
Nov 09 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
浅谈web上存漏洞及原理分析、防范方法(安全文件上存方法)
2013/06/29 PHP
PHP 之 写时复制介绍(Copy On Write)
2014/05/13 PHP
分享PHP-pcntl 实现多进程代码
2016/09/30 PHP
IE event.srcElement和FF event.target 功能比较
2010/03/01 Javascript
JavaScript具有类似Lambda表达式编程能力的代码(改进版)
2010/09/14 Javascript
ie下jquery.getJSON的缓存问题的处理方法
2013/03/29 Javascript
Js nodeType 属性全面解析
2013/11/14 Javascript
JQuery对表格进行操作的常用技巧总结
2014/04/23 Javascript
javascript中sort()的用法实例分析
2015/01/30 Javascript
javascript实现网页屏蔽Backspace事件,输入框不屏蔽
2015/07/21 Javascript
JavaScript学习笔记(三):JavaScript也有入口Main函数
2015/09/12 Javascript
Javascript复制实例详解
2016/01/28 Javascript
Bootstrap模块dropdown实现下拉框响应
2016/05/22 Javascript
js实现导航吸顶效果
2017/02/24 Javascript
在ABP框架中使用BootstrapTable组件的方法
2017/07/31 Javascript
详解react-native WebView 返回处理(非回调方法可解决)
2018/02/27 Javascript
jQuery的Ajax接收java返回数据方法
2018/08/11 jQuery
使用js获取身份证年龄的示例代码
2020/12/11 Javascript
python判断字符串是否纯数字的方法
2014/11/19 Python
python通过文件头判断文件类型
2015/10/30 Python
Python实现字典的遍历与排序功能示例
2017/12/23 Python
Pycharm无法显示动态图片的解决方法
2018/10/28 Python
在Python中,不用while和for循环遍历列表的实例
2019/02/20 Python
python 将字符串完成特定的向右移动方法
2019/06/11 Python
Python机器学习算法库scikit-learn学习之决策树实现方法详解
2019/07/04 Python
python 中xpath爬虫实例详解
2019/08/26 Python
Python日志:自定义输出字段 json格式输出方式
2020/04/27 Python
踩坑:pytorch中eval模式下结果远差于train模式介绍
2020/06/23 Python
python爬虫中url管理器去重操作实例
2020/11/30 Python
Giglio美国站:意大利奢侈品购物网
2018/02/10 全球购物
说一下mysql, oracle等常见数据库的分页实现方案
2012/09/29 面试题
写好求职信第一句话的技巧
2013/10/26 职场文书
医药营销个人求职信
2014/04/12 职场文书
高校教师个人工作总结2014
2014/12/17 职场文书
个人工作总结(管理人员)范文
2019/08/13 职场文书
vue报错function () { [native code] },无法出现我们想要的内容 Unknown custom element
2022/04/11 Vue.js