Skip to content

原生 js - showLoading 显示加载中


loading

参数

  • textOrOptions: string | Object - 加载提示文本或配置选项

  • options: Object - 配置选项

  • text: string - 加载提示文本,默认'加载中...'

  • fullscreen: boolean - 是否全屏显示,默认 true

  • background: string - 遮罩背景色,默认'rgba(0, 0, 0, 0.7)'

  • target: HTMLElement - 遮罩挂载的目标元素,在非全屏模式下生效

  • lock: boolean - 是否锁定屏幕滚动,默认 false

返回值

  • Function - 关闭 loading 的函数

使用示例

javascript
// 基础用法

const closeLoading = showLoading()

// 关闭loading

closeLoading()

// 在指定元素上显示loading

const el = document.querySelector('.container')

showLoading({
  target: el,

  fullscreen: false,

  text: '加载中...'
})

源码

源码
js
/**
 * 显示/关闭加载中遮罩层
 * @author chuxiao
 * @param {string|Object} textOrOptions - 加载提示文本或配置选项
 * @param {Object} [options={}] - 配置选项
 * @param {string} [options.text='加载中...'] - 加载提示文本
 * @param {boolean} [options.fullscreen=true] - 是否全屏显示
 * @param {string} [options.background='rgba(0, 0, 0, 0.7)'] - 遮罩背景色
 * @param {HTMLElement} [options.target] - 遮罩挂载的目标元素,在非全屏模式下生效
 * @param {boolean} [options.lock=false] - 是否锁定屏幕滚动
 * @returns {Function} 关闭loading的函数
 * 
 * @example
 * // 基础用法-显示全屏loading
 * const closeLoading = showLoading();
 * // 关闭loading
 * closeLoading();
 * 
 * // 显示带文本的loading
 * showLoading('数据加载中...');
 * 
 * // 在指定元素上显示loading
 * const el = document.querySelector('.container');
 * showLoading({
 *   target: el,
 *   fullscreen: false,
 *   text: '加载中...'
 * });
 */
function showLoading(textOrOptions, options = {}) {
  let text, finalOptions;
  
  if(typeof textOrOptions === 'string') {
    text = textOrOptions;
    finalOptions = options;
  } else if(textOrOptions) {
    text = textOrOptions.text;
    finalOptions = textOrOptions;
  } else {
    text = '加载中...';
    finalOptions = options;
  }

  const {
    fullscreen = true,
    background = 'rgba(0, 0, 0, 0.7)',
    target = document.body,
    lock = false
  } = finalOptions;

  // 创建loading容器
  const loadingContainer = document.createElement('div');
  loadingContainer.className = 'el-loading-mask';
  loadingContainer.style.cssText = `
    position: ${fullscreen ? 'fixed' : 'absolute'};
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: ${background};
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    transition: opacity 0.3s;
    z-index: 2000;
  `;

  // 创建loading图标
  const spinner = document.createElement('div');
  spinner.className = 'el-loading-spinner';
  spinner.innerHTML = `
    <svg class="circular" viewBox="25 25 50 50">
      <circle class="path" cx="50" cy="50" r="20" fill="none"/>
    </svg>
  `;

  // 添加loading文本
  if(text) {
    const textEl = document.createElement('p');
    textEl.className = 'el-loading-text';
    textEl.textContent = text;
    textEl.style.cssText = `
      margin: 3px 0 0;
      color: #409eff;
      font-size: 14px;
    `;
    spinner.appendChild(textEl);
  }

  loadingContainer.appendChild(spinner);

  // 添加样式
  const style = document.createElement('style');
  style.textContent = `
    .el-loading-spinner {
      display: flex;
      flex-direction: column;
      align-items: center;
    }
    .circular {
      width: 42px;
      height: 42px;
      animation: loading-rotate 2s linear infinite;
    }
    .path {
      stroke-dasharray: 90,150;
      stroke-dashoffset: 0;
      stroke-width: 2;
      stroke: #409eff;
      stroke-linecap: round;
      animation: loading-dash 1.5s ease-in-out infinite;
    }
    @keyframes loading-rotate {
      100% {
        transform: rotate(360deg);
      }
    }
    @keyframes loading-dash {
      0% {
        stroke-dasharray: 1,200;
        stroke-dashoffset: 0;
      }
      50% {
        stroke-dasharray: 90,150;
        stroke-dashoffset: -40px;
      }
      100% {
        stroke-dasharray: 90,150;
        stroke-dashoffset: -120px;
      }
    }
  `;
  document.head.appendChild(style);

  // 锁定滚动
  if(lock) {
    document.body.style.overflow = 'hidden';
  }

  // 添加到目标元素
  if(!fullscreen && target !== document.body) {
    if(getComputedStyle(target).position === 'static') {
      target.style.position = 'relative';
    }
  }
  target.appendChild(loadingContainer);

  // 关闭loading的函数
  const close = () => {
    loadingContainer.style.opacity = '0';
    setTimeout(() => {
      target.removeChild(loadingContainer);
      document.head.removeChild(style);
      if(lock) {
        document.body.style.overflow = '';
      }
    }, 300);
  };

  return close;
}

Released under the MIT License.