微信小程序学习之路——模块化
模块化简介
最早前端JavaScript代码量不大,统一放在一个文件夹内,如下面一段代码:
[code]var name ='weixin', age=12; function getName(){ //实现代码 } function getAge(){ //实现代码 }
后来前端代码越来越多,为了便于管理和工作拆分,我们不得不把代码拆分为多个文件,这时将上述代码封装到user.js文件中,需要用时引入页面(或打包到一个文件)就行。初期团队成员少,一切都运行正常,直到团队越来越大,开始有人抱怨:我想定义一name变量但user.js中已经存在,我不得不定义为myName;为什么我在自己代码中定了getAge方法就导致别人代码出问题了呢?通过这种文件拆分的工作我们只是对代码做了物理上的分离,能初步实现多人开发和简单的代码管理,但并没有真正做到作用域的隔离,由于不知道其他文件内已存在的变量名,甚至让全局冲突问题变得更容易、更严重。
再后来为了避免这种全局冲突,大家决定参考Java的方式,引入命名空间和闭包来解决变量冲突问题。于是user.js里的代码变成了如下这样:
[code]Page({ function(){ myProject = myProject || {};//定义全局命名空间 myProject.user ={}; myProject.user.name='weixin'; var age=12;//闭包内变量,外部不能访问 myProject.user.getName = function(){ //实现代码 } myProject.user.getAge = function(){ //实现代码 } } });
这样别的同事可以通过myProject.user获取name,调用getName和getAge方法,通过命名空间,的确能缓解大部分冲突,但是为此我们不得不记住很长一串命名空间,同时当我使用user这个空间后,别人就不能使用,这也不能完美地解决问题。同时更可怕的是如果user.js依赖另外一个utils.js,别的同事必须通过阅读user.js源码搞懂这层依赖关系,按顺序引入utils.js、user.js,直接引入user.js将会导致他代码出错,如果utils还依赖别的资源他还得必须搞懂相关的所有依赖,而他仅仅是想调用我的getName方法,这对调用的同事来说无疑是个噩梦。这时我们需要一种新的组织方式,于是诞生了模块化:
- 模块是一段JavaScript代码,具有统一的基本书写格式。
- 模块之间通过基本交互规则,能彼此引用,协同工作。
目前模块化的规范不统一,大致可分为CommonJS和ES6两种规范,大家有兴趣可以参考网上相关资料,小程序模块化机制比较接近CommonJS规范,无论哪种规范,学习起来都十分简单。
文件作用域
小程序中一个JavaScript文件就是一个模块,在中国文件中声明的变量和函数只在该文件中有效,不同文件中的相同变量名和函数名是不会相互影响的。模块中可以调用一些全局的方法,如下例中通过调用getApp()获取小程序实例:
[code]App({ myGlobalData:{ /**定义全局属性 */ name:'weixin' } }); var myPrivateData ="value1";/**myPrivateData只能在a.js中使用 */ var appData = getApp(); appData.myGlobalData.name+='app'; var myPrivateData= "value2";/**myPrivateData不会和a.js中同名变量冲突 */ var appData = getApp(); /**当a.js在b.js前执行后,这里会输出"weixin app value2" */ cnsole.log(appData.myGlobalData.name+" "+myPrivateData);
模块的使用
模块接口的暴露和引入十分简单:
- 通过exports暴露接口
- 通过require(path)引入依赖,path是需要引入的模块文件的相对路径
实例代码如下:
[code]var privateData = 'weixin'; function run(who){ console.log(who+'run'); } function walk(who){ console.log(who+'walk'); } module.exports.run=run; exports.walk = walk; /** * 也可以如下写法: * module.exports={ * run:run, * walk:walk * }; */ var otherMod = require('mod.js'); Page({ onShow:function(){ /**这里会打印出sombody run */ otherMod.run('somebody'); /**这里会打印出sombody walk */ otherMod.walk('somebody'); } });
需要注意的是:
- exports是module.exports的一个引用,因此在模块里面随意更改exports的只想会造成未知错误。所以我们更推荐开发者采用module.exports来暴露模块接口,触发你已经很清晰的知道这两者的关系
- 小程序目前不支持直接引入node_modules,开发者需要使用node_modules时建议拷贝相关代码到小程序目录中
通过模块化我们能实现代码真正的隔离,可以多人并行开发,降低大项目管理难度,对前端工程化具有很大促进作用。
其他
1.JavaScript运行环境
微信小程序逻辑代码运行在三端:iOS、Android和用于调试的开发者工具,这三端是各自不同的三个解析引擎:
- 在iOS上,小程序的JavaScript代码是运行在JavaScriptCore中。
- 在Android上,小程序的JavaScript代码是通过X5内核来解析。
- 在开发工具上,小程序的JavaScript代码是运行在nwjs(chrome内核)中。
虽然尽管三端的环境十分相似,但是至少在目前对一些语法、特性的支持还是有一些区别,在开发过程中要尽可能地在三端进行测试。
2.ES6语法以及API支持
在小程序中,开发者可以使用ES6语法进行编码,在0.10.101000以及之后版本的开发工具中,会默认使用babel将开发者ES6代码转换为三端都能很好支持的ES5的代码,帮助开发者解决环境不同所带来的开发问题。如果没有使用ES6语法,开发者可以在项目设置中关闭这个功能。
转化过程中需要注意:
- 这种转换只会帮助开发者处理语法上问题,新的ES6的API,例如Promise等需要开发者自行引入Polyfill或者别的类库。
- 为了提高代码质量,在开启ES6转换功能的情况下,默认启用JavaScript严格模式,请参考“use strict”。
- 微信小程序学习笔记(七)模块化
- 微信小程序学习之路(二) ------ 组件
- 微信小程序学习之路——API界面(一)
- 微信小程序学习之路——API获取二维码
- 微信小程序学习之路《六》 生命周期
- 微信小程序学习笔记 (小程序页面学习 四 逻辑层 模块化 基础食用方法)
- 微信小程序学习之路04-简易的计算器
- 【微信小程序学习之路】----使用globalData函数设置全局变量
- 微信小程序学习之路 在html中绑定点击事件
- 微信小程序学习之路01-初识微信小程序
- 微信小程序学习笔记——模板和模块化
- 微信小程序学习之路 扫一扫
- 微信小程序学习之路——API界面(二)
- 微信小程序学习之路——Flex布局
- 微信小程序学习之路——API文件
- 微信小程序学习之路——API数据缓存
- 微信小程序学习之路——API位置
- 微信小程序开发小白学习之路--事件
- 微信小程序学习之路——API用户信息
- 微信小程序学习之路——媒体组件(二)