目录
1_前端工具库
jQuery是一个快速、小型且功能丰富的 JavaScript 库,它使HTML文档遍历和操作、事件处理、动画和 AJAX 之类的事情变得
更加简单。当时jQuery库不但简化了代码,而且提供出色的跨浏览器支持,其极大的提高了 Web 开发人员的工作效率。 除了
jQuery之外,其实还有许多库和框架可供JavaScript开发人员使用。下图是前端开发常用的工具库:
百分比表示使用的比例
2_underscore库 & Lodash库
Lodash 和 Underscore 都是非常实用JavaScript工具库,它们都提供了非常多的函数来对数字、字符串、数组、对象等操作,这些函数不但可以简化JavaScript编写,而且可以极大的提高开发效率。这些库非常适合如下操作:
- 迭代数组、对象和字符串。
- 操作和测试值。
- 创建复合函数。
Lodash是Underscore的一个分支,仍然遵循Underscore的API, 但在底层已完全重写过。对于字符串、数组、对象等Lodash提供了跨环境迭代的支持。
Lodash还添加了许多Underscore没有提供的特性和功能,例如:提供 AMD 支持、深度克隆、深度合并、更好的性能、大型数组和对象迭代的优化等,如今的Lodash足以成为Underscore替代品。
Lodash从第4个版本开始放弃对IE9以下的支持
3_Lodash库
3.1_Lodash库的安装
方式一:CND
https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
方式二:下载源码引入
<script src="./libs/lodash-4.17.21.js"></script>
<script>
// 1.打印一下 _
console.log("%O", _)
console.log(_.VERSION) // 查看Lodash的版本号
console.log(_.join([2050, 6, 23], '-'))
</script>
3.2_Lodash库字符串、数组
字符串、数组字符串(String)
- _.camelCase(string) - 转换字符串为驼峰写法。
- _.capitalize(string) - 转换字符串首字母为大写,剩下为小写。
- _.endsWith(string, target) - 检查字符串是否以给定的target字符串结尾。
- _padStart(str, length,char) - 若字符串长度小于 length 则在左侧填充字符。 如果超出length长度则截断超出的部分。
- _.trim(string, chars) - 从字符串中移除前面和后面的 空格 或 指定的字符。
<script src="./libs/lodash-4.17.21.js"></script>
<script>
// 1.将字符串转成 驼峰命名
console.log( _.camelCase(' foo bar ') ) //fooBar
console.log( _.camelCase('--foo-bar--') ) //fooBar
//2. 首字母大写
console.log( _.capitalize('foo bar') ) //Foo bar
// 3. 检查字符串,是否以给的的字符串结尾
console.log(_.endsWith('logo.jpeg', '.png') ) //false
// 4. _padStart(str, length,char) 若字符串长度小于 length 则在左侧填充字符。 如果超出length长度则截断超出的部分。
console.log(_.padStart('9', 2, '0')) // 9 -> 09
</script>
数组(Array)
- _.first(arr, level) - 获取array中的第一个元素。
- _.last(arr, [n=1]) - 获取array中的最后一个元素。
- _.uniq(arr) - 创建一个去重后的array数组副本。返回新的去重后的数组。
- _.compact(arr) - 创建一个新数组,包含原数组中所有的非假值元素。返回过滤掉假值的新数组。
- _.flatten(arr) - 减少一级array嵌套深度。返回新数组
3.3_Lodash库对象、集合、函数
对象
- _.pick(object, [props]) : 从object中选中的属性来创建一个对象。返回新对象。
- .omit(object, [props]): 反向版.pick ; 删除object对象的属性。返回新对象。
- _.clone( value) - 支持拷贝 arrays、 booleans、 date 、map、 numbers, Object 对象, sets, strings, symbols等等。 arguments对象的可枚举属性会拷贝为普通对象。(注:
也叫浅拷贝) 返回拷贝后的值。 - .cloneDeep(value) -这个方法类似.clone,担它会递归拷贝 value。(注:也叫深拷贝)。返回拷贝后的值。
集合(Array | Object)
- _.sample(): 从collection(集合)中获得一个随机元素。返回随机元素。
- _.orderBy : 给数组排序,默认是升序asc。
- _.each() / _.forEach() - 遍历(集合) 中的每个元素
- _.filter( ) - 返回一个新的过滤后的数组。
函数
- _.curry() - 返回新的柯里化(curry)函数。
- _.debounce() - 返回新的 debounced(防抖动)函数。
- _.throttle() - 返回节流的函数。
4_Moment.js库 & Day.js库
Moment库,官网的描述:
- Moment 是一个 JavaScript 库,可以帮助快速处理时间和日期,已在数百万的项目中使用。
- Moment对浏览器的兼容性比较好,例如,在Internet Explorer 8+版本运行良好。
- 现在比较多人反对使用 Moment是因为它的包大小。Moment 不适用于“tree-shaking”算法,因此往往会增加 Web 应用程序包的大小。如果需要国际化或时区支持,Moment 可以变得相当大。
- Moment团队也希望在未来的新项目中不要使用Moment 。而推荐使用其它的替代品。例如:Day.js。
Day.js库,官网的描述:
- Day.js 是 Moment的缩小版。Day.js 拥有与 Moment相同的 API,并将其文件大小减少了 97%。
- Moment完整压缩文件的大小为 67+Kb,Day.js 压缩文件只有 2Kb。
- Day.js所有的 API 操作都将返回一个新的 Day.js 对象,这种设计能避免 bug 产生,减少调试时间。
- Day.js 对国际化支持良好。国际化需手动加载,多国语言默认是不会被打包到Day.js中的
5_Day.js库
5.1_Day.js库的安装
方式一:CND
https://unpkg.com/dayjs@1.8.21/dayjs.min.js
方式二:下载源码引入
<script src="./libs/dayjs.js"></script>
<script>
// console.log("%O", dayjs)
console.log("%O", dayjs()) // 创建 dayjs 对象
console.log(dayjs().format()) // 拿到当前的时间
</script>
源码: Dayjs.min.js (可以直接复制,新建一个js文件保存)
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).dayjs=e()}(this,(function(){"use strict";var t=1e3,e=6e4,n=36e5,r="millisecond",i="second",s="minute",u="hour",a="day",o="week",f="month",h="quarter",c="year",d="date",$="Invalid Date",l=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,y=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,M={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_")},m=function(t,e,n){var r=String(t);return!r||r.length>=e?t:""+Array(e+1-r.length).join(n)+t},g={s:m,z:function(t){var e=-t.utcOffset(),n=Math.abs(e),r=Math.floor(n/60),i=n%60;return(e<=0?"+":"-")+m(r,2,"0")+":"+m(i,2,"0")},m:function t(e,n){if(e.date()<n.date())return-t(n,e);var r=12*(n.year()-e.year())+(n.month()-e.month()),i=e.clone().add(r,f),s=n-i<0,u=e.clone().add(r+(s?-1:1),f);return+(-(r+(n-i)/(s?i-u:u-i))||0)},a:function(t){return t<0?Math.ceil(t)||0:Math.floor(t)},p:function(t){return{M:f,y:c,w:o,d:a,D:d,h:u,m:s,s:i,ms:r,Q:h}[t]||String(t||"").toLowerCase().replace(/s$/,"")},u:function(t){return void 0===t}},v="en",D={};D[v]=M;var p=function(t){return t instanceof _},S=function t(e,n,r){var i;if(!e)return v;if("string"==typeof e){var s=e.toLowerCase();D[s]&&(i=s),n&&(D[s]=n,i=s);var u=e.split("-");if(!i&&u.length>1)return t(u[0])}else{var a=e.name;D[a]=e,i=a}return!r&&i&&(v=i),i||!r&&v},w=function(t,e){if(p(t))return t.clone();var n="object"==typeof e?e:{};return n.date=t,n.args=arguments,new _(n)},O=g;O.l=S,O.i=p,O.w=function(t,e){return w(t,{locale:e.$L,utc:e.$u,x:e.$x,$offset:e.$offset})};var _=function(){function M(t){this.$L=S(t.locale,null,!0),this.parse(t)}var m=M.prototype;return m.parse=function(t){this.$d=function(t){var e=t.date,n=t.utc;if(null===e)return new Date(NaN);if(O.u(e))return new Date;if(e instanceof Date)return new Date(e);if("string"==typeof e&&!/Z$/i.test(e)){var r=e.match(l);if(r){var i=r[2]-1||0,s=(r[7]||"0").substring(0,3);return n?new Date(Date.UTC(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)):new Date(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)}}return new Date(e)}(t),this.$x=t.x||{},this.init()},m.init=function(){var t=this.$d;this.$y=t.getFullYear(),this.$M=t.getMonth(),this.$D=t.getDate(),this.$W=t.getDay(),this.$H=t.getHours(),this.$m=t.getMinutes(),this.$s=t.getSeconds(),this.$ms=t.getMilliseconds()},m.$utils=function(){return O},m.isValid=function(){return!(this.$d.toString()===$)},m.isSame=function(t,e){var n=w(t);return this.startOf(e)<=n&&n<=this.endOf(e)},m.isAfter=function(t,e){return w(t)<this.startOf(e)},m.isBefore=function(t,e){return this.endOf(e)<w(t)},m.$g=function(t,e,n){return O.u(t)?this[e]:this.set(n,t)},m.unix=function(){return Math.floor(this.valueOf()/1e3)},m.valueOf=function(){return this.$d.getTime()},m.startOf=function(t,e){var n=this,r=!!O.u(e)||e,h=O.p(t),$=function(t,e){var i=O.w(n.$u?Date.UTC(n.$y,e,t):new Date(n.$y,e,t),n);return r?i:i.endOf(a)},l=function(t,e){return O.w(n.toDate()[t].apply(n.toDate("s"),(r?[0,0,0,0]:[23,59,59,999]).slice(e)),n)},y=this.$W,M=this.$M,m=this.$D,g="set"+(this.$u?"UTC":"");switch(h){case c:return r?$(1,0):$(31,11);case f:return r?$(1,M):$(0,M+1);case o:var v=this.$locale().weekStart||0,D=(y<v?y+7:y)-v;return $(r?m-D:m+(6-D),M);case a:case d:return l(g+"Hours",0);case u:return l(g+"Minutes",1);case s:return l(g+"Seconds",2);case i:return l(g+"Milliseconds",3);default:return this.clone()}},m.endOf=function(t){return this.startOf(t,!1)},m.$set=function(t,e){var n,o=O.p(t),h="set"+(this.$u?"UTC":""),$=(n={},n[a]=h+"Date",n[d]=h+"Date",n[f]=h+"Month",n[c]=h+"FullYear",n[u]=h+"Hours",n[s]=h+"Minutes",n[i]=h+"Seconds",n[r]=h+"Milliseconds",n)[o],l=o===a?this.$D+(e-this.$W):e;if(o===f||o===c){var y=this.clone().set(d,1);y.$d[$](l),y.init(),this.$d=y.set(d,Math.min(this.$D,y.daysInMonth())).$d}else $&&this.$d[$](l);return this.init(),this},m.set=function(t,e){return this.clone().$set(t,e)},m.get=function(t){return this[O.p(t)]()},m.add=function(r,h){var d,$=this;r=Number(r);var l=O.p(h),y=function(t){var e=w($);return O.w(e.date(e.date()+Math.round(t*r)),$)};if(l===f)return this.set(f,this.$M+r);if(l===c)return this.set(c,this.$y+r);if(l===a)return y(1);if(l===o)return y(7);var M=(d={},d[s]=e,d[u]=n,d[i]=t,d)[l]||1,m=this.$d.getTime()+r*M;return O.w(m,this)},m.subtract=function(t,e){return this.add(-1*t,e)},m.format=function(t){var e=this,n=this.$locale();if(!this.isValid())return n.invalidDate||$;var r=t||"YYYY-MM-DDTHH:mm:ssZ",i=O.z(this),s=this.$H,u=this.$m,a=this.$M,o=n.weekdays,f=n.months,h=function(t,n,i,s){return t&&(t[n]||t(e,r))||i[n].slice(0,s)},c=function(t){return O.s(s%12||12,t,"0")},d=n.meridiem||function(t,e,n){var r=t<12?"AM":"PM";return n?r.toLowerCase():r},l={YY:String(this.$y).slice(-2),YYYY:this.$y,M:a+1,MM:O.s(a+1,2,"0"),MMM:h(n.monthsShort,a,f,3),MMMM:h(f,a),D:this.$D,DD:O.s(this.$D,2,"0"),d:String(this.$W),dd:h(n.weekdaysMin,this.$W,o,2),ddd:h(n.weekdaysShort,this.$W,o,3),dddd:o[this.$W],H:String(s),HH:O.s(s,2,"0"),h:c(1),hh:c(2),a:d(s,u,!0),A:d(s,u,!1),m:String(u),mm:O.s(u,2,"0"),s:String(this.$s),ss:O.s(this.$s,2,"0"),SSS:O.s(this.$ms,3,"0"),Z:i};return r.replace(y,(function(t,e){return e||l[t]||i.replace(":","")}))},m.utcOffset=function(){return 15*-Math.round(this.$d.getTimezoneOffset()/15)},m.diff=function(r,d,$){var l,y=O.p(d),M=w(r),m=(M.utcOffset()-this.utcOffset())*e,g=this-M,v=O.m(this,M);return v=(l={},l[c]=v/12,l[f]=v,l[h]=v/3,l[o]=(g-m)/6048e5,l[a]=(g-m)/864e5,l[u]=g/n,l[s]=g/e,l[i]=g/t,l)[y]||g,$?v:O.a(v)},m.daysInMonth=function(){return this.endOf(f).$D},m.$locale=function(){return D[this.$L]},m.locale=function(t,e){if(!t)return this.$L;var n=this.clone(),r=S(t,e,!0);return r&&(n.$L=r),n},m.clone=function(){return O.w(this.$d,this)},m.toDate=function(){return new Date(this.valueOf())},m.toJSON=function(){return this.isValid()?this.toISOString():null},m.toISOString=function(){return this.$d.toISOString()},m.toString=function(){return this.$d.toUTCString()},M}(),T=_.prototype;return w.prototype=T,[["$ms",r],["$s",i],["$m",s],["$H",u],["$W",a],["$M",f],["$y",c],["$D",d]].forEach((function(t){T[t[1]]=function(e){return this.$g(e,t[0],t[1])}})),w.extend=function(t,e){return t.$i||(t(e,_,w),t.$i=!0),w},w.locale=S,w.isDayjs=p,w.unix=function(t){return w(1e3*t)},w.en=D[v],w.Ls=D,w.p={},w}));
5.2_自定义实现
新建Dayjs.js文件,具体代码如下
;(function (g){
// browser -> window 全局对象
// node -> global 全局对象
// globalThis -> ES11
g = typeof globalThis !== 'undefined' ? globalThis : g || self
// 构造函数
function Dayjs() {
var date = new Date()
this.$Y = date.getFullYear()
this.$M = date.getMonth()
this.$D = date.getDate()
}
// 原型上的方法
Dayjs.prototype.format = function() {
return `${this.$Y}-${ (this.$M + 1) }-${this.$D}`
}
// ......原型的方法
// 工厂函数
function dayjs() {
return new Dayjs()
}
dayjs.prototype = Dayjs.prototype
// 统一导出
g.dayjs = dayjs
})(this)
5.3_Day.js获取、设置、操作时间
获取(Get) + 设置(Set)
- .year()、.month、.date() - - 获取年、月、日
- .hour()、.minute()、.second() - 获取时、分、秒
- .day() - 获取星期几
- .format() - 格式化日期
//下载后,本地引入Dayjs库
<script src="./libs/dayjs.js"></script>
<script >
// 1.拿到当前时间的Dayjs的对象
var day = dayjs()
console.log(day.year(), (day.month() + 1), day.date(), day.hour(), day.minute(), day.second())
// 2.设置某个时间
var day2 = dayjs()
.year(2035)
.month(5)
.date(1)
console.log(day2.year(), (day2.month() + 1), day2.date(), day2.hour(), day2.minute(), day2.second())
</script>
操作日期和时间
- .add(numbers , unit) - 添加时间
- .subtract(numbers , unit) - 减去时间
- .startOf(unit) - 时间的开始
例如:获取今年的第一天零时零分零秒
//下载后,本地引入Dayjs库
<script src="./libs/dayjs.js"></script>
<script>
var day = dayjs() // 拿到当前时间的dayjs 对象
// .add(1, 'year') // 增加一年
// .add(2, 'month') // 增加2个月
// .add(-1, 'month') // 减去一个月
// .subtract(1, 'year') // 减去一年
// .subtract(1, 'month') //减去一个月
// .subtract(1, 'day') //减去一天
// .startOf('year') // 一年的开始 2022-01-01 00:00:00
.startOf('month') // 一个月的开始
// .startOf('day') //
// 时间的格式化
console.log( day.format("YYYY-MM-DD HH:mm:ss") )
</script>
5.4_Day.js解析、国际化、插件
解析时间
- dayjs(毫秒|秒) - 时间戳(毫秒 和 秒)
- dayjs(‘2022-06-15’) - ISO 8601格式的字符串
- dayjs(new Date()) - 接收日期对象
//下载后,本地引入Dayjs库
<script src="./libs/dayjs.js"></script>
<script>
// 1.解析一个字符串(ISO 8601)类型的时间
// YYYY-MM-DD HH:mm:ss
// YYYY-MM-DD
// YYYY/MM/DD
var day1 = dayjs('2035-2-2 12:00:10') // dayjs 对象
console.log( day1.format("YYYY/MM/DD HH/mm/ss") ) //2035/02/02 12/00/10
// 2.解析时间戳(毫秒)
var day2 = dayjs(1759206934331) // dayjs 对象
console.log( day2.format("YYYY/MM/DD HH/mm/ss") ) //2025/09/30 12/35/34
// 3.解析时间戳(秒)
var day3 = dayjs.unix( 1856206934 ) // dayjs 对象
console.log( day3.format("YYYY/MM/DD HH/mm/ss") ) //2028/10/27 05/02/14
// 4.解析Date对象
var day4 = dayjs(new Date('2050-10-1')) // dayjs 对象
console.log( day4.format("YYYY/MM/DD HH/mm/ss") ) //2050/10/01 00/00/00
</script>
Day.js的插件应用
- .fromNow() - 从现在开始的时间 (需要依赖:relativeTime 插件)
- relativeTime插件:https://cdn.jsdelivr.net/npm/dayjs@1.11.3/plugin/relativeTime.js
- 源码:dayjs.relative-time.min.js (可以直接复制,新建一个js文件保存)
!function(r,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(r="undefined"!=typeof globalThis?globalThis:r||self).dayjs_plugin_relativeTime=e()}(this,(function(){"use strict";return function(r,e,t){r=r||{};var n=e.prototype,o={future:"in %s",past:"%s ago",s:"a few seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",M:"a month",MM:"%d months",y:"a year",yy:"%d years"};function i(r,e,t,o){return n.fromToBase(r,e,t,o)}t.en.relativeTime=o,n.fromToBase=function(e,n,i,d,u){for(var f,a,s,l=i.$locale().relativeTime||o,h=r.thresholds||[{l:"s",r:44,d:"second"},{l:"m",r:89},{l:"mm",r:44,d:"minute"},{l:"h",r:89},{l:"hh",r:21,d:"hour"},{l:"d",r:35},{l:"dd",r:25,d:"day"},{l:"M",r:45},{l:"MM",r:10,d:"month"},{l:"y",r:17},{l:"yy",d:"year"}],m=h.length,c=0;c<m;c+=1){var y=h[c];y.d&&(f=d?t(e).diff(i,y.d,!0):i.diff(e,y.d,!0));var p=(r.rounding||Math.round)(Math.abs(f));if(s=f>0,p<=y.r||!y.r){p<=1&&c>0&&(y=h[c-1]);var v=l[y.l];u&&(p=u(""+p)),a="string"==typeof v?v.replace("%d",p):v(p,n,y.l,s);break}}if(n)return a;var M=s?l.future:l.past;return"function"==typeof M?M(a):M.replace("%s",a)},n.to=function(r,e){return i(r,e,this,!0)},n.from=function(r,e){return i(r,e,this)};var d=function(r){return r.$u?t.utc():t()};n.toNow=function(r){return this.to(d(this),r)},n.fromNow=function(r){return this.from(d(this),r)}}}));
国际化:
- 下载对应的语言包,去官网https://unpkg.com/browse/dayjs@1.8.21/locale/ (中文包是zh-cn.js,网址:https://unpkg.com/dayjs@1.8.21/locale/zh-cn.js)
- 去Dayjs的官网,,“国际化”选项中找到如何配置 https://day.js.org/docs/zh-CN/installation/browser
- 源码:dayjs.zh-cn.min.js (可以直接复制,新建一个js文件保存)
!function(e,_){"object"==typeof exports&&"undefined"!=typeof module?module.exports=_(require("dayjs")):"function"==typeof define&&define.amd?define(["dayjs"],_):(e="undefined"!=typeof globalThis?globalThis:e||self).dayjs_locale_zh_cn=_(e.dayjs)}(this,(function(e){"use strict";function _(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var t=_(e),d={name:"zh-cn",weekdays:"星期日_星期一_星期二_星期三_星期四_星期五_星期六".split("_"),weekdaysShort:"周日_周一_周二_周三_周四_周五_周六".split("_"),weekdaysMin:"日_一_二_三_四_五_六".split("_"),months:"一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月".split("_"),monthsShort:"1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月".split("_"),ordinal:function(e,_){return"W"===_?e+"周":e+"日"},weekStart:1,yearStart:4,formats:{LT:"HH:mm",LTS:"HH:mm:ss",L:"YYYY/MM/DD",LL:"YYYY年M月D日",LLL:"YYYY年M月D日Ah点mm分",LLLL:"YYYY年M月D日ddddAh点mm分",l:"YYYY/M/D",ll:"YYYY年M月D日",lll:"YYYY年M月D日 HH:mm",llll:"YYYY年M月D日dddd HH:mm"},relativeTime:{future:"%s内",past:"%s前",s:"几秒",m:"1 分钟",mm:"%d 分钟",h:"1 小时",hh:"%d 小时",d:"1 天",dd:"%d 天",M:"1 个月",MM:"%d 个月",y:"1 年",yy:"%d 年"},meridiem:function(e,_){var t=100*e+_;return t<600?"凌晨":t<900?"早上":t<1100?"上午":t<1300?"中午":t<1800?"下午":"晚上"}};return t.default.locale(d,null,!0),d}));
下方代码使用举例:
<script src="./libs/dayjs.js"></script>
<!-- 会在 Dayjs 的原型上添加插件: fromNow .... -->
<script src="./libs/dayjs.relative-time.min.js"></script>
<!-- 给给dayjs的全局变量 Ls 添加了一个中文包 -->
<script src="./libs/dayjs.zh-cn.min.js"></script>
<script>
// 1.安装插件
dayjs.extend(dayjs_plugin_relativeTime)
// 2.切换使用中文
dayjs.locale('zh-cn')
// 3.实现当前时间,距离某个时间点过去了多久。比如 1小时前 5分钟前 2天前 一个月内
var day = dayjs(1696206934331) // dayjs 对象
console.log(day.fromNow()) //两个月内
</script>