2019.5.31 星期五
实践
下面一堆东西都作废。
jQuery3.4的封装方式可以到处使用。和 UMD 的语法糖稍微有一点差别。$PS: 咱也不敢问
CMD是中文开发者(玉伯?),可以直接去sea.js 了解到 js 模块的历史。
AMD是英文。中文教程也有一堆
一堆东西,就不赘述了
5分钟上手,原因/特性等也是明明白白。实现没有去了解
Sea.js: https://seajs.github.io/seajs/
https://github.com/seajs/seajs
require.js:https://github.com/requirejs/requirejs
https://requirejs.org/
browserify: https://github.com/browserify/browserify
http://browserify.org/
$PS: seajs, requirejs 都有打包方案。browserify的打包稍微有一些区别(把node包打包浏览器可以用),合并/压缩文件等没有细看;
写在前面
不谈什么:传统的模块化开发方式,比如文件拆分、全局变量、命名空间,以及 YUI3 式的模块化开发方式。有兴趣的可阅读:#547
谈什么: 关于 CommonJS、AMD、Node.js、CMD 等相关的故事与未来趋势,很有意思。
不一定精准:本文是基于史实的扯淡,因此部分文字特别是时间都是模糊记忆,不一定精准。关于流派、趋势则是个人在社区的感受,不代表客观看法。(看法都是主观> 的,呵呵)
# Sea.js 使用文档
## 探讨
前端模块化开发那点历史
从 CommonJS 到 Sea.js
与 Node.js 兼容
与 RequireJS 的异同
与 OzJS 的探讨
ES6 模块
概述
ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。
CommonJS 和 AMD 模块,都只能在运行时确定这些东西。比如,CommonJS 模块就是对象,输入时必须查找对象属性。
除了静态加载带来的各种好处,ES6 模块还有以下好处。
$PS: 静态加载(非运行加载),所以又很多限制。但是有 import() 函数了
浏览器加载
传统方法
defer与async的区别是:
defer要等到整个页面在内存中正常渲染结束(DOM 结构完全生成,以及其他脚本执行完成),才会执行;
async一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。
一句话,defer是“渲染完再执行”,async是“下载完就执行”。
另外,如果有多个defer脚本,会按照它们在页面出现的顺序加载,而多个async脚本是不能保证加载顺序的。
加载规则
浏览器加载 ES6 模块,也使用<script>
标签,但是要加入type=”module”属性。
浏览器对于带有type=”module”的<script>
,都是异步加载,不会造成堵塞浏览器,即等到整个页面渲染完,再执行模块脚本,等同于打开了<script>
标签的defer属性。
如果网页有多个<script type="module">
,它们会按照在页面出现的顺序依次执行。 $PS: async并不会顺序执行<script>
标签的async属性也可以打开,这时只要加载完成,渲染引擎就会中断渲染立即执行。执行完成后,再恢复渲染。
一旦使用了async属性,<script type="module">
就不会按照在页面出现的顺序执行,而是只要该模块加载完成,就执行该模块。
ES6 模块与 CommonJS 模块的差异
它们有两个重大差异。
(1) CommonJS 模块输出的是一个值的拷贝,ES6 模块输出的是值的引用。
(2) CommonJS 模块是运行时加载,ES6 模块是编译时输出接口。
第二个差异是因为 CommonJS 加载的是一个对象(即module.exports属性),该对象只有在脚本运行完才会生成。
而 ES6 模块不是对象,它的对外接口只是一种静态定义,在代码静态解析阶段就会生成。
下面重点解释第一个差异。
CommonJS 模块输出的是值的拷贝,也就是说,一旦输出一个值,模块内部的变化就影响不到这个值。请看下面这个模块文件lib.js的例子。
Node 加载
概述
Node 对 ES6 模块的处理比较麻烦,因为它有自己的 CommonJS 模块格式,与 ES6 模块格式是不兼容的。
目前的解决方案是,将两者分开,ES6 模块和 CommonJS 采用各自的加载方案。
………
1 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
~~~~~~~~
jQuery的封装方式
2019.5.30 星期四
封装pagination。借鉴了jquery-3.41
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111// cc from jquery: <https://code.jquery.com/jquery-3.4.1.js>
;( function( global, factory ) {
;
if ( typeof module === "object" && typeof module.exports === "object" ) {
// For CommonJS and CommonJS-like environments where a proper `window`
// is present, execute the factory and get jQuery.
// For environments that do not have a `window` with a `document`
// (such as Node.js), expose a factory as module.exports.
// This accentuates the need for the creation of a real `window`.
// e.g. var jQuery = require("jquery")(window);
// See ticket #14549 for more info.
module.exports = global.document ?
factory( global, true ) :
function( w ) {
if ( !w.document ) {
throw new Error( "CoPagination requires a window with a document" );
}
return factory( w );
};
} else {
factory( global );
}
// Pass this if window is not defined yet
} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
/**
* @param {string} param0.hideOnSinglePage - 只有一页时是否隐藏. $_NEXT
* @param {string} param0.pagerCount - 显示页码按钮的数量,当总页数超过该值时会折叠。大于等�?? 5 且小于等�?? 21 的奇�?? $PS: 不知道为啥小�??21
* @param {Array} param0.layout - 要展示的内容。limits, prev, pager, next, jumper, total,count
*/
function CoPagination({ele='.co-pagination',hideOnSinglePage=false,curr=1,count=1,limit=10,limits=[5,10,15,20],pagerCount=7,prevText='<',nextText='>',layout=['limits','prev','pager','next','jumper']}={}){
this.dom=document.querySelectorAll(ele)[0]
this.curr=curr
pagerCount%2==0&&(pagerCount+=1)
pagerCount<7&&(pagerCount=7)
this.count=count
this.limit=limit
this.limits=limits
this.pagerCount=pagerCount
this.prevText=prevText
this.nextText=nextText
this.layout=layout
this.init()
}
CoPagination.prototype={
constructor:CoPagination,
init:function(){
this.renderHtml()
},
renderHtml(){},
renderPagerHtml(curr){},
changeCurr(curr){},
changeLimit(limit){},
}
// Register as a named AMD module, since jQuery can be concatenated with other
// files that may use define, but not via a proper concatenation script that
// understands anonymous AMD modules. A named AMD is safest and most robust
// way to register. Lowercase jquery is used because AMD module names are
// derived from file names, and jQuery is normally delivered in a lowercase
// file name. Do this after creating the global so that if an AMD module wants
// to call noConflict to hide this version of jQuery, it will work.
// Note that for maximum portability, libraries that are not jQuery should
// declare themselves as anonymous modules, and avoid setting a global if an
// AMD loader is present. jQuery is a special case. For more information, see
// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
// $PS: 和上面定义的 UMD 语法糖 稍微有些区别
if ( typeof define === "function" && define.amd ) {
define( "copagination", [], function() {
return CoPagination;
} );
}
// Expose jQuery and $ identifiers, even in AMD
// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
// and CommonJS for browser emulators (#13566)
if ( !noGlobal ) {
// window.jQuery = window.$ = jQuery;
window.CoPagination = CoPagination;
}
return CoPagination;
});
/* ES6
class CoPagination{
constructor({dom=''}={}){
this.dom=dom
}
_pagerHtml=''
init(){}
}
*/