likes
comments
collection
share

使用 Vue中extends选项 扩展 Element image-viewer 组件

作者站长头像
站长
· 阅读数 52

背景

有一天,领导和我说,在使用 table 表格展示图片记录的基础上加上以下功能:

  1. 当点击单元格图片项时,在图片预览的时候将图片的编号加上
  2. 按下键盘上下键时,切换不同的图片记录项
  3. 按下键盘左右键时,切换当前图片记录项的图片 内心:啊这,领导你知道我们使用的是 element 的组件么,提供的组件根本没这功能啊,是想让我自己实现一个么.... 啊这,还是学习看看有没有啥方法能改写 element 组件更快吧.....

实现思路

  1. 点击图片时,生成并添加图片编号至预览界面
  2. 使用 extends扩展 image-viewer组件,重写方法覆盖image-viewer 监听键盘按下上下按键事件方法
  3. 监听键盘按下上下按键事件,更换正确的图片预览地址数组数据

实现过程中遇到的问题

  • 问题: 当上一记录存在多张图片且切换到了该记录的第二张图片以后,再切换到下一记录时,组件会报错找不到元素
  • 原因:image-viewer组件中的 index未正确设置
  • 解决办法: 在 CustomerImageViewer 当预览地址发生改变时,改变 index 的值
watch: {
  urlList(){
    this.index = 0;
  }
},

总结

主要用了 vueextends 选项来继承另外一个组件,然后重写该内部的方法,以达成我们自己的需求。在继承组件时,需要将该组件引入的依赖一并引入

代码实现

CustomerImageViewer.vue

import ElImageViewer from 'element-ui/packages/image/src/image-viewer';
import { on, off } from 'element-ui/src/utils/dom';
import { rafThrottle, isFirefox } from 'element-ui/src/utils/util';
import { PopupManager } from 'element-ui/src/utils/popup';
const mousewheelEventName = isFirefox() ? 'DOMMouseScroll' : 'mousewheel';
export default {
  name: 'Customer-image-viewer',
  extends: ElImageViewer,
  watch: {
    urlList(){
      this.index = 0;
    }
  },
  methods: {
    deviceSupportInstall() {
      this._keyDownHandler = e => {
        e.stopPropagation();
        const keyCode = e.keyCode;
        switch (keyCode) {
          // ESC
          case 27:
            this.hide();
            break;
          // SPACE
          case 32:
            this.toggleMode();
            break;
          // LEFT_ARROW
          case 37:
            this.prev();
            break;
          // RIGHT_ARROW
          case 39:
            this.next();
            break;
        }
      };
      this._mouseWheelHandler = rafThrottle(e => {
        const delta = e.wheelDelta ? e.wheelDelta : -e.detail;
        if (delta > 0) {
          this.handleActions('zoomIn', {
            zoomRate: 0.015,
            enableTransition: false
          });
        } else {
          this.handleActions('zoomOut', {
            zoomRate: 0.015,
            enableTransition: false
          });
        }
      });
      on(document, 'keydown', this._keyDownHandler);
      on(document, mousewheelEventName, this._mouseWheelHandler);
    },
  },
};

Table.vue

<template>
  <div class="view-page">
    <div class="view-body">
      <el-table :data="dataList">
        ...
        <el-table-column label="图片" width="100" align="center">
          <template slot-scope="{ row }">
            <el-image @click="imgClickHandle(row)" :src="row.cover" style="width: 40px; height: 40px;cursor: pointer" ></el-image>
          </template>
        </el-table-column>
      </el-table>
      <customer-image-viewer
        ref="imgViewer"
        v-if="showViewer"
        :initial-index="initialIndex"
        :on-close="onClose"
        :url-list="previewSrcList"
      />
    </div>
  </div>
</template>

<script>
import { getDataList } from '@/service';

import CustomerImageViewer from '@components/Customer-image-viewer';

export default {
  name: 'TableList',
  components: { CustomerImageViewer},
  data() {
    return {
      dataList: [],
      previewSrcList: [],
      
      showViewer: false,
      initialIndex: 0,
      divDom: null,
      indexMap: {},
      // 用来记录选中了哪一记录的 index, 用于查询
      imgIndex: 0
    };
  },
  created() {
    document.addEventListener('keyup', this.handleKeyup);
  },
  mounted(){
   this.loadDataList();
  },
  methods: {
    // 键盘监听事件
    handleKeyup(event){
      const e = event ;
      if (!e) return;
      const { key, keyCode } = e;
      switch (keyCode) {
        // UP_ARROW
        case 38:
          this.imgIndex = this.imgIndex > 0 ? (this.imgIndex - 1) : (this.dataList.length - 1) ;
          break;
        // DOWN_ARROW
        case 40:
          this.imgIndex = this.imgIndex < this.dataList.length - 1 ? (this.imgIndex + 1) : 0 ;
      }
      const no = this.dataList[this.imgIndex].no;
      this.divDom && (this.divDom.innerText = '编号:' + no);
      this.previewSrcList = this.indexMap[this.imgIndex];
    },

    async loadDataList() {
      const res = await getDataList();
      if (!res) return;
      const list = res.list || [];
      list.map((item, index) => item.index = index);
      this.dataList = list;
      const indexMap = {};
      list.forEach((item, index) => {
        indexMap[index] = item.photos;
      });
      this.indexMap = indexMap;
    },

    imgClickHandle({ index, no }){
      this.showViewer = true;
      this.imgIndex = index;
      // 获取图片预览地址
      this.previewSrcList = this.indexMap[index];
      this.$nextTick(() => {
        // 生成并添加图片编号至预览界面
        const divDom = document.createElement('div');
        const parentDom = document.getElementsByClassName('el-image-viewer__wrapper')[0];
        divDom.innerText = '编号:' + no;
        divDom.className = 'no-class';
        parentDom.appendChild(divDom);
        this.divDom = divDom;
      });
    },
    // 关闭图片预览
    onClose() {
      this.showViewer = false;
      this.divDom = null;
    },
  },
  destroyed() {
    document.removeEventListener('keyup', this.handleKeyup);
  }
};
</script>

完结撒花

转载自:https://juejin.cn/post/7100845825122631687
评论
请登录