微信小程序开发入门及案例详解:模块化小程序逻辑层的 JavaScript 语言解析

2024-07-17
来源:网络整理

本文节选自华章出版社出版的《微信小程序:开发入门与案例详解》一书第 2 章 2.5 节,作者:李俊斌。更多章节内容请关注云栖社区“华章电脑”公众号查看。

2.5 模块化

小程序的逻辑层语言是 ,作为脚本语言,在设计初期仅仅是为了实现简单的页面交互,于1995年由Eich发明,发明时间不到十天,语言本身缺乏很多支持大型项目的设计。现在前端业务逻辑越来越复杂,代码越来越多,暴露出很多问题。模块化主要解决命名冲突和文件依赖两个问题,模块化现在在前端被广泛使用,比如、、、等,它们大多遵循或者接近规范,甚至ES6都提出了自己对模块化的规范。目前前端模块化还没有统一的解决方案,在不同环境、不同框架下的实现方式都不一样,本节将重点讲解小程序的模块化规范。

2.5.1 模块化简介

一开始,前端代码量不大,都放在一个文件中,比如下面的代码:

var name = 'weixin', age = 12; function getName() { // 实现代码 } function getAge() { // 实现代码 }

后来随着前端代码越来越多,为了管理和分工方便,我们不得不将代码拆分成多个文件。这时候,上述代码就被封装到 user.js 文件中,需要用到的时候再引入到页面中(或者打包成一个文件)。早期团队成员很少,一切运行正常。直到团队越来越大,开始有人抱怨:我要定义一个 name 变量,但是 user.js 中已经存在,所以我还要定义它;为什么在自己的代码中定义一个方法,别人的代码中就会出现问题?通过这种文件拆分工作,我们只是物理上将代码分离了,可以初步实现多人开发和简单的代码管理,但并没有真正隔离作用域。因为我们不知道其他文件中已经存在的变量名,甚至会让全局冲突问题更容易发生,更加严重。

后来为了避免这种全局冲突,我们决定参考Java的做法,引入命名空间和闭包来解决变量冲突问题。于是user.js中的代码就变成了这样:

( function() { myProject = myProject || {}; // 定义全局命名空间 myProject.user = {}; myProject.user.name = 'weixin'; var age = 12; // 闭包内变量,外部不能访问 myProjecct.user.getName = function() { // 实现代码 } myProject.user.getAge = function() { // 实现代码 } } )();

这样其他同事就可以通过.user、call和拿到name了,确实可以缓解大部分冲突,但为此我们要记住一长串的。同时,当我使用user空间的时候,别人就不能用了,不能完美解决问题。更要命的是,如果user.js依赖了另外一个.js,其他同事就必须通过阅读user.js源码来了解这一层依赖,并按顺序引入.js和user.js。直接引入user.js会导致他的代码出错,如果他还依赖了其他资源,就必须了解所有相关的依赖,而他只想调用我的方法,这对于调用的同事来说无疑是一场噩梦。这时候就需要一种新的组织方式,于是模块化诞生了:

模块是一段具有统一基本书写格式的代码。

模块之间可以互相引用,通过基本的交互规则协同工作。

目前模块化还没有统一的规范,大致可以分为ES6和ES7两种规范,有兴趣的可以在网上查阅相关资料,小程序的模块化机制比较贴近规范,无论采用哪种规范,都很容易学习。

2.5.2 文件范围

在小程序中,一个文件就是一个模块,在这个文件中声明的变量和函数只在这个文件中有效,不同文件中相同的变量名和函数名不会互相影响。模块中可以调用一些全局方法。以下示例中,通过调用()获取小程序实例:

App( { myGlobalData : { /* 定义全局属性 */ name : 'weixin' } } ); var myPrivatyData = "value1"; /* myPrivatyData只能在a.js中使用 */ var appData = getApp(); appData.myGlobalData.name += ' app'; var myPrivatyData = "value2"; /* myPrivatyData不会和a.js中同名变量冲突 */ var appData = getApp(); /* 当a.js在b.js前执行后,这里会输出"weixin app value2" */ console.log( appData.myGlobalData.name + ' ' + myPrivatyData );

2.5.3 模块的使用

模块接口的暴露和引入非常简单:

通过公开接口。

依赖关系通过(path)引入,其中path是要引入的模块文件的相对路径。

示例代码如下:

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() { /* 这里会打印出somebody run */ otherMod.run( 'somebody' ); /* 这里会打印出somebody walk */ otherMod.walk( 'somebody' ); } } );

需要注意的是:

它是对 . 的引用,随意改变模块中的引用可能会引发未知错误,因此我们建议开发者使用 . 来暴露模块接口,除非你已经清楚两者之间的关系。

小程序目前不支持直接导入,建议开发者在需要使用时将相关代码复制到小程序目录下。

通过模块化,我们可以实现代码的真正隔离,允许多人并行开发,降低大型项目的管理难度,大大促进了前端工程化。

2.5.4 其他 1.经营环境

微信小程序逻辑代码运行在三个端:iOS、开发者工具(用于调试)。这三个端是三个不同的解析引擎:

在 iOS 上,小程序代码在 中运行。

在,代码由X5内核进行解析。

在开发工具中,小程序的代码运行在nwjs(内核)中。

虽然三个终端的环境非常相似,但是至少目前对一些语法和特性的支持还是存在一些差异,在开发过程中应该尽量在三个终端上进行测试。

2. ES6 语法和 API 支持

在小程序中,开发者可以使用 ES6 语法进行编码。在 0.10 版本及以上版本的开发工具中,开发者的 ES6 代码会默认转换为三端均能良好支持的 ES5 代码,帮助开发者解决不同环境带来的开发问题。如果不使用 ES6 语法,开发者可以在项目设置中关闭该功能。

转换过程中需要注意的事项:

这种转换只会帮助开发者处理语法问题。新的 ES6 API,例如,需要开发者自己引入或者通过其他库来引入。

为了提高代码质量,开启ES6转换时默认开启严格模式,请参考“使用”。

分享