1. /**
  2. * 判断是否含有某个class
  3. *
  4. * @export
  5. * @param {any} ele 元素
  6. * @param {any} cls class名
  7. * @returns
  8. */
  9. export function hasClass (ele, cls) {
  10. cls = cls || ''
  11. if (cls.replace(/\s/g, '').length === 0) return false // 当cls没有参数时,返回false
  12. return new RegExp(' ' + cls + ' ').test(' ' + ele.className + ' ')
  13. }
  14. /**
  15. * 添加class
  16. *
  17. * @export
  18. * @param {any} ele 元素
  19. * @param {any} cls 需要添加的class名
  20. */
  21. export function addClass (ele, cls) {
  22. if (!hasClass(ele, cls)) {
  23. ele.className = ele.className === '' ? cls : ele.className + ' ' + cls
  24. }
  25. }
  26. /**
  27. * 移出class
  28. *
  29. * @export
  30. * @param {any} ele 元素
  31. * @param {any} cls 需要移除的class名
  32. */
  33. export function removeClass (ele, cls) {
  34. if (hasClass(ele, cls)) {
  35. var newClass = ' ' + ele.className.replace(/[\t\r\n]/g, '') + ' '
  36. while (newClass.indexOf(' ' + cls + ' ') >= 0) {
  37. newClass = newClass.replace(' ' + cls + ' ', ' ')
  38. }
  39. ele.className = newClass.replace(/^\s+|\s+$/g, '')
  40. }
  41. }
  42. export function on (element, event, handler) {
  43. if (element && event) {
  44. element.addEventListener(event, handler, false)
  45. }
  46. }
  47. export function off (element, event, handler) {
  48. if (element && event) {
  49. element.removeEventListener(event, handler, false)
  50. }
  51. }

检查元素是否具有指定类

  1. const hasClass = (el, className) => el.classList.contains(className);
  2. // 例子
  3. hasClass(document.querySelector('p.special'), 'special'); // true

添加类

  1. const addClass = (el, className) => el.classList.add(className);
  2. // 例子
  3. addClass(document.querySelector('p'), 'special');
  4. // The paragraph will now have the 'special' class

删除类

  1. const removeClass = (el, className) => el.classList.remove(className);
  2. // 例子
  3. removeClass(document.querySelector('p.special'), 'special');
  4. // The paragraph will not have the 'special' class anymore

获取元素样式

  1. const getStyle = (el, ruleName) => getComputedStyle(el)[ruleName];
  2. // 例子
  3. getStyle(document.querySelector('p'), 'font-size'); // '16px'

toggle切换类

  1. const toggleClass = (el, className) => el.classList.toggle(className);
  2. // 例子
  3. toggleClass(document.querySelector('p.special'), 'special');
  4. // The paragraph will not have the 'special' class anymore

设置样式

  1. const setStyle = (el, rule, val) => (el.style[rule] = val);
  2. // 例子
  3. setStyle(document.querySelector('p'), 'font-size', '20px');
  4. // The first <p> element on the page will have a font-size of 20px

指定元素添加样式

  1. const addStyles = (el, styles) => Object.assign(el.style, styles);
  2. // 例子
  3. addStyles(document.getElementById('my-element'), {
  4. background: 'red',
  5. color: '#ffff00',
  6. fontSize: '3rem'
  7. });

渲染DOM

  1. const renderElement = ({ type, props = {} }, container) => {
  2. const isTextElement = !type;
  3. const element = isTextElement
  4. ? document.createTextNode('')
  5. : document.createElement(type);
  6. const isListener = p => p.startsWith('on');
  7. const isAttribute = p => !isListener(p) && p !== 'children';
  8. Object.keys(props).forEach(p => {
  9. if (isAttribute(p)) element[p] = props[p];
  10. if (!isTextElement && isListener(p))
  11. element.addEventListener(p.toLowerCase().slice(2), props[p]);
  12. });
  13. if (!isTextElement && props.children && props.children.length)
  14. props.children.forEach(childElement =>
  15. renderElement(childElement, element)
  16. );
  17. container.appendChild(element);
  18. };
  19. // 例子
  20. const myElement = {
  21. type: 'button',
  22. props: {
  23. type: 'button',
  24. className: 'btn',
  25. onClick: () => alert('Clicked'),
  26. children: [{ props: { nodeValue: 'Click me' } }]
  27. }
  28. };
  29. renderElement(myElement, document.body);

添加多个监听

  1. const addMultipleListeners = (el, types, listener, options, useCapture) => {
  2. types.forEach(type =>
  3. el.addEventListener(type, listener, options, useCapture)
  4. );
  5. };
  6. // 例子
  7. addMultipleListeners(
  8. document.querySelector('.my-element'),
  9. ['click', 'mousedown'],
  10. () => { console.log('hello!') }
  11. );

仅监听一次

  1. const listenOnce = (el, evt, fn) =>
  2. el.addEventListener(evt, fn, { once: true });
  3. // 例子
  4. listenOnce(
  5. document.getElementById('my-id'),
  6. 'click',
  7. () => console.log('Hello world')
  8. ); // 'Hello world' will only be logged on the first click

停止滚动监听

  1. const onScrollStop = callback => {
  2. let isScrolling;
  3. window.addEventListener(
  4. 'scroll',
  5. e => {
  6. clearTimeout(isScrolling);
  7. isScrolling = setTimeout(() => {
  8. callback();
  9. }, 150);
  10. },
  11. false
  12. );
  13. };
  14. // 例子
  15. onScrollStop(() => {
  16. console.log('The user has stopped scrolling');
  17. });

点击指定元素范围外执行回调

  1. const onClickOutside = (element, callback) => {
  2. document.addEventListener('click', e => {
  3. if (!element.contains(e.target)) callback();
  4. });
  5. };
  6. // 例子
  7. onClickOutside('#my-element', () => console.log('Hello'));
  8. // Will log 'Hello' whenever the user clicks outside of #my-element

触发给定元素上的特定事件,可选传递自定义数据

  1. const triggerEvent = (el, eventType, detail) =>
  2. el.dispatchEvent(new CustomEvent(eventType, { detail }));
  3. // 例子
  4. triggerEvent(document.getElementById('myId'), 'click');
  5. triggerEvent(document.getElementById('myId'), 'click', { username: 'bob' });

获取元素到文档顶部的距离

  1. const getVerticalOffset = el => {
  2. let offset = el.offsetTop,
  3. _el = el;
  4. while (_el.offsetParent) {
  5. _el = _el.offsetParent;
  6. offset += _el.offsetTop;
  7. }
  8. return offset;
  9. };
  10. // 例子
  11. getVerticalOffset('.my-element'); // 120

检测元素是否在视图中可见

  1. const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
  2. const { top, left, bottom, right } = el.getBoundingClientRect();
  3. const { innerHeight, innerWidth } = window;
  4. return partiallyVisible
  5. ? ((top > 0 && top < innerHeight) ||
  6. (bottom > 0 && bottom < innerHeight)) &&
  7. ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))
  8. : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
  9. };
  10. // 例子
  11. // e.g. 100x100 viewport and a 10x10px element at position {top: -1, left: 0, bottom: 9, right: 10}
  12. elementIsVisibleInViewport(el); // false - (not fully visible)
  13. elementIsVisibleInViewport(el, true); // true - (partially visible)

全屏显示元素

  1. const fullscreen = (mode = true, el = 'body') =>
  2. mode
  3. ? document.querySelector(el).requestFullscreen()
  4. : document.exitFullscreen();
  5. // 例子
  6. fullscreen(); // Opens `body` in fullscreen mode
  7. fullscreen(false); // Exits fullscreen mode