网站插入地图/关键词排名技巧
在上一章中介绍了一个前台开发框架的基础骨干架构,接下来在此基础上再详细说明一下主函数里面require的一些其他用法。
首先简单说明一下为什么要使用require:
1.页面引用的不同js组件之间如果存在依赖关系,一旦在引用顺序上发生错误,就会引发页面异常(即依赖注入的顺序错误);
2.页面渲染会被js加载阻塞(加载的js越多,阻塞的时间越久),表现为页面无法响应用户的操作(页面的样式渲染停止等等),影响用户体验。
然后来回顾一下主函数是如何使用require的:
/*** Created by 李庆 on 2016/10/6.*/
require.config({"shim":{"lib/angular":{"deps":["lib/jquery-3.1.1"],"exports":"angular"},"lib/angular-ui-router":{"deps":["lib/angular"]},"lib/jquery":{"exports":"$"}}
});require(["framework/framework"],function(framework){var injector = angular.bootstrap($("html"),[framework.name])
});
在主函数里使用了require.config函数,函数有一个对象参数(包括js的模块加载、require的路径定义等等),函数作用是对require的全局配置(当然也包括控制js的加载)。下面就来详细说明一下这个对象参数支持我们执行哪些配置。
1.shim(即上例中对象参数的唯一一个属性):加载不符合AMD规范的js, 在shim中可以同时定义多个不符合AMD规范的js的加载,定义格式如下(具体的代码例子可参考主函数):
{"不符合AMD规范的js文件路径":{"deps":["依赖js文件路径"],//可以同时依赖多个js,因此这里deps是一个数组"exports":"js外部调用名称"}
}
当这样定义以后,就不用再担心js在使用的时候发生依赖项未加载而导致页面显示异常的错误了,当使用一个js时,require会自动帮我们先把它的依赖项加载进来。
2.paths:使用自定义名称来定义js的加载路径,可以改造一下主函数的require.config来看paths是如何使用的,代码如下:
/*** Created by 李庆 on 2016/10/6.*/
require.config({"paths":{"angular":"lib/angular","jquery":"lib/jquery-3.1.1","angular-ui-router":"lib/angular-ui-router"},"shim":{"angular":{"deps":["jquery"],"exports":"angular"},"angular-ui-router":{"deps":["angular"]},"jquery":{"exports":"$"}}
});require(["framework/framework"],function(framework){var injector = angular.bootstrap($("html"),[framework.name])
});
上面的例子中,为lib/angular定义的名称为angular,为lib/jquery-3.1.1定义的名称为jquery,为lib/angular-ui-router定义的名称为angular-ui-router,这样在shim中定义文件路径就可以使用为各个路径定义的自定义名称而不再需要使用真实的路径了,这样做的好处是当一个js的文件路径很深且又被多次引用时,可以保持代码的简洁清爽。
不过当我们按上面的代码修改了main.js后,会发现原来可以正常访问的界面挂了:
错误消息(查看frameworkConfig.js的39行)提示我们module未定义,即我们定义的框架module依赖的angular-ui-router未能正常引用。看到这里估计大部分人都会这么想:就定义个js的加载路径就把页面搞死了?搞什么飞机?不要方,其实问题原因很简单:在require.config中定义的信息是全局的,这意味着应用中所有引用angular、jquery和angular-ui-router的地方都需要调整(当然,在实际的web开发过程中一般不会有先码完代码然后变更了一个全局配置导致所有代码都需要排查调整的情况)。下面贴一下需要变更的部分:
framework.js的define部分:
define(["angular","angular-ui-router","framework/config/frameworkConfig","framework/controller/frameworkCtrl"],function(angular,router,frameworkConfig,frameworkCtrl){
frameworkConfig.js的define部分:
define(["angular","angular-ui-router"],function(angular,router){var serviceConfigs = ["$stateProvider","$urlRouterProvider","$controllerProvider",
可以看到使用了paths的自定义名称后define部分减少了很多冗余代码。
3.baseUrl:使用自定义名称来定义应用基础路径,同样可以改造一下主函数的require.config来看baseUrl是如何使用的,代码如下:
/*** Created by 李庆 on 2016/10/6.*/
require.config({"baseUrl":"lib","paths":{"angular":"angular","jquery":"jquery-3.1.1","angular-ui-router":"angular-ui-router"},"shim":{"angular":{"deps":["jquery"],"exports":"angular"},"angular-ui-router":{"deps":["angular"]},"jquery":{"exports":"$"}}
});require(["framework/framework"],function(framework){var injector = angular.bootstrap($("html"),[framework.name])
});
上面的例子中,定义了baseUrl为lib,这样我们在定义paths的时候对应的js的加载路径可以直接从baseUrl定义的目录开始算,而不用重复写js加载路径的相同部分了。
注意:在实际的应用开发中,这个baseUrl通常为web目录(而不是像上例中为lib),用于区分前后台代码(通常前台代码目录为web,后台代码目录为src,定义了baseUrl后避免引用到后台代码)。
同样,按上面的代码修改了main.js后,会发现原来可以正常访问的界面又挂了(为什么要说又呢?):
console部分:
network部分:
可以看到错误原因是framework.js突然引不到了。问题原因也很简单:baseUrl同样是全局的,所有的请求资源路径都会加上baseUrl,从console部分请求的资源路径就可以看到多加了一层lib目录,这样显然是无法请求到framework.js,下面贴一下需要变更的部分:
main.js:
require(["../framework/framework"],function(framework){
framework.js:
define(["angular","angular-ui-router","../framework/config/frameworkConfig","../framework/controller/frameworkCtrl"],function(angular,router,frameworkConfig,frameworkCtrl){
即需要从lib目录的上一层目录开始获取资源,避免baseUrl对引用非lib目录下文件造成的影响,当然,实际的开发过程中,baseUrl会对应web目录,也就不会有这个问题。