wframe不是控件库,也不是UI库,她是一个微信小程序面向对象编程框架,代码只有几百行。她的主要功能是规范小程序项目的文件结构、规范应用程序初始化、规范页面加载及授权管理的框架,当然,wframe也提供了一些封装好了的函数库,方便开发者调用。
wframe目前已实现的核心功能:
1. 应用程序初始化自动从服务器获取配置,ajax成功后触发ready事件;
2. 每个页面对象可以配置是否requireLogin属性,如果需要登录,则每个页面在进入ready方法之前会自动完成授权、获取用户信息、服务器端登录;
3. 完成ajax全局封装:如果用户已经登录,则会自动在http-header添加token信息,如果session过期则会重新进入登录流程;
本文的阅读对象:想要自己搭建小程序框架的人,相信本文会给你提供一些思路。
我们为什么要开发wframe?
我们开发的小程序越来越多,小程序也越来越复杂,于是我们就想将每个小程序重复在写的那一部分代码提出来,变成一个公共的函数库,一个跟每个项目的业务逻辑完全不相关的函数库。除了在新项目中可以节省代码之外,有一些复杂的代码逻辑由于提到了公共的函数库,我们将其优化得更优雅、更健壮。
说wframe是一个函数库虽说也可以,但wframe更像一个框架。我们通常把一些静态方法、静态对象、仅处理页面内容的JS文件集称作函数库,比如jQuery;我们通常把处理了应用程序和页面生命周期,以及使用了大量的面向对象编程技术的JS文件集称作框架。因此,wframe其实是一个框架。
重要说明:wframe框架用到了大量的面向对象编程知识,比如实例、继承、覆写、扩展、抽象方法等等,因此对开发人员,特别是项目中的架构师,的面向对象编程能力有较高要求。
项目源码已上传到GitHub并会持续更新:https://github.com/leotsai/wframe
一、wframe项目结构
wframe的最核心的职责就是规范项目文件结构。
为什么需要规范呢?因为我们小程序越来越多,如果每个小程序的文件结构都不一样的话,那定是一件很难受的事。另外,wframe由于其框架的身份,其本职工作就是定义一个最好的文件结构,这样基于wframe创建的所有小程序都将自动继承wframe的优秀品质。
1. _core文件夹
wframe框架源码,与业务毫不相干,每个小程序都可以直接将_core文件夹复制到项目中,而当wframe更新版本时,所有小程序可以直接覆盖_core完成升级。用下划线“_”开头的目的有2个:
(a) 将此文件夹置顶;
(b) 标记此文件夹是一个特殊文件夹,本框架中还有其他地方也会用到下划线开头为文件夹/文件。
2. _demo文件夹
业务核心文件夹,比如定义一些扩展wframe框架的类,同时这些类又被具体的业务类继承使用,比如ViewModelBase等。
3. pages文件夹
与微信小程序官方文档定义一致:放置页面的地方。
4. app.js
程序主入口,只不过基于wframe的小程序的app.js跟官方的长得很不一样,我们定义了一个自己的Applicaiton类,然后再new的一个Application实例。稍后详解。
5. mvcApp.js
几乎每个js文件都会require引入的一个文件,因为这相当于是项目的静态入口,其包含了所有的静态函数库,比如对wx下面方法的封装、Array类扩展、Date类扩展、网络请求(ajax)封装等等。mvcApp.js几乎只定义了一个入口,其内部的很多对象、方法都是通过require其他JS引入的。因此,大多数情况下,我们只需要require引入mvcApp.js就够了。
写到这里,分享一个我们的编程思想:入口要少。小程序里有哪些入口:this、getApp()、wx、mvcApp。其实也就是每一行代码点号“.”前面的都叫代码入口。
我们还有另一个编程规范(强制):每个文件不能超过100行代码。这就是要求每个程序员必须学会拆分,拆分也是我们的另一个编程思想。通过拆分,每个JS文件职责清晰,极大的提高了代码阅读率。
二、详解 1. app.js和Application类详解
app.js定义了程序入口。
1 var mvcApp = require('mvcApp.js'); 2 var Application = require('_core/Application.js'); 3 4 function MvcApplication() { 5 Application.call(this); 6 this.initUrl = 'https://www.somdomain.com/api/client-config/get?key=wx_applet_wframe'; 7 this.host = 'http://localhost:18007'; 8 this.confgis = { 9 host: 'http://localhost:18007', 10 cdn: 'https://images.local-dev.cdn.somedomain.com' 11 }; 12 this.mock = true; 13 this.accessToken = null; 14 this.useDefaultConfigsOnInitFailed = false; 15 }; 16 17 MvcApplication.prototype = new Application(); 18 19 MvcApplication.prototype.onInitialized = function (configs) { 20 if (configs != null && configs !== '') { 21 this.configs = JSON.parse(configs); 22 this.host = this.configs.host; 23 } 24 }; 25 26 App(new MvcApplication());