介绍25种很实用的ES6方法,来解决实际开发中的问题 原创 @泽泽vlog 昨天
主要是介绍25种ES6方法,这些方法都挺实用的,用本本记好要考的,嘿嘿嘿。时不时翻出来看看
1. 如何隐藏所有指定的元素 const hide = (el )=> [...el].forEach(e => e.style.display = 'none' ) hide(document .querySelectorAll('img' ))
2. 如何检查元素是否具有指定的类 在页面DOM里的每个节点上都有一个classList对象,程序员可以使用里面的方法新增、删除、修改节点上的CSS类。使用classList,程序员还可以用它来判断某个节点是否被赋予了某个CSS类
const hasClass = (el,className )=> el.classList.contains(className)hasClass(document .querySelector('div.s_form_wrapper ' ),'soutu-env-nomac' )
3. 如何切换一个元素的类 const toggleClass =(el,className )=> el.classList.toggle(className)toggleClass( document .querySelector('div.s_form_wrapper ' ),'s_form_wrapper' )
4. 如何获取当前页面的滚动位置 const getScrollPosition =(el=window )=> ({ x:el.pageXOffset !==undefined ? el.pageXOffset:el.scrollLeft, y:el.pageYOffset !==undefined ? el.pageYOffset:el.scrollTop }) getScrollPosition()
5. 如何平滑滚动到页面顶部 const scrollToTop=() => { const c = document .documentElement.scrollTop || document .body.scrollTop if (c > 0 ){ window .requestAnimationFrame(scrollToTop) window .scrollTo(0 ,c-c/8 ) } } scrollToTop()
requestAnimationFrame()
不需要设置时间间隔,是由系统的时间间隔定义的。大多数浏览器的刷新频率是60Hz(每秒钟反复绘制60次),循环间隔是1000/60,约等于16.7ms。大多数浏览器会对反复挥着这个操作加以限制,不能超过60HZ,即使人为设置超过了该值,效果也不会改善。requestAnimationFrame()
保证了最佳的绘制效率。 当页面被隐藏或者最小化时,setInterval()
仍在后台继续执行,这种动画刷新是完全没有意义的,对cpu也是极大的浪费; 当页面被隐藏或者最小化时,requestAnimationFramel()
中页面的渲染会被系统暂停,当页面再次激活后,继续从上次停止地方继续绘制;
6. 如何检查指定的元素在视口中是否可见 const elmentIsVisibleInViewport = (el,partiallyVisible=false )=> { const {top,left,bottom,right } = el.getBoundingClientRect(); const { innerHeight ,innerWidth } = window ; return partiallyVisible ?((top > 0 && top < innerHeight ) ||( bottom > 0 && bottom < innerHeight )) && ((left > 0 && left < innerWidth ) || (right > 0 && right < innerWidth )) : top >= 0 && left >=0 && bottom <= innerHeight && right <= innerWidth; } elmentIsVisibleInViewport(el); elmentIsVisibleInViewport(el,true );
7. 如何检查父元素是否包含子元素 const elementContains =(parent,child )=> parent !== child && parent.contains(child);elementContains(document .querySelector('head' ),document .querySelector('title' ) elementContains(document .querySelector('body' ),document .querySelector('body' )
8. 如何获取元素中的所有图像? const getImages = (el,includeDuplicates = false )=> { const images = [...el.getElementByTagName('img' )].map(img => img.getAttribute('src' )); return includeDuplicates?images:[...new Set (images)]; } getImages(document ,true ) getImages(document ,false )
9. 如何确定设备是移动设备还是台式机/笔记本电脑 const detectDeviceType = () => { return /Android|webOS|iPhone|iPad|BlackBerry|IEMobile|Opera Mini/i .test(navigator.userAgent)?'Mobile' :'Desktop' ; } detectDeviceType();
10. 获取当前url const currentURL =() => {window .location.href}currentURL();
11. 验证url的格式合法性 const isURL=(str_url )=> { let reg = /(?:(https?|ftp|file):)?\/\/[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]/ ; let re = new RegExp (reg); return re.test(str_url); } isURL('http://www.zeze.info' )
12. 如何创建一个包含当前URL参数的对象 const getURLParameters = url => (url.match(/([^?=&]+)(=([^&]*))/g ) || []).reduce( (accumulator,currentValue) => ((accumulator[currentValue.slice(0 ,v.indexOf('=' ))] = currentValue.slice(currentValue.indexOf('=' )+1 )),accumulator) ,{} ); getURLParameters('http://www.zeze.info/index?a=1&b=2' ) getURLParameters('http://www.zeze.info' )
13. 如何将一组表单元素转化为对象 const formToObject = form => { Array .from(new FormData(form)).reduce( (acc,[key,value])=>({ ...acc, [key]:value }), {} ) } formToObject(document .querySelector('#from' ))
14. 如何从对象检索给定选择器指示的一组属性 const get =(from,...selectos)=> [...selectos].map(s=> s .replace(/\[([^\[\]]*)\]/g,'.$1.') .split('.') .filter(t=> t !=='') .reduce((prev,cur)=>prev && prev[cur],from) ); const obj = { selector:{to :{val :'val to select' } }, target :[1 ,2 ,{a :'test' }] }; get (obj,'selector.to.val','target[0]','target[2].a')// ["val to select", 1, "test"]
15. 如何在等待指定时间后调用提供的函数 const delay =(fn,wait,...args )=> setTimeout(fn,wait,...args)delay( (test)=>console .info(test), 1000 , 'later' )
16. 如何在给定元素上触发特定事件且能选择地传递自定义数据 var newEvent = new Event('build' , { bubbles :true ,cancelable :true ,composed :true }); newEvent.name = "新的事件!" ; document .addEventListener("build" ,function ( ) { alert("你触发了自定义事件!" + newEvent.name); },false ) document .dispatchEvent(newEvent);
启动文档的时候因为”document.dispatchEvent(newEvent)”的关系,会先触发一次事件:
之后你每执行一次”document.dispatchEvent(newEvent)”都会触发这个事件:
接下来我们看看Event()这个方法的语法
event = new Event(typeArg, eventInit);
typeArg:指定事件类型,传递一个字符串。这里的事件类型指的是像点击事件(click)、提交事件(submit)、加载事件(load)等等。 eventInit:可选,传递EventInit类型的字典。实际上这个EventInit类型的字典也就是我们使用InitEvent()时需要传递的参数,以键值对的形式传递,不过它可以多选一个参数: bubbles:事件是否支持冒泡,传递一个boolean类型的参数,默认值为false。 cancelable:是否可取消事件的默认行为,传递一个boolean类型的参数,默认值为false。 composed:事件是否会触发shadow DOM(阴影DOM)根节点之外的事件监听器,传递一个boolean类型的参数,默认值为false。(关于shadow DOM可以去看ChokCoco前辈的这篇文章 ,这里就不详说了,可能我会根据自己的理解也写一个关于shadow DOM的笔记)这个参数是InitEvent()中没有的新参数。
我们先通过下面的例子了解一下如何使用CustomEvent()去创建一个事件对象(这里先不使用事件相关值detail);
var newEvent = new CustomEvent('build' , { bubbles :true ,cancelable :true ,composed :true });newEvent.name = "新的事件!" ; document .addEventListener("build" ,function ( ) { alert("你触发了使用CustomEvent创建的自定义事件!" + newEvent.name); },false ) document .dispatchEvent(newEvent);
然后我们来看CustomEvent()的语法:
event = new CustomEvent(typeArg, customEventInit);
typeArg:指定事件类型,传递一个字符串。这里的事件类型指的是像点击事件(click)、提交事件(submit)、加载事件(load)等等。
customEventInit:可选。传递一个CustomEventInit字典。实际上这个字典就是我们使用initCustomEvent()时需要的参数,这个参数就是事件相关值(detail):
detail:可选,默认值为null,类型为any(也就是说可以传递任意类型的参数)。这个值就是和事件相关联的值。
在展示使用detail作为第二个参数的例子前,要先注意一件事:CustomEventInit字典也可以接受EventInit字典的参数,就像一开始的例子一样,我传递了EventInit字典的bubbles、cancelable、composed。
下面将展示使用detail参数的例子,使用到detail的部分我会加粗处理(为了看着方便,这回就不传递EventInit字典中的参数了):
var newEvent = new CustomEvent('build' ,{ detail: { dog:"wo" ,cat :"mio" } }); document .addEventListener("build" ,function ( ) { alert(" event.detail.dog:" + event.detail.dog + "\n event.detail.cat:" + event.detail.cat ); },false ) document .dispatchEvent(newEvent);
17. 如何从元素中移除事件监听器 const off = (el,evt,fn,opts=false ) => el.removeEventListener(evt,fn,opts); const fn =() => console .log('!' )document .body.addEventListener('click' ,fn)off(document .body,'click' ,fn)
18. 如何获得给定毫秒数的可读格式 const formatDuration = ms => { if (ms<0 ) ms = -ms; const time ={ day: Math .floor(ms/86400000 ), hour:Math .floor(ms/3600000 ) % 24 , minute: Math .floor(ms/60000 ) % 60 , second: Math .floor(ms/1000 ) % 60 , millisecond: Math .floor(ms) % 1000 , }; return Object .entries(time) .filter(val => val[1 ] !== 0 ) .map(([key,val] )=> `${val} ${key} ${val !== 1 ? 's' :'' } ` ) .join(',' ); } formatDuration(1001 ); formatDuration(3432505574 );
19. 如何获得两个日期之间的差异(以天为单位) const getDaysDiffBetweenDates = (dateInitial,dateFinal )=> (dateFinal - dateInitial) / (1000 * 3600 *24 ) getDaysDiffBetweenDates(new Date ('2020-03-01' ),new Date ('2020-03-03' ))
20. 如何向传递的URL发出GET请求 const httpGet = (url,callback,err = console .error ) => { const request = new XMLHttpRequest(); request.open('GET' ,url,true ); request.onload = () => callback(request.responseText); request.onerror = () => err(request); request.send(); } httpGet( 'https://jsonplaceholder.typicode.com/posts/1' , console .log )
21. 如何对传递的URL发出POST请求 const httpPost = (url,data,callback,err = console .error ) => { const request = new XMLHttpRequest(); request.open('POST' ,url,true ); request.setRequestHeader('Content-type' ,'application/json; charset=utf-8' ); request.onload = () => callback(request.responseText); request.onerror = () => err(request); request.send(data); } const postData={ userId:1 , title:'Foo' } const data =JSON .stringify(postData)httpPost( 'https://jsonplaceholder.typicode.com/posts' , data, console .log )
22. 如何为指定选择器创建具有指定范围,步长和持续时间的计数器 const counter = (selector,start,end,step=1 ,duration )=> { let current = start; _step = (end-start) * step < 0 ?-step : step timer = setInterval(() => { current += _step; document .querySelector(selector).innerHTML = current; if (current >= end) { document .querySelector(selector).innerHTML = end ; clearInterval(timer); } },Math .abs(Math .floor(duration/(end-start)))); } counter('#myId' ,1 ,1000 ,5 ,20000 );
23. 如何将字符串复制到剪贴板 const copyToClipboard = str => { const el = document .createElement('textarea' ); el.value = str; el.setAttribute('readonly' ,'' ); el.style.position='absolute' ; el.style.left = '-9999px' ; document .body.appendChild(el); const selected =document .getSelection().rangeCount >0 ?document .getSelection().getRangeAt(0 ):false ; el.select(); document .execCommand('copy' ); document .body.removeChild(el) if (selected){ document .getSelection().removeAllRanges(); document .getSelection().addRange(selected); } } copyToClipboard('www.zeze.info' )
24. 如何确定页面的浏览器选项卡是否聚焦 const isBrowserTabFocused= () => !document .hidden; isBrowserTabFocused();
25. 如何创建目录(如果不存在) const fs =require ('fs' )const createDirIfNotExists = dir => (!fs.existsSync(dir)?fs.mkdirSync(dir):undefined );createDirIfNotExists('test' );
这里面的方法大都挺实用,可以解决很多开发过程问题,大家就好好利用起来吧。
博主主页
可以加博主微信一起交流: