seajs中模块的解析规则详解和模块使用总结


Posted in Javascript onMarch 12, 2014

seajs github 模块标识已经说的相对清楚了。但并没有面面俱到,特别是当你需要手写 【模块ID】和【模块依赖】的时候,或者自己写自动化工具来做 transport 的时候(ps:spm貌似适应性不是很强也不易用,毕竟每个项目的目录结构可能相差很大,且不易改变。当然如果他的定位是包管理工具就别指望它来做你的项目的自动化构建工具了),ID的解析规则就需要了解透彻了。
注意事项:
1. 顶级标识始终相对 base 基础路径解析。
2. 绝对路径和根路径始终相对当前页面解析。
3. require 和 require.async 中的相对路径相对当前模块路径来解析。
4. seajs.use 中的相对路径始终相对当前页面来解析。

seajs中,模块的ID大致可分为三种:【相对标识】、【顶级标识】、【普通路径】,
普通路径包括 “绝对路径”、“根路径”,等。

这里重点说明 【相对标识】 和 【顶级标识】。
相对标识 是指 "./","../" 开头的,如:"./OtherModule", "../lib/Base"。
顶级标识 是指 以文件或目录(可以包含:字母、-、_)开头的,如:"app/widget/Select"

需要写模块ID的地方有三处:

define("id (1)",["../id2 (2)"], function(require, exports, module){
    var moduleA = require('./moduleA (3)');
})

注意:无论是define第一个参数【模块ID】还是第二个参数【依赖模块的ID】还是【require模块ID】,最终的比对标准是【解析后的文件URI】。
因此,这三处需要写ID 的地方可以以任意一种方式来写,只要最终解析为同一个URI,即被认为是同一个模块。
在解析ID的过程中,会预先经过 seajs.config 中定义的 alias 和 paths 的处理。

base 路径解析规则
(第 1 层,本身的路径不依赖于任何设置)
1. 不可使用【顶级标识】,因为顶级标识就是相对于 base 基础路径来解析的,因此 base 本身只能使用【相对标识】或【根路径】等。
2. base 默认路径为 seajs 的目录,其他情况参见seajs官网,如果不是seajs推荐的源码目录结构,尽量手动设置 base 路径。
3. 【相对标识】:相对于 当前页面 解析。
paths 中路径解析规则
(第 1 层,本身的路径不依赖于任何设置)
1. 【相对标识】:在哪里被引用,相对的解析位置视被引用的地方而定,遵循当地的规则。
2. paths中的字段会被以变量的方式在被使用的地方替换,然后再解析。
比如:

//代码块(1)
//path定义:
seajs.config({
    base:"./app/src",
    path:{
        "a":"../lib", //(1) 相对路径
        "lib":"path/to/lib", //(2) 顶级标识
        "l2":"/lib" //(3) 根路径
    }
});
//模块 mod/m/m.js: 
...
require("a/jquery");
//=> 转换为:"../../lib/jquery"
//=> 加载:mod/lib/jquery (特别注意 1)
...
//模块 mod/f.js:
...
require("a/jquery");
//=> 转换为:"../../lib/jquery"
//=> 加载:lib/jquery (特别注意 2)
...

alias 中路径解析规则
(第 2 层,本身的路径可以依赖于paths的设置)
1. alias 的规则类似于 paths,并且 alias 路径也可以使用 paths 中的“变量”
2. 提醒:paths、alias 中尽量使用【顶级标识】、【根路径】、【绝对路径】,不要使用【相对标识】,因为在不同深度的模块引用时会解析为不同的路径。
3. 【相对标识】:在哪里被引用,相对的解析位置视被引用的地方而定,遵循当地的规则。
seajs.use 路径解析规则
【相对标识】:相对于 当前页面 解析。
define 定义模块 ID 解析规则 (1)

(第 3 层,路径可以相对于 alias 或 paths 来设置)
可以使用:【相对标识】、【顶级标识】、【根路径】
推荐使用【顶级标识】,如果模块的位置不在 base 基础路径内,则使用【相对标识】或【根路径】。
【相对标识】:相对 当前页面 解析

// 代码块(2)
//config -- 还使用 [代码块 (1)]中的配置
// 模块1,无歧义,根路径解析
define("/app/src/module/Base", ..);
// 模块2,无歧义,顶级标识,相对于 base 基础路径来解析
define("app/src/module/Base", ..);
// 模块3,有歧义,相对标识,此处相对于 当前页面(引用到这个模块的html页面)
// 但其他地方即便使用 【表面上相同的“ID”】,也可能会被解析不同的模块
define("./app/src/module/Base",..);

模块依赖ID 解析规则 (2)

(第 3 层,路径可以相对于 alias 或 paths 来设置)
【相对标识】:相对 base 基础路径解析

//代码块(3)
//config -- 还使用 [代码块 (1)]中的配置
//无歧义,相对于根路径解析
define("..", ["/app/src/module/Base"], ..)
// 无歧义,顶级标识,相对于 base 基础路径解析
define("..", ["app/src/module/Base"], ..)
//有歧义,相对标识,此处相对于 当前模块 来解析
//此处的依赖看起来是依赖于【代码块(2)】中的 `模块3`
//但如果当前模块跟当前页面不在同一层目录下,就不会被解析为 `模块3`

define("..", ["./app/src/module/Base"],..)
模块内 require 其他模块的ID 解析规则 (3)
(第 3 层,路径可以相对于 alias 或 paths 来设置)
【相对标识】:相对 base 基础路径解析
//代码块(4)
//config -- 还使用 [代码块 (1)]中的配置
define("..", [..], function(require){
    //无歧义,相对于根路径解析
    require("/app/src/module/Base");
});
define("..", [..], function(require){
    // 无歧义,顶级标识,相对于 base 基础路径解析
    require("app/src/module/Base");
});
define("..", [..], function(require){
    //有歧义,相对标识,此处相对于 当前模块 来解析
    //此处的依赖看起来是依赖于【代码块(2)】中的 `模块3`
    //但如果当前模块跟当前页面不在同一层目录下,就不会被解析为 `模块3`
    require("./app/src/module/Base");
})

特别提醒:模块内三处需要写ID的地方,不需要使用看起来相同的字符串,只要被解析为相同的模块即可。

总结:
1.paths 和 alias 的设置仅仅相当于一个变量,在哪里使用,就在那里替换为设定的值,然后再解析。
2.尽可能的使用【顶级标识】。
3.如果不能使用【顶级标识】,比如目录跨越比较大等,则尽量设置 alias 或 paths 通过一个【非相对路径】 标识 定位到一个目录,然后在这个标识下,再定义ID。

Javascript 相关文章推荐
jQuery UI Autocomplete 体验分享
Feb 14 Javascript
Jquery在指定DIV加载HTML示例代码
Feb 17 Javascript
JavaScript返回当前会话cookie全部键值对照的方法
Apr 03 Javascript
JS实现带缓冲效果打开、关闭、移动一个层的方法
May 09 Javascript
javascript自定义in_array()函数实现方法
Aug 03 Javascript
node.js学习之base64编码解码
Oct 21 Javascript
利用jQuery.Validate异步验证用户名是否存在(推荐)
Dec 09 Javascript
详解Node.js项目APM监控之New Relic
May 12 Javascript
详解前端路由实现与react-router使用姿势
Aug 07 Javascript
JS实现的加减乘除四则运算计算器示例
Aug 09 Javascript
基于js中style.width与offsetWidth的区别(详解)
Nov 12 Javascript
微信小程序 wx:for遍历循环使用实例解析
Sep 09 Javascript
判断一个对象是否为jquery对象的方法
Mar 12 #Javascript
Jquery实现自定义窗口随意的拖拽
Mar 12 #Javascript
Jquery实现自定义弹窗示例
Mar 12 #Javascript
把jQuery的类、插件封装成seajs的模块的方法
Mar 12 #Javascript
使用js检测浏览器是否支持html5中的video标签的方法
Mar 12 #Javascript
利用Keydown事件阻止用户输入实现代码
Mar 11 #Javascript
JavaScript中奇葩的假值示例应用
Mar 11 #Javascript
You might like
咖啡豆的最常见发酵处理方法,详细了解一下
2021/03/03 冲泡冲煮
PHP读取数据库并按照中文名称进行排序实现代码
2013/01/29 PHP
PHP中把对象数组转换成普通数组的方法
2015/07/10 PHP
通过PHP自带的服务器来查看正则匹配结果的方法
2015/12/24 PHP
thinkphp中字符截取函数msubstr()用法分析
2016/01/09 PHP
PHP获取网页所有连接的方法(附demo源码下载)
2016/03/30 PHP
JavaScript 关键字屏蔽实现函数
2009/08/02 Javascript
JavaScript高级程序设计(第3版)学习笔记11 内建js对象
2012/10/11 Javascript
javascript 图片裁剪技巧解读
2012/11/15 Javascript
html超链接打开窗口大小的方法
2013/03/05 Javascript
Jquery选中或取消radio示例
2013/09/29 Javascript
jQuery实现区域打印功能代码详解
2016/06/17 Javascript
angular.js之路由的选择方法
2016/09/24 Javascript
jQuery tagsinput在h5邮件客户端中应用详解
2016/09/26 Javascript
AngularJS开发教程之控制器之间的通信方法分析
2016/12/25 Javascript
微信小程序 石头剪刀布实例代码
2017/01/04 Javascript
微信小程序实现带刻度尺滑块功能
2017/03/29 Javascript
使用Vue构建可重用的分页组件
2018/03/26 Javascript
JS实现移动端点击按钮复制文本内容
2019/07/28 Javascript
JS中的算法与数据结构之队列(Queue)实例详解
2019/08/20 Javascript
通过js实现压缩图片上传功能
2020/02/25 Javascript
解决idea开发遇到javascript动态添加html元素时中文乱码的问题
2020/09/29 Javascript
动态创建类实例代码
2009/10/07 Python
python批量修改图片尺寸,并保存指定路径的实现方法
2019/07/04 Python
基于多进程中APScheduler重复运行的解决方法
2019/07/22 Python
Python产生一个数值范围内的不重复的随机数的实现方法
2019/08/21 Python
Pandas之read_csv()读取文件跳过报错行的解决
2020/04/21 Python
Pycharm添加虚拟解释器报错问题解决方案
2020/10/13 Python
深入解读CSS3中transform变换模型的渲染
2016/05/27 HTML / CSS
AVI-8手表美国官方商店:AVI-8 USA
2019/04/10 全球购物
生物技术专业毕业生求职信范文
2013/12/14 职场文书
2014年营业员工作总结
2014/11/18 职场文书
幼师辞职信怎么写
2015/02/27 职场文书
2015年国庆节新闻稿
2015/07/18 职场文书
入团申请书格式
2019/06/20 职场文书
python关于集合的知识案例详解
2021/05/30 Python