h5空数据展示太频繁,抽成组件不太灵活,试试动态挂载

60 阅读1分钟

几乎每个h5页面都要有空数据展示逻辑,一个个写又太耗费时间。

组件 - 不灵活版本

<template>
  <div class="empty-page">
    <div class="empty-wrapper">
      <div class="img-wrapper">
        <img :src="url" />
        <p class="empty-text">{{ text }}</p>
        <!-- 补充说明 -->
        <p v-if="descText" class="empty-desc">{{ descText }}</p>
        <!-- 按钮 -->
      </div>
      <div class="btn-wrapper" v-if="btn">
        <van-button class="empty-btn" size="small" type="primary" @click="onClick">{{ btn }}</van-button>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  components: {},
  props: {
    // 类型
    emptyType: {
      type: String,
      default: 'noData'
    },
    // 图片地址
    imgUrl: {
      type: String,
      default: ''
    },
    // 描述
    emptyText: {
      type: String,
      default: ''
    },
    // 描述补充
    emptyDescText: {
      type: String,
      default: ''
    },
    // 按钮文案
    btnText: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      emptyTypeToImgMap: {
        // 暂无内容
        noData: {
          img: require('@/assets/images/empty/noData.png'),
          text: '暂无内容'
        },
        // 加载失败
        loadFail: {
          img: require('@/assets/images/empty/loadFail.png'),
          text: '加载失败',
          descText: '请稍后重试~',
          btn: '重试'
        },
        // 服务器异常
        serverError: {
          img: require('@/assets/images/empty/serverError.png'),
          text: '服务器异常',
          descText: '网络连接失败,请检查网络后重试~',
          btn: '刷新'
        },
        // 网络异常
        networkError: {
          img: require('@/assets/images/empty/networkError.png'),
          text: '网络异常',
          descText: '正在抢修,请稍后刷新试试~',
          btn: '重试'
        }
      }
    }
  },
  computed: {
    url() {
      return this.imgUrl || this.emptyTypeToImgMap[this.emptyType].img
    },
    text() {
      return this.description || this.emptyTypeToImgMap[this.emptyType].text
    },
    descText() {
      return this.btnText || this.emptyTypeToImgMap[this.emptyType].descText
    },
    btn() {
      return this.btnText || this.emptyTypeToImgMap[this.emptyType].btn
    }
  },
  watch: {},
  created() {},
  mounted() {},
  methods: {
    onClick() {
      this.$emit('click')
    }
  }
}
</script>

动态挂载,直接使用

Exception.vue

<template>
  <!-- 异常内容区域 -->
  <div class="exception_ctt">
    <div>
      <!-- 根据type显示不同的图片 -->
      <img src="@/assets/images/new_empty.png" v-if="type === 'emptyData'" />
      <img src="@/assets/images/loadFail.png" v-if="type === 'loadFail'" />
      <img src="@/assets/images/serverError.png" v-if="type === 'serverError'" />
      <!-- 如果text1存在,则显示text1内容 -->
      <div class="text1" v-if="text1">{{ text1 }}</div>
      <!-- 如果text2存在,则显示text2内容 -->
      <div class="text2" v-if="text2">{{ text2 }}</div>
      <!-- 如果reloadText存在,则显示重载按钮 -->
      <div class="reload" v-if="reloadText" @click="toReload">{{ reloadText }}</div>
    </div>
  </div>
</template>

<script>
export default {
  name: 'StarryDialog',
  data() {
    return {
      // type表示异常类型
      type: '',
      // text1用于显示第一行文本信息
      text1: '',
      // text2用于显示第二行文本信息
      text2: '',
      // reloadText用于显示重载按钮的文本
      reloadText: ''
    }
  },
  created() {},
  methods: {
    /**
     * 重载方法
     * 当用户点击重载按钮时调用此方法
     * 触发onReload回调函数,如果存在的话
     */
    toReload() {
      this.onReload && this.onReload()
    }
  }
}
</script>

exception.js

主要流程:

// 导入Vue和异常组件
import Vue from 'vue'
import Exception from '@/components/Exception.vue'

// 1. 创建组件实例 (实例化通过 extend 生成的构造器)
const ExceptionConstructor = Vue.extend(Exception)

/**
 * 在指定的DOM元素中渲染异常组件
 * @param {HTMLElement} dom - 要渲染异常组件的DOM元素如果不需要添加到DOM树中,则可以省略
 * @param {Object} data - 传递给异常组件的数据
 */
const exception = (dom, data) => {
  // 创建一个新的异常组件实例,指定DOM元素和数据
  const newDom = new ExceptionConstructor({
    el: document.createElement('div'),// 2. 创建挂载锚点 
    data() {
      return data
    }// 3. 注入响应式数据
  })
  
  // 4. 手动 DOM 操作挂载。
  // 如果提供了DOM元素,则清空其内容并appendChild新的异常组件DOM元素
  if (dom) {
    dom.innerHTML = ''          // 清空容器
    dom.appendChild(newDom.$el) // 插入组件 DOM
  }
}

// 导出异常组件渲染函数
export default exception

使用:

要有一个div来接收

 <div ref="exceptionRef"/> 
loadError() {
      this.exceptionFlag = true
      this.$nextTick(() => {
        this.showException(this.$refs.exceptionRef, {
          type: 'loadFail',
          text1: '加载失败',
          text2: '请稍后重试~',
          reloadText: '重试',
          onReload: this.onRefresh
        })
      })
    }