New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

前端模块化开发的价值 #547

Closed
lifesinger opened this Issue Feb 18, 2013 · 66 comments

Comments

Projects
None yet
@lifesinger
Member

lifesinger commented Feb 18, 2013

本文发表在《程序员》杂志 2013 年 3 月刊,推荐购买。


前端模块化开发的价值

随着互联网的飞速发展,前端开发越来越复杂。本文将从实际项目中遇到的问题出发,讲述模块化能解决哪些问题,以及如何使用 Sea.js 进行前端的模块化开发。

恼人的命名冲突

我们从一个简单的习惯出发。我做项目时,常常会将一些通用的、底层的功能抽象出来,独立成一个个函数,比如

function each(arr) {
  // 实现代码
}

function log(str) {
  // 实现代码
}

并像模像样地把这些函数统一放在 util.js 里。需要用到时,引入该文件就行。这一切工作得很好,同事也很感激我提供了这么便利的工具包。

直到团队越来越大,开始有人抱怨。

小杨:我想定义一个 each 方法遍历对象,但页头的 util.js 里已经定义了一个,我的只能叫 eachObject 了,好无奈。

小高:我自定义了一个 log 方法,为什么小明写的代码就出问题了呢?谁来帮帮我。

抱怨越来越多。团队经过一番激烈的讨论,决定参照 Java 的方式,引入命名空间来解决。于是 util.js 里的代码变成了

var org = {};
org.CoolSite = {};
org.CoolSite.Utils = {};

org.CoolSite.Utils.each = function (arr) {
  // 实现代码
};

org.CoolSite.Utils.log = function (str) {
  // 实现代码
};

不要认为上面的代码是为了写这篇文章而故意捏造的。将命名空间的概念在前端中发扬光大,首推 Yahoo! 的 YUI2 项目。下面是一段真实代码,来自 Yahoo! 的一个开源项目。

if (org.cometd.Utils.isString(response)) {
  return org.cometd.JSON.fromJSON(response);
}
if (org.cometd.Utils.isArray(response)) {
  return response;
}

通过命名空间,的确能极大缓解冲突。但每每看到上面的代码,都忍不住充满同情。为了调用一个简单的方法,需要记住如此长的命名空间,这增加了记忆负担,同时剥夺了不少编码的乐趣。

作为前端业界的标杆,YUI 团队下定决心解决这一问题。在 YUI3 项目中,引入了一种新的命名空间机制。

YUI().use('node', function (Y) {
  // Node 模块已加载好
  // 下面可以通过 Y 来调用
  var foo = Y.one('#foo');
});

YUI3 通过沙箱机制,很好的解决了命名空间过长的问题。然而,也带来了新问题。

YUI().use('a', 'b', function (Y) {
  Y.foo();
  // foo 方法究竟是模块 a 还是 b 提供的?
  // 如果模块 a 和 b 都提供 foo 方法,如何避免冲突?
});

看似简单的命名冲突,实际解决起来并不简单。如何更优雅地解决?我们按下暂且不表,先来看另一个常见问题。

烦琐的文件依赖

继续上面的故事。基于 util.js,我开始开发 UI 层通用组件,这样项目组同事就不用重复造轮子了。

其中有一个最被大家喜欢的组件是 dialog.js,使用方式很简单。

<script src="util.js"></script>
<script src="dialog.js"></script>
<script>
  org.CoolSite.Dialog.init({ /* 传入配置 */ });
</script>

可是无论我怎么写文档,以及多么郑重地发邮件宣告,时不时总会有同事来询问为什么 dialog.js 有问题。通过一番排查,发现导致错误的原因经常是

<script src="dialog.js"></script>
<script>
  org.CoolSite.Dialog.init({ /* 传入配置 */ });
</script>

在 dialog.js 前没有引入 util.js,因此 dialog.js 无法正常工作。同样不要以为我上面的故事是虚构的,在我待过的公司里,至今依旧有类似的脚本报错,特别是在各种快速制作的营销页面中。

上面的文件依赖还在可控范围内。当项目越来越复杂,众多文件之间的依赖经常会让人抓狂。下面这些问题,我相信每天都在真实地发生着。

  1. 通用组更新了前端基础类库,却很难推动全站升级。
  2. 业务组想用某个新的通用组件,但发现无法简单通过几行代码搞定。
  3. 一个老产品要上新功能,最后评估只能基于老的类库继续开发。
  4. 公司整合业务,某两个产品线要合并。结果发现前端代码冲突。
  5. ……

以上很多问题都是因为文件依赖没有很好的管理起来。在前端页面里,大部分脚本的依赖目前依旧是通过人肉的方式保证。当团队比较小时,这不会有什么问题。当团队越来越大,公司业务越来越复杂后,依赖问题如果不解决,就会成为大问题。

文件的依赖,目前在绝大部分类库框架里,比如国外的 YUI3 框架、国内的 KISSY 等类库,目前是通过配置的方式来解决。

YUI.add('my-module', function (Y) {
  // ...
}, '0.0.1', {
    requires: ['node', 'event']
});

上面的代码,通过 requires 等方式来指定当前模块的依赖。这很大程度上可以解决依赖问题,但不够优雅。当模块很多,依赖很复杂时,烦琐的配置会带来不少隐患。

命名冲突和文件依赖,是前端开发过程中的两个经典问题。下来我们看如何通过模块化开发来解决。为了方便描述,我们使用 Sea.js 来作为模块化开发框架。

使用 Sea.js 来解决

Sea.js 是一个成熟的开源项目,核心目标是给前端开发提供简单、极致的模块化开发体验。这里不多做介绍,有兴趣的可以访问 seajs.org 查看官方文档。

使用 Sea.js,在书写文件时,需要遵守 CMD (Common Module Definition)模块定义规范。一个文件就是一个模块。前面例子中的 util.js 变成

define(function(require, exports) {
  exports.each = function (arr) {
    // 实现代码
  };

  exports.log = function (str) {
    // 实现代码
  };
});

通过 exports 就可以向外提供接口。这样,dialog.js 的代码变成

define(function(require, exports) {
  var util = require('./util.js');

  exports.init = function() {
    // 实现代码
  };
});

关键部分到了!我们通过 require('./util.js') 就可以拿到 util.js 中通过 exports 暴露的接口。这里的 require 可以认为是 Sea.js 给 JavaScript 语言增加的一个 语法关键字,通过 require 可以获取其他模块提供的接口。

这其实一点也不神奇。作为前端工程师,对 CSS 代码一定也不陌生。

@import url("base.css");

#id { ... }
.class { ... }

Sea.js 增加的 require 语法关键字,就如 CSS 文件中的 @import 一样,给我们的源码赋予了依赖引入功能。

如果你是后端开发工程师,更不会陌生。Java、Python、C# 等等语言,都有 includeimport 等功能。JavaScript 语言本身也有类似功能,但目前还处于草案阶段,需要等到 ES6 标准得到主流浏览器支持后才能使用。

这样,在页面中使用 dialog.js 将变得非常简单。

<script src="sea.js"></script>
<script>
seajs.use('dialog', function(Dialog) {
  Dialog.init(/* 传入配置 */);
});
</script>

首先要在页面中引入 sea.js 文件,这一般通过页头全局把控,也方便更新维护。想在页面中使用某个组件时,只要通过 seajs.use 方法调用。

好好琢磨以上代码,我相信你已经看到了 Sea.js 带来的两大好处:

  1. 通过 exports 暴露接口。这意味着不需要命名空间了,更不需要全局变量。这是一种彻底的命名冲突解决方案。
  2. 通过 require 引入依赖。这可以让依赖内置,开发者只需关心当前模块的依赖,其他事情 Sea.js 都会自动处理好。对模块开发者来说,这是一种很好的 关注度分离,能让程序员更多地享受编码的乐趣。

小结

除了解决命名冲突和依赖管理,使用 Sea.js 进行模块化开发还可以带来很多好处:

  1. 模块的版本管理。通过别名等配置,配合构建工具,可以比较轻松地实现模块的版本管理。
  2. 提高可维护性。模块化可以让每个文件的职责单一,非常有利于代码的维护。Sea.js 还提供了 nocache、debug 等插件,拥有在线调试等功能,能比较明显地提升效率。
  3. 前端性能优化。Sea.js 通过异步加载模块,这对页面性能非常有益。Sea.js 还提供了 combo、flush 等插件,配合服务端,可以很好地对页面性能进行调优。
  4. 跨环境共享模块。CMD 模块定义规范与 Node.js 的模块规范非常相近。通过 Sea.js 的 Node.js 版本,可以很方便实现模块的跨服务器和浏览器共享。

模块化开发并不是新鲜事物,但在 Web 领域,前端开发是新生岗位,一直处于比较原始的刀耕火种时代。直到最近两三年,随着 Dojo、YUI3、Node.js 等社区的推广和流行,前端的模块化开发理念才逐步深入人心。

前端的模块化构建可分为两大类。一类是以 Dojo、YUI3、国内的 KISSY 等类库为代表的大教堂模式。在大教堂模式下,所有组件都是颗粒化、模块化的,各组件之间层层分级、环环相扣。另一类是以 jQuery、RequireJS、国内的 Sea.js、OzJS 等类库为基础的集市模式。在集市模式下,所有组件彼此独立、职责单一,各组件通过组合松耦合在一起,协同完成开发。

这两类模块化构建方式各有应用场景。从长远来看,小而美更具备宽容性和竞争力,更能形成有活力的生态圈。

总之,模块化能给前端开发带来很多好处。如果你还没有尝试,不妨从试用 Sea.js 开始。

(完)
特别感谢这篇文章: http://chaoskeh.com/blog/why-seajs.html
参考了部分内容。


2013-04-23

补充一篇很不错的入门文档:一步步学会使用 Sea.js 2.0

@lifesinger lifesinger closed this Feb 18, 2013

@freestyle21

This comment has been minimized.

Show comment
Hide comment
@freestyle21

freestyle21 Mar 5, 2013

就说吧,怎么越读越熟=-=。。。用过一段时间,吸引的不止是seajs,是玉伯的代码风格,哈哈~~对怎么实现异步的不太了解,看源码没有看懂,,一个require太神奇了。

freestyle21 commented Mar 5, 2013

就说吧,怎么越读越熟=-=。。。用过一段时间,吸引的不止是seajs,是玉伯的代码风格,哈哈~~对怎么实现异步的不太了解,看源码没有看懂,,一个require太神奇了。

@xiongsongsong

This comment has been minimized.

Show comment
Hide comment
@xiongsongsong

xiongsongsong Mar 5, 2013

曾经参与了seaJS有奖征文,写的非常幼稚,但细读,和这个issue还是有共通的地方:#292

xiongsongsong commented Mar 5, 2013

曾经参与了seaJS有奖征文,写的非常幼稚,但细读,和这个issue还是有共通的地方:#292

@ghostcode

This comment has been minimized.

Show comment
Hide comment
@ghostcode

ghostcode Jul 3, 2013

开始学习,项目要用到了!体验模块化的编程。

ghostcode commented Jul 3, 2013

开始学习,项目要用到了!体验模块化的编程。

@xiongsongsong

This comment has been minimized.

Show comment
Hide comment
@xiongsongsong

xiongsongsong Jul 4, 2013

还有另外一个好处:不用考虑命名空间了!

降低了学习和理解的难度。

xiongsongsong commented Jul 4, 2013

还有另外一个好处:不用考虑命名空间了!

降低了学习和理解的难度。

@motouzhixin

This comment has been minimized.

Show comment
Hide comment
@motouzhixin

motouzhixin Jul 9, 2013

当然,js的到良好的管理和充分利用!

------------------ 原始邮件 ------------------
发件人: "xiongsongsong"notifications@github.com;
发送时间: 2013年7月4日(星期四) 中午11:37
收件人: "seajs/seajs"seajs@noreply.github.com;
抄送: "魔鬼的泪与血"1114910233@qq.com;
主题: Re: [seajs] 前端模块化开发的价值 (#547)

还有另外一个好处:不用考虑命名空间了!

降低了学习和理解的难度。


Reply to this email directly or view it on GitHub.

motouzhixin commented Jul 9, 2013

当然,js的到良好的管理和充分利用!

------------------ 原始邮件 ------------------
发件人: "xiongsongsong"notifications@github.com;
发送时间: 2013年7月4日(星期四) 中午11:37
收件人: "seajs/seajs"seajs@noreply.github.com;
抄送: "魔鬼的泪与血"1114910233@qq.com;
主题: Re: [seajs] 前端模块化开发的价值 (#547)

还有另外一个好处:不用考虑命名空间了!

降低了学习和理解的难度。


Reply to this email directly or view it on GitHub.

@lip2up

This comment has been minimized.

Show comment
Hide comment
@lip2up

lip2up Jul 22, 2013

不错,我们的项目一直在用,越来越觉得好用。

lip2up commented Jul 22, 2013

不错,我们的项目一直在用,越来越觉得好用。

@panxuepeng

This comment has been minimized.

Show comment
Hide comment

panxuepeng commented Aug 13, 2013

@greatming

This comment has been minimized.

Show comment
Hide comment
@greatming

greatming Sep 3, 2013

我也要开始学习了

greatming commented Sep 3, 2013

我也要开始学习了

@greatming

This comment has been minimized.

Show comment
Hide comment
@greatming

greatming Sep 3, 2013

我也要开始学习了,
问个问题,项目中只需要seajs就可以了吗,不需要别的了吧

greatming commented Sep 3, 2013

我也要开始学习了,
问个问题,项目中只需要seajs就可以了吗,不需要别的了吧

@afc163

This comment has been minimized.

Show comment
Hide comment
@afc163

afc163 Sep 3, 2013

Member

@greatming

seajs 只是模块加载器,不负责任何具体的业务。你还需要模块。

Member

afc163 commented Sep 3, 2013

@greatming

seajs 只是模块加载器,不负责任何具体的业务。你还需要模块。

@jabez128

This comment has been minimized.

Show comment
Hide comment
@jabez128

jabez128 Oct 8, 2013

很好的文章,长知识了

jabez128 commented Oct 8, 2013

很好的文章,长知识了

@tedyhy

This comment has been minimized.

Show comment
Hide comment
@tedyhy

tedyhy Nov 13, 2013

写的很好,涨姿势了。。。

tedyhy commented Nov 13, 2013

写的很好,涨姿势了。。。

@hotoo

This comment has been minimized.

Show comment
Hide comment
@hotoo

hotoo Nov 13, 2013

Member

@lifesinger 用 Issues 写文档,有一些问题,这里探讨下:

  1. 不利于文档本身的管理,和普通的问题 Issues 混杂在一起,不好找。
  2. 没有版本管理,多个版本只能分散在不同的未知 Issues 中。不好找。
  3. 文档总体来说不需要讨论和回复。如果文档有问题,可以提 Issues 或 Fork & Pull Request。现在受无意义回复骚扰太多。

Issues 没有收藏功能,又分散各处,没有版本控制,用作文档挺不合适的。
建议文档跟源码放一起。

Member

hotoo commented Nov 13, 2013

@lifesinger 用 Issues 写文档,有一些问题,这里探讨下:

  1. 不利于文档本身的管理,和普通的问题 Issues 混杂在一起,不好找。
  2. 没有版本管理,多个版本只能分散在不同的未知 Issues 中。不好找。
  3. 文档总体来说不需要讨论和回复。如果文档有问题,可以提 Issues 或 Fork & Pull Request。现在受无意义回复骚扰太多。

Issues 没有收藏功能,又分散各处,没有版本控制,用作文档挺不合适的。
建议文档跟源码放一起。

@jiyinyiyong

This comment has been minimized.

Show comment
Hide comment
@jiyinyiyong

jiyinyiyong Nov 13, 2013

@hotoo +1
另外 Issue API 可以把 Markdown 内容拉出来的, 还有点用 http://jiyinyiyong.github.io/seajs-issues/

jiyinyiyong commented Nov 13, 2013

@hotoo +1
另外 Issue API 可以把 Markdown 内容拉出来的, 还有点用 http://jiyinyiyong.github.io/seajs-issues/

@kaizhuQin

This comment has been minimized.

Show comment
Hide comment
@kaizhuQin

kaizhuQin Nov 17, 2013

涨姿势了,写得很好。。。

kaizhuQin commented Nov 17, 2013

涨姿势了,写得很好。。。

@eilvein

This comment has been minimized.

Show comment
Hide comment
@eilvein

eilvein Nov 29, 2013

项目使用中

eilvein commented Nov 29, 2013

项目使用中

@xiaojiong

This comment has been minimized.

Show comment
Hide comment
@xiaojiong

xiaojiong Dec 16, 2013

不错,新项目移植中....

xiaojiong commented Dec 16, 2013

不错,新项目移植中....

@markyun

This comment has been minimized.

Show comment
Hide comment
@markyun

markyun Jan 10, 2014

mark一下。

markyun commented Jan 10, 2014

mark一下。

@destinyd

This comment has been minimized.

Show comment
Hide comment
@destinyd

destinyd commented Feb 16, 2014

mark

@ivanthing

This comment has been minimized.

Show comment
Hide comment
@ivanthing

ivanthing Feb 24, 2014

涨姿势了.。。。学习中!

ivanthing commented Feb 24, 2014

涨姿势了.。。。学习中!

@Troland

This comment has been minimized.

Show comment
Hide comment
@Troland

Troland Mar 6, 2014

目前用了reuirejs感觉不明白的就是一些模块的监听等等。

Troland commented Mar 6, 2014

目前用了reuirejs感觉不明白的就是一些模块的监听等等。

@hehongwei44

This comment has been minimized.

Show comment
Hide comment
@hehongwei44

hehongwei44 Mar 18, 2014

非常有价值的项目

hehongwei44 commented Mar 18, 2014

非常有价值的项目

@iyangyuan

This comment has been minimized.

Show comment
Hide comment
@iyangyuan

iyangyuan Apr 22, 2014

哇,这和Node.js有啥联系呢,感觉太像了!
还有就是关于路径的处理,比如,根目录表示什么路径?能否介绍一下呢?

iyangyuan commented Apr 22, 2014

哇,这和Node.js有啥联系呢,感觉太像了!
还有就是关于路径的处理,比如,根目录表示什么路径?能否介绍一下呢?

@diamont1001

This comment has been minimized.

Show comment
Hide comment
@diamont1001

diamont1001 Jun 16, 2014

谢谢,入门前看看这篇文章会有很大的帮助

diamont1001 commented Jun 16, 2014

谢谢,入门前看看这篇文章会有很大的帮助

@yeguangss

This comment has been minimized.

Show comment
Hide comment
@yeguangss

yeguangss commented Jun 20, 2014

Mark

@lquanyang

This comment has been minimized.

Show comment
Hide comment
@lquanyang

lquanyang commented Jun 30, 2014

fock

@niweicumt

This comment has been minimized.

Show comment
Hide comment
@niweicumt

niweicumt Jul 2, 2014

好文,学习ing

niweicumt commented Jul 2, 2014

好文,学习ing

@code-artisan

This comment has been minimized.

Show comment
Hide comment
@code-artisan

code-artisan commented Jul 10, 2014

mark

@ql9075

This comment has been minimized.

Show comment
Hide comment
@ql9075

ql9075 Aug 19, 2014

移植工作是个麻烦事,比如jquery里面已经定义好的类$.fn.class,需要放到模块中来。就必须重新改造。
exports.class( this , fn ),之类的。调用方式也不一样了。对于之前已做好的项目来改造,真有点无力...

ql9075 commented Aug 19, 2014

移植工作是个麻烦事,比如jquery里面已经定义好的类$.fn.class,需要放到模块中来。就必须重新改造。
exports.class( this , fn ),之类的。调用方式也不一样了。对于之前已做好的项目来改造,真有点无力...

@RockyRen

This comment has been minimized.

Show comment
Hide comment
@RockyRen

RockyRen Aug 26, 2014

还没试过模块化的前端编程,就从sea.js开始试试吧

RockyRen commented Aug 26, 2014

还没试过模块化的前端编程,就从sea.js开始试试吧

@Natumsol

This comment has been minimized.

Show comment
Hide comment
@Natumsol

Natumsol Aug 30, 2014

很好的入门教程学习了

Natumsol commented Aug 30, 2014

很好的入门教程学习了

@iLoosen

This comment has been minimized.

Show comment
Hide comment
@iLoosen

iLoosen Sep 10, 2014

很通俗~

iLoosen commented Sep 10, 2014

很通俗~

@ofmyice

This comment has been minimized.

Show comment
Hide comment
@ofmyice

ofmyice commented Jan 29, 2015

mark

@tennessine

This comment has been minimized.

Show comment
Hide comment
@tennessine

tennessine Mar 7, 2015

到此一游

tennessine commented Mar 7, 2015

到此一游

@northdrift

This comment has been minimized.

Show comment
Hide comment
@northdrift

northdrift Apr 1, 2015

学习了,推荐的文章也很不错,很适合我这种刚接触前端自动化的!

northdrift commented Apr 1, 2015

学习了,推荐的文章也很不错,很适合我这种刚接触前端自动化的!

@front-thinking

This comment has been minimized.

Show comment
Hide comment
@front-thinking

front-thinking Apr 9, 2015

没理解CMD与AMD、CMD与CMJ的区别

front-thinking commented Apr 9, 2015

没理解CMD与AMD、CMD与CMJ的区别

@Natumsol

This comment has been minimized.

Show comment
Hide comment
@Natumsol

Natumsol Apr 20, 2015

@front-thinking 伟哥也在这里!

Natumsol commented Apr 20, 2015

@front-thinking 伟哥也在这里!

@front-thinking

This comment has been minimized.

Show comment
Hide comment
@front-thinking

front-thinking Apr 20, 2015

是的 紧跟萌神的步伐 @Natumsol

front-thinking commented Apr 20, 2015

是的 紧跟萌神的步伐 @Natumsol

@1994

This comment has been minimized.

Show comment
Hide comment
@1994

1994 May 18, 2015

入门文档搬家了....

1994 commented May 18, 2015

入门文档搬家了....

@xuanxia

This comment has been minimized.

Show comment
Hide comment
@xuanxia

xuanxia May 25, 2015

赞一个,开始学习了

xuanxia commented May 25, 2015

赞一个,开始学习了

@ahcometrue

This comment has been minimized.

Show comment
Hide comment
@ahcometrue

ahcometrue Jun 5, 2015

今早在博客园看到的,感觉很cool

ahcometrue commented Jun 5, 2015

今早在博客园看到的,感觉很cool

@blackcater

This comment has been minimized.

Show comment
Hide comment
@blackcater

blackcater Jun 20, 2015

不错~ 作为菜鸟的我,感觉有懂了许多

blackcater commented Jun 20, 2015

不错~ 作为菜鸟的我,感觉有懂了许多

@hogaFarming

This comment has been minimized.

Show comment
Hide comment
@hogaFarming

hogaFarming commented Jun 27, 2015

学习了

@ylygithub

This comment has been minimized.

Show comment
Hide comment
@ylygithub

ylygithub Aug 7, 2015

开始学习sea ~

ylygithub commented Aug 7, 2015

开始学习sea ~

@1215904405a

This comment has been minimized.

Show comment
Hide comment
@1215904405a

1215904405a Aug 23, 2015

其实就是手动加载js文件和统一变量命名

1215904405a commented Aug 23, 2015

其实就是手动加载js文件和统一变量命名

@cdll

This comment has been minimized.

Show comment
Hide comment
@cdll

cdll Aug 25, 2015

为何木有shim机制?不是很明白~

cdll commented Aug 25, 2015

为何木有shim机制?不是很明白~

@kookpua

This comment has been minimized.

Show comment
Hide comment
@kookpua

kookpua commented Oct 12, 2015

learn!

@YAMAPM

This comment has been minimized.

Show comment
Hide comment
@YAMAPM

YAMAPM Oct 24, 2015

YUI().use('node', function (Y) {
// Node 模块已加载好
// 下面可以通过 Y 来调用
var foo = Y.one('#foo');
});
这段代码 是不是Y.node('#foo')啊

YAMAPM commented Oct 24, 2015

YUI().use('node', function (Y) {
// Node 模块已加载好
// 下面可以通过 Y 来调用
var foo = Y.one('#foo');
});
这段代码 是不是Y.node('#foo')啊

@ruofeng086

This comment has been minimized.

Show comment
Hide comment
@ruofeng086

ruofeng086 Nov 2, 2015

像上面的例子里说的,a.js 里面 require('b.js'),在模板中可以调用a.js中的方法,那b.js的方法怎么去调用呢?

a.js

define(function(require, exports) {

var seajs = require('hello-Seajs.js');

exports.init = function() {
alert('init:ok');
};

});

b.js

define(function(require, exports) {

exports.each = function (arr) {
alert("each:ok");
};

exports.log = function (str) {
alert("log:ok");
};

});

模板

seajs.use("init",function(seajs){
seajs.log("e");
});

ruofeng086 commented Nov 2, 2015

像上面的例子里说的,a.js 里面 require('b.js'),在模板中可以调用a.js中的方法,那b.js的方法怎么去调用呢?

a.js

define(function(require, exports) {

var seajs = require('hello-Seajs.js');

exports.init = function() {
alert('init:ok');
};

});

b.js

define(function(require, exports) {

exports.each = function (arr) {
alert("each:ok");
};

exports.log = function (str) {
alert("log:ok");
};

});

模板

seajs.use("init",function(seajs){
seajs.log("e");
});

@XiaodongTong

This comment has been minimized.

Show comment
Hide comment
@XiaodongTong

XiaodongTong commented Dec 17, 2015

Mark

@lihuacn

This comment has been minimized.

Show comment
Hide comment
@lihuacn

lihuacn Dec 17, 2015

很好的入门

lihuacn commented Dec 17, 2015

很好的入门

@freedomdebug

This comment has been minimized.

Show comment
Hide comment
@freedomdebug

freedomdebug Jan 19, 2016

从微信的页面过来期待做的越来越好

freedomdebug commented Jan 19, 2016

从微信的页面过来期待做的越来越好

@liubin595338764

This comment has been minimized.

Show comment
Hide comment
@liubin595338764

liubin595338764 Feb 4, 2016

一步步学会使用 Sea.js 2.0 链接已经失效了

liubin595338764 commented Feb 4, 2016

一步步学会使用 Sea.js 2.0 链接已经失效了

@xinbingliang

This comment has been minimized.

Show comment
Hide comment
@xinbingliang

xinbingliang Apr 6, 2016

来水一脚

xinbingliang commented Apr 6, 2016

来水一脚

@playwolf719

This comment has been minimized.

Show comment
Hide comment
@playwolf719

playwolf719 Jul 22, 2016

请问,avalon和seajs我结合使用,但用到avalon的另一个组件ajax组件时,老是报null,https://github.com/RubyLouvre/mmRequest
mmRequest应该怎么结合avalon和seajs一起使用?

playwolf719 commented Jul 22, 2016

请问,avalon和seajs我结合使用,但用到avalon的另一个组件ajax组件时,老是报null,https://github.com/RubyLouvre/mmRequest
mmRequest应该怎么结合avalon和seajs一起使用?

@ckx321

This comment has been minimized.

Show comment
Hide comment
@ckx321

ckx321 Sep 29, 2016

非常好,学习了,感谢。

ckx321 commented Sep 29, 2016

非常好,学习了,感谢。

@ccbbhh

This comment has been minimized.

Show comment
Hide comment
@ccbbhh

ccbbhh commented Oct 21, 2016

thanks

@GuoChen-WHU

This comment has been minimized.

Show comment
Hide comment
@GuoChen-WHU

GuoChen-WHU commented Nov 30, 2016

学习了

@deepdatatop

This comment has been minimized.

Show comment
Hide comment
@deepdatatop

deepdatatop commented Dec 16, 2016

hard work!

@starof

This comment has been minimized.

Show comment
Hide comment
@starof

starof May 3, 2017

现在用什么来做模块化

starof commented May 3, 2017

现在用什么来做模块化

@alxtz

This comment has been minimized.

Show comment
Hide comment
@alxtz

alxtz May 16, 2017

現在JS模組化好像使用webpack比較多,很火紅

alxtz commented May 16, 2017

現在JS模組化好像使用webpack比較多,很火紅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment