SeaJS在AIFISH前端框架中的使用详解

Posted 麒麟敏捷社区

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SeaJS在AIFISH前端框架中的使用详解相关的知识,希望对你有一定的参考价值。

SeaJS在AIFISH前端框架中的使用详解

背景描述

在软件开发过程中,模块化编程思想已经习以为常了,模块化编程不仅仅给开发团队带来效率方面上的好处,还能够让开发的项目或者产品维护成本大大降低。

那么,在WEB开发过程中JS脚本语言已经不可或缺了,通过JS脚本语言能够带来更加舒适的人机交互和用户体验。但是,JS脚本的使用过程中也会有出现引用依赖的混乱,那么JS脚本语言的模块化思想势必会得到大家广泛的认可,在这样的一个背景下,AIFISH框架采用了由现蚂蚁金服前端工程师玉伯带来的成熟的模块化加载js框架——seajs

SeaJS简介

Seajs,一个Web模块加载框架,追求简单、自然的代码书写和组织方式,Sea.js 遵循 CMD 规范,模块化JS代码。依赖的自动加载、配置的简洁清晰,可以让程序员更多地专注编码。

优点:

1. 提高可维护性。

2.模块化编程。

3.动态加载,前端性能优化

这里不得不提一下AMDCMD规范:

异步模块定义(AMD)是AsynchronousModule Definition的缩写,是 RequireJS 在推广过程中对模块定义的规范化产出。

通用模块定义(CMD)是Common ModuleDefinition的缩写,是SeaJS 在推广过程中对模块定义的规范化产出。

RequireJS SeaJS 都是模块化框架的代表,AMDCMD,是他们各自定义模块化的方式,大同小异,主要是代码风格和API不同。

SeaJS使用

SeaJS环境中的javascript的写法—模块化

模块化?何为模块化?在seaJS中的所有javascript都必须要依据模块化的书写格式。这又是什么意思?其实,seaJS在管理文件的过程中是根据javascript(这里我们先讨论seaJSjavascript的管理)的文件名进行管理的,这个文件名就相当于我们平时所说的命名空间。在调用文件的时候我们可以直接写文件名而不需要写它的后缀。但是也是有特殊情况的:

a.加载css的时候一定要加后缀的

b.路径中有的时候javascript文件的后缀不能省略

c.路径中是以"#"号结尾的文件也不可以省去后缀

到底如何模块化一个javascript?这个时候就要用到我们seaJS提供的几个接口了,模块化使用define函数,如下:

define(id,deps,factory)

id:模块id,可以自己赋值,如果不赋值默认就是该函数的相对路径,各位可以调试看看;

deps:当前模块所依赖的模块,这里关键就是按需加载了,将你需要的js文件引入;

factory:模块工厂函数,这个函数是重点,主要是模块的逻辑实现。

模块化案例

在前端开发领域,一个模块,可以是JS 模块,也可以是 CSS 模块,或是 Template 等模块。在 Sea.js 里,我们专注于 JS 模块(其他类型的模块可以转换为 JS 模块):

1.模块是一段 JavaScript 代码,具有统一的基本书写格式。

2.模块之间通过基本交互规则,能彼此引用,协同工作。

AIFISH前端框架中每个js文件都是一个模块,在文件开头有如下定义:

SeaJS在AIFISH前端框架中的使用详解

factory 为函数时,表示是模块的构造方法。执行该构造方法,可以得到模块向外提供的接口。factory 方法在执行时,默认会传入三个参数:requireexports 和 module

SeaJS在AIFISH前端框架中的使用详解

当前模块对外提供的接口。传给 factory 构造方法的 exports 参数是 module.exports 对象的一个引用。只通过 exports 参数来提供接口,有时无法满足开发者的所有需求。 比如当模块的接口是某个类的实例时,需要通过 module.exports来实现。

SeaJS在AIFISH前端框架中的使用详解

require 是一个方法,接受模块标识作为唯一参数,用来获取其他模块提供的接口。之后就可以在当前js模块引用utils模块的方法了。

SeaJS踩坑全记录

seajs的模块定义方式非常simple,主要的难点在于不同项目有不同的部署要求,因此因为模块标识理解不够在AIFISH前端开发框架选型初期造成各种坑。下面详细分析下模块标识和加载机制!

模块标识
  • 模块标识命名规则

1、一个模块标识由斜线(/)分隔的多项组成。

2、每一项必须是小驼峰字符串、 .  .. 

3、模块标识可以不包含文件后缀名,比如 .js 

4、模块标识可以是 相对  顶级 标识。如果第一项是 .  ..,则该模块标识是相对标识。

解释一下其中的几种概念:

1、相对路径,以 ..开头。

2、顶级路径,不以. ..及斜线(/)开头。

3、普通路径,除相对和顶级路径外的,比如/(根路径)开头的,"http://""https://"    "file:///" 等协议标识开头的。

4.模块命名空间是seajs所在文件的根路径即所谓的base路径,去除了seajs/x.y.z 字串,   也可以指定seajs.config({base:});

SeaJS在AIFISH前端框架中的使用详解

  • 模块依赖提取过程如何解析

1、只提取相对标识。

2、相对标识相对 require 所在模块的标识来解析。

  • 上线后模块标识解析规则

1、顶级标识始终相对 base 基础路径解析。(顶级标识由字符串开头)。

3、模块定义中require  require.async 的相对路径相对当前模块路径来解析。

如果我们能理解其模块标识解析设计的出发点,那么就可以轻易的理解这些而不用记忆这么多:

1关注度分离。书写模块的时候我们是不用指定模块id的,require的模块时候只要填入依赖模块的相对路径,于是我们只要关注代码的书写而不是依赖,打包后工具会自动帮我们处理好模块id

2尽量与浏览器的解析规则一致。上线后在浏览器中的代码,模块路径的解析规则应该于平时用的cssjs这些加载路径规则一样,普通路径和相对路径的都是相对当前页面的。

模块记载机制

千万别天真的以为你在模块里面这样:

SeaJS在AIFISH前端框架中的使用详解

就天真地以为,这个模块会加载完a模块之后再加载b模块。真相其实是这样的
在一个模块里面,require语句的优先级是最高的,无论你将它放在模块的任意位置会优先执行require 注意,优先执行require不代表你可以这么写:

SeaJS在AIFISH前端框架中的使用详解

除非a.js是个三方插件或者a模块不对外提供任何方法和属性,仅仅是用于给页面来点特效啦,加载一些数据啦等,和代码的下文没有什么关系的事情,你大可以把require(“a”)放在任何地方,也就没必要将其赋值给某个变量了。

比如

a.js的内容如下:

SeaJS在AIFISH前端框架中的使用详解

一个依赖a模块的模块内容如下:

执行结果你会发现弹窗内容果然先是”a”,后是”t”; 
值得注意的是seajs还有一种模块加载方法是use,它的加载时机就得看你把它写在什么地方了。 
接上文的那个依赖a模块的模块内容如果是这么写:

这次的执行结果就是先”t””a”了。

言归正传,ab到底谁先加载,我可以肯定地告诉你,确实是a先加载,但是!恩,但是来了。但是ab谁先加载完就得看各自的造化了,或是因为网络原因,或是因为文件大小,意思就是说你require的模块它们之间一定不要有啥耦合关系,否则很有可能会因为加载的先后顺序导致一些异常,不过话又说回来,如果你严格按照seajs的规范来设计模块的话这种事问题肯定不会出现的,各个模块内部都有独立的作用域和其明确的依赖链。

总 结

AIFISH中使用SeaJS可以提高JavaScript代码的可读性和清晰度,解决目前JavaScript编程中普遍存在的依赖关系混乱和代码纠缠等问题,方便代码的编写和维护。
SeaJS
本身遵循KISSKeep It Simple, Stupid)理念进行开发,其本身仅有个位数的API,因此学习起来毫无压力。
在学习SeaJS的过程中,处处能感受到KISS原则的精髓——仅做一件事,做好一件事。


以上是关于SeaJS在AIFISH前端框架中的使用详解的主要内容,如果未能解决你的问题,请参考以下文章

day21

前端技术 - SeaJS学习

模块化之seaJs学习和使用

前端模块化——seaJS

前端模块化CMD规范seajs的使用

angularJS1笔记-(20)-模块化加载机制seajs