本文只是seajs的入门贴。要详细了解,请看GitHub主页上的相关链接,精彩不断,精选几篇:

前端模块化开发的价值

前端模块化开发的历史

ID和路径匹配原则

与RequireJS的异同

模块的加载启动

下面本文开始:

seajs的价值

原生javascript的一个弱项,就是不支持模块化,说白了就是没有其他语言的import,include等语句。所以开发者就只有2个选择:把所有的东西写到一起,或者通过全局变量来交互

这至少造成以下几个问题:

1、污染全局变量,容易发生命名空间冲突,难以维护

2、无法按需加载

由于javascript官方迟迟未能解决这些问题,所以就有民间的社区提出标准,希望能自行解决,弥补语言的不足。主要有2种规范,一种是 CommonJS提出的CMD规范,另一种是AMD规范,server端的node就是CMD的一种实现,seajs实现的也是CMD规范。所以熟悉 node的用户会发现,seajs的API和node的API非常类似,这就是因为它们是同一种规范的不同实现

关于seajs的价值,这篇帖子说得更加详细:why seajs

seajs的例子

官网上的5分钟入门例子也很简单,不过本文再简化一点,用一个更简单的例子进行说明:

目录结构简化后是这样的:

helloworld.html:

  1. <!doctype html>
  2. <html>
  3. <head>
  4.     <meta charset="utf-8">
  5.     <title>Hello Sea.js</title>
  6. </head>
  7. <body>
  8. <div id="thediv">
  9.     <p>hello world</p>
  10. </div>
  11. <script src="../javascript/sea.js"></script>
  12. <script>
  13.     seajs.config({
  14.         alias: {
  15.             "jquery": "jquery-debug.js"
  16.         }
  17.     });
  18.     seajs.use("../javascript/main");
  19. </script>
  20. </body>
  21. </html>

首先用<script>标签引入了seajs,并且要放在第一行。然后这行代码是入口:

  1. seajs.use("../javascript/main");

加载seajs以后,会引进一个唯一的全局变量seajs,这是无法避免的,除非是一次性执行的匿名函数,否则单全局变量模式已经是最好的结果。然后seajs上有一个use方法,是启动其他模块的入口方法,这里就是启动了main.jsmain.js

  1. define(function (require, exports, module) {
  2.     var module1 = require("./module1");
  3.     alert(module1.add(1, 2));
  4. })

实际上use()和require()方法非常类似,不过官方推荐的最佳实践是,只把use()作为启动的入口方法,后续的模块导入都用require()来完成熟悉node的用户会觉得非常眼熟,define方法是seajs自己的实现方式,require,exports,module都是CMD规范的 设计,所以跟在node里是一样的。所有的seajs module,都应该写在define方法的factory function里

上面这段代码就引入了另一个模块module1,然后调用了其上的一个方法

module1.js

  1. define(function (require, exports, module) {
  2.     exports.add = function (a, b) {
  3.         return a + b;
  4.     }
  5.     var $ = require("jquery");
  6.     $("#thediv").click(function () {
  7.         alert("on click");
  8.     });
  9. })

这里又看到了熟悉的exports,导出了add()函数,并引用了jQuery框架,给DOM元素绑定了一个事件这里有一点要注意,就是对jQuery进行了CMD改造(也就是导出了变量$),这里有个小坑,后面会说

factory function有3个参数,分别是require,exports,module,作用跟node里是完全一样的。但是还有另外一种写法:

  1. define(function () {
  2.     return {sayHello: function () {
  3.         alert("hi there");
  4.     }};
  5. });

这个factory function没有任何参数,直接返回了导出的对象。这个叫做return语法,不过我用得比较少seajs的例子就到此为止了,确实非常易用

与node module的比较

基本上是一致的,包括exports和module.exports的表现,还有require后立刻执行的行为,还有require的结果也同样会被cache起来

集成jQuery的一个坑

我下载了官网的例子,然后只是稍微移动了文件的路径,结果发现这行代码:
  1. var $ = require("jquery");

$的值一直是null,百思不得其解。在官方的GitHub issue上,这个问题也有广泛的讨论。本质的原因在于seajs有一个路径和ID匹配的原则:著名的#930

seajs的设计思想是,路径即ID。一般在调用define()方法时,如果只传递一个factory function,那么这个模块就是个匿名模块;或者传递define(module_id, dependency, factory),这个模块就是个具名模块
如果一个文件就是一个模块,那么匿名模块就可以了。但是在生产环境中,往往会把多个模块放到一个文件里,但是路径只有一个,如何知道要加载哪个 模块呢?这时候就需要给其中一个模块赋予module_id,和path保持一致,seajs就知道应该加载这个ID和path匹配的模块了
如果具名模块的id和require的path参数不匹配,就会返回null,这就是我出现这个错误的原因:
  1. var $ = require("jquery-debug");// path是"jquery-debug"

而jquery中的代码:

  1. define("jquery/jquery/1.10.1/jquery-debug", [], function () { return jQuery; } );// module_id是"jquery/jquery/1.10.1/jquery-debug"

我移动了文件路径以后,path和module_id匹配不上,所以就失败了

把jQuery中的代码改成:
  1. define("jquery-debug.js",[],function(){return jQuery});

或者

  1. define(function(){return jQuery});

就行了,但是对于不熟悉#930的用户来说,这确实是不大不小的一个坑

Sea.js入门的更多相关文章

  1. sea.js 入门

    上个月学了 require.js 现在顺便来学学 sea.js. 对比下这两种的区别,看自己喜欢哪个,就在接下来的项目中去使用它吧. seajs中的所有 JavaScript 模块都遵循 CMD 模块 ...

  2. Sea.Js使用入门

    1.Sea.Js是什么 seajs相对于RequireJs与LabJS就比较年轻,2010年玉伯发起了这个开源项目,SeaJS遵循CMD规范,与RequireJS类似,同样做为模块加载器.示例 // ...

  3. sea.js 个人入门

    玉伯 : http://seajs.org/docs/ 说这两个JS 必须提到AMD.commonjs两种不同的规范: 奇舞团:http://www.75team.com/archives/882 知 ...

  4. 深入学习sea.js

    入门学习了文档之后,在深入学习里面的一些有趣的知识点 =================================== 一.配置 seajs.config({ alias:( a3:'./js/ ...

  5. sea.js模块化编程

    * 为什么要模块化? 解决文件依赖 解决命名冲突 ; var var2 = 2; function fn1(){ } function fn2(){ } return { fn1: fn1, fn2: ...

  6. 1. web前端开发分享-css,js入门篇

    关注前端这么多年,没有大的成就,就入门期间积累了不少技巧与心得,跟大家分享一下,不一定都适合每个人,毕竟人与人的教育背景与成长环境心理活动都有差别,但就别人的心得再结合自己的特点,然后探索适合自己的学 ...

  7. 解决sea.js引用jQuery提示$ is not a function的问题

    在使用sea.js的如下写法引用jQuery文件时, //main.jsdefine(function(require,exports,module){ var $ = require('jquery ...

  8. React.js入门笔记

    # React.js入门笔记 核心提示 这是本人学习react.js的第一篇入门笔记,估计也会是该系列涵盖内容最多的笔记,主要内容来自英文官方文档的快速上手部分和阮一峰博客教程.当然,还有我自己尝试的 ...

  9. Ember.js入门教程、博文汇总

    第一章 对象模型 Ember.js 入门指南——类的定义.初始化.继承 Ember.js 入门指南——类的扩展(reopen) Ember.js 入门指南——计算属性(compute properti ...

随机推荐

  1. php 实现多线程

    通过php的Socket方式实现php程序的多线程.php本身是不支持多线程的,那么如何在php中实现多线程呢?可以想一下,WEB服务器本身都是支持多线程的.每一个访问者,当访问WEB页面的时候,都将 ...

  2. Spring中Quartz调度器的使用

    一.Quartz的特点 * 按作业类的继承方式来分,主要有以下两种: 1.作业类继承org.springframework.scheduling.quartz.QuartzJobBean类的方式 2. ...

  3. 对phpcms中{L('news')}的讲解

    直切话题 对于phpcms分M,C,A,那么现在要讲解的L是跟着M走的,每个M在languages中都有一个.lang.php文件,如Mcontent,就有一个content.lang.php,找到对 ...

  4. ASP.NET MVC4学习笔记之Controller的激活

    一. 高层相关类说明 当路由系统根据请求Url收集路由信息后,下一步就要将路由信息传给Controller激活系统,Controller激活系统负责实现了IController接口的Controlle ...

  5. 部署到iis后,发现无法加载运行CSS文件

    解决方法: 打开或关闭window功能中的Internet信息服务里的万维网服务=>常见HTTP功能=>静态内容

  6. 使用WIF实现单点登录Part III —— 正式实战

    我们接下来的demo将包括以下的工程: SiteA —— 基于.net framework 4.5的MVC 4程序,使用WIF 4.5的SDK,第一个RP SiteB —— 基于.net framew ...

  7. Java 第二天

    1.不带访问修饰符号的类成员变量默认是friendly(可以同一个包中访问) 2.protected的类成员可以在同一个包及其子类中访问 3.方法中可以定义内部类(如下面的代码),该类只能访问方法中的 ...

  8. DMA直接内存存取20160525

    说一下工作中接触到的DMA1)在实现DMA传输时,是由DMA控制器直接掌管总线,因此,存在着一个总线控制权转移问题.即DMA传输前,CPU要把 总线控制权交给DMA控制器,而在结束DMA传输后,DMA ...

  9. Python学习教程(learning Python)--2.1 Python下自定义函数

    在Python里可以自定义函数,实现某特定功能,这里首先要区分一下函数的定义和函数的调用两个基本概念,初学者往往容易混淆. 函数的定义是指将一堆能实现特定功能的语句用一个函数名标识起来,而函数的调用则 ...

  10. Java 逻辑运算符、位运算符、移位操作符 总结(Java 学习中的小记录)

    Java 逻辑运算符.位运算符.移位操作符  总结     作者:王可利(Star·星星) 逻辑运算符,表格如下: 解析逻辑运算符表: 1.与 (&) 特点:两个都为真的时候,结果为真.两个为 ...