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 相关文章推荐
JS图片浏览组件PhotoLook的公开属性方法介绍和进阶实例代码
Nov 09 Javascript
用Jquery实现滚动新闻
Feb 12 Javascript
javascript 寻找错误方法整理
Jun 15 Javascript
纯JavaScript代码实现移动设备绘图解锁
Oct 16 Javascript
Knockout自定义绑定创建方法
Dec 26 Javascript
JavaScript中获取纯正的undefined的方法
Mar 06 Javascript
js实现StringBuffer的简单实例
Sep 02 Javascript
vue刷新和tab切换实例
Feb 11 Javascript
详解vue2.0 不同屏幕适配及px与rem转换问题
Feb 23 Javascript
红黑树的插入详解及Javascript实现方法示例
Mar 26 Javascript
JS实现的图片选择顺序切换和循环切换功能示例【测试可用】
Dec 28 Javascript
JavaScript创建对象的四种常用模式实例分析
Jan 11 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
索尼SONY ICF-7600A(W)电路分析
2021/03/01 无线电
PHP中获取内网用户MAC地址(WINDOWS/linux)的实现代码
2011/08/11 PHP
CodeIgniter扩展核心类实例详解
2016/01/20 PHP
利用Laravel事件系统如何实现登录日志的记录详解
2017/05/20 PHP
安装PHP扩展时解压官方 tgz 文件后没有configure文件无法进行配置编译的问题
2020/08/26 PHP
Prototype Function对象 学习
2009/07/12 Javascript
javascript游戏开发之《三国志曹操传》零部件开发(一)让静态人物动起来
2013/01/23 Javascript
js如何获取兄弟、父类等节点
2014/01/06 Javascript
js面向对象之公有、私有、静态属性和方法详解
2015/04/17 Javascript
JQuery实现鼠标滚轮滑动到页面节点
2015/07/28 Javascript
基于Javascript实现返回顶部按钮
2016/02/29 Javascript
相册展示PhotoSwipe.js插件实现
2016/08/25 Javascript
JQuery统计input和textarea文字输入数量(代码分享)
2016/12/29 Javascript
Node.js读取文件内容示例
2017/03/07 Javascript
Angular2自定义分页组件
2017/04/19 Javascript
Bootstrap里的文件分别代表什么意思及其引用方法
2017/05/01 Javascript
js循环map 获取所有的key和value的实现代码(json)
2018/05/09 Javascript
用WebStorm进行Angularjs 2开发(环境篇:Windows 10,Angular-cli方式)
2018/12/05 Javascript
JavaScript适配器模式原理与用法实例详解
2020/03/09 Javascript
[02:28]DOTA2 2017国际邀请赛小组赛回顾
2017/08/09 DOTA
python正则表达式匹配[]中间为任意字符的实例
2018/12/25 Python
Python切片操作去除字符串首尾的空格
2019/04/22 Python
python启动应用程序和终止应用程序的方法
2019/06/28 Python
简单了解python的break、continue、pass
2019/07/08 Python
Python+Selenium+phantomjs实现网页模拟登录和截图功能(windows环境)
2019/12/11 Python
使用Django搭建网站实现商品分页功能
2020/05/22 Python
用纯CSS3实现网页中常见的小箭头
2017/10/16 HTML / CSS
Zooplus葡萄牙:欧洲领先的网上宠物商店
2018/07/01 全球购物
LINUX下线程,GDI类的解释
2012/04/17 面试题
外语专业毕业生自我评价分享
2013/10/05 职场文书
医学院校毕业生自荐信范文
2014/01/01 职场文书
赞美老师的演讲稿
2014/05/22 职场文书
县委常委班子对照检查材料思想汇报
2014/09/28 职场文书
部门群众路线教育实践活动对照检查材料思想汇报
2014/10/07 职场文书
单位个人查摆问题及整改措施
2014/10/28 职场文书
MongoDB连接数据库并创建数据等使用方法
2021/11/27 MongoDB