美文网首页
Element-UI使用及遇到的问题

Element-UI使用及遇到的问题

作者: 浅忆_0810 | 来源:发表于2021-12-21 16:08 被阅读0次

1. el-tooltip 超出宽度显示文字提示,否则隐藏

<!-- 第一种方法 -->
<template>
  <div class="menu-item-container">
    <el-tooltip :content="contentHover" placement="right" :disabled="isShowTooltip">
      <p class="title-container" @mouseover="onMouseOver(title)">
        <span class="menu-title" :ref="title">{{ title }}</span>
      </p>
    </el-tooltip>
  </div>
</template>

<script>
  export default {
    name: 'MenuItem',
    props: {
      title: String
    },
    data() {
      return {
        isShowTooltip: false,
        contentHover: ''
      };
    },
    methods: {
      /**
       * 鼠标移入事件
       * @param {title} ref 的 title 值
       */
      onMouseOver(title) {
        const el = this.$refs[title];
        const parentWidth = el.parentNode.offsetWidth; // 获取元素父级可视宽度
        const contentWidth = el.offsetWidth; // 获取元素可视宽度
        this.isShowTooltip = contentWidth <= parentWidth; 
        // 鼠标悬停后显示的内容
        this.contentHover = title;
      }
    }
  }
</script>

<style scoped>
  .title-container {
    overflow: hidden;
    width: 100%;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
</style>
<!-- 第二种方法 解决 el-autocomplete中 搜索列表 tooltip进入下一项闪烁问题 -->
<template>
  <el-autocomplete class="inline-input" placeholder="搜索">
    <template slot-scope="{ item }">
      <el-tooltip :content="item.title" placement="right" :disabled="isShowTooltip">
        <p class="ellispis" @mouseover="onMouseOver($event)">{{ item.title }}</p>
      </el-tooltip>
    </template>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        isShowTooltip: true,
        contentHover: ''
      };
    },
    methods: {
      // 鼠标移入事件
      onMouseOver(e) {
        const el = e.target;
        // scrollWidth: 对象的实际内容的宽度,不包括边线宽度,会随对象中内容超过可视区后而变大
        // offsetWidth: 对象整体的实际宽度,包括滚动条等边线,会随对象显示大小的变化而改变
        this.isShowTooltip = el.scrollWidth <= el.offsetWidth; 
      }
    }
  }
</script>

<style lang="less">
  .ellispis {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .el-tooltip__popper {
    top: -100px; // 解决 tooltip与非tooltip来回切换,左上角会闪现tooltip弹框
  }
</style>

2. 使用阿里乾坤等微前端嵌入Element-UI弹出框页面时

2.1 改变Popover 弹出框样式在微前端中不生效

原因:Popover默认是插入到body元素上的,此时得修改成插入到父级元素中

<template>
  <el-popover
    :append-to-body="false"
    placement="bottom"
    width="200"
    trigger="click"
    :popper-options="popperOptions"
  >
    <el-button ref="popRef" slot="reference">click 激活</el-button>
    <p>内容</p>
  </el-popover>
</template>

当插入到父元素后悔发现原本的弹框边界悔自动变换位置的特性失效了

解决办法:设置popper-options中的boundariesElement为边界判定的HTMLElement元素

<script>
export default {
  data() {
    return {
      popperOptions: {
        boundariesElement: 'body',
        gpuAcceleration: false
      }
    }
  },
  mounted() {
    // 这里尝试后发现 第一个 offsetParent 值必须为边界容器,否则不生效,具体原因不清楚,欢迎大佬解答
    this.popperOptions.boundariesElement = this.$refs.moreImg.offsetParent
  }
}
</script>

2.2 当把el-dialog中的modal-append-to-bodyappend-to-body都设为false时,关闭弹框时,遮罩层挡住问题

解决办法:控制v-modalhidden属性来显示隐藏遮罩层

<template>
  <div ref="dialogContainer">
    <el-dialog
      :visible.sync="dialog.visible"
      width="30%"
      :modal-append-to-body="false"
      :append-to-body="false"
      @open="haddleDia(true)"
      @close="haddleDia(false)"
    ></el-dialog>
  </div>
</template>

<script>
export default {
  data() {
    return {
      dialog: {
        visible: false
      }
    }
  },
  methods: {
    haddleDia(bool) {
      this.dialog.visible = bool
      this.$refs.dialogContainer.lastChild.hidden = !bool
    }
  }
}
</script>

3. el-table相关问题

3.1 自定义expand展开收缩

<template>
  <el-table ref="table" :data="tableData">
    <template v-for="(header, i) in headerList">
      <el-table-column
        :key="i"
        :prop="header.prop"
        :label="header.label"
        :width="header.width || 'auto'"
      />
    </template>
    <el-table-column label="操作" width="120">
      <template slot-scope="scope">
        <p class="btn" @click="toogleExpand(scope.row)">查看详情</p>
      </template>
    </el-table-column>
    <el-table-column type="expand" width="1">
      <template slot-scope="props">
        详情内容
      </template>
    </el-table-column>
  </el-table>
</template>

<script>
export default {
  data() {
    return {
      headerList: [
        { prop: 'name', label: '姓名' },
        { prop: 'time', label: '时间' }
      ]
    }
  },
  methods: {
    toogleExpand(row) {
      this.$refs.table.toggleRowExpansion(row)
    }
  }
}
</script>

3.2 自定义filter筛选图标和内容

<template>
  <el-table ref="table" :data="tableData">
    <el-table-column width="108">
      <template slot="header">
        <el-popover placement="bottom-start" trigger="click">
          <p slot="reference">
            <span>分类</span>
            <img src="">
          </p>
        </el-popover>
      </template>
      <template slot-scope="scope">
        <p>表格body内容</p>
      </template>
    </el-table-column>
  </el-table>
</template>

<style lang="scss">
  .el-table {
    .el-table__header-wrapper {
      overflow: initial;
      thead {
        th.el-table__cell,
        .cell {
          overflow: initial;
        }
      }
    }
  }
</style>

3.3. el-date-picker设置时间跨度

<template>
  <el-date-picker
    v-model="timeRange"
    type="daterange"
    start-placeholder="开始日期"
    end-placeholder="结束日期"
    value-format="yyyy-MM-dd"
    :picker-options="pickerOptions"
  ></el-date-picker>
</template>

<script>
export default {
  data() {
    return {
      timeRange: '',
      timeOptionRange: '',
      pickerOptions: {
        disabledDate: (time) => {
          // 选择时间不能小于当天
          if (time.getTime() < Date.now() - 8.64e7) {
            return true;
          }

          // 最长跨度为 180 天
          const maxNum = 60 * 60 * 24 * 1000 * 179;
          // 最短为 2 天
          const minNum = 60 * 60 * 24 * 1000 * 2

          if (this.timeOptionRange) {
            const maxLongTime = this.timeOptionRange + maxNum
            const minLongTime = this.timeOptionRange - maxNum

            const maxShortTime = this.timeOptionRange + minNum
            const minShortTime = this.timeOptionRange - minNum

            return (time.getTime() > maxLongTime || time.getTime() < minLongTime) || (time.getTime() > minShortTime && time.getTime() < maxShortTime);
          }
        },
        onPick: ({ minDate, maxDate }) => {
          // 当第一时间选中才设置禁用
          if (minDate && !maxDate) {
            this.timeOptionRange = minDate.getTime();
          }
          if (maxDate) {
            this.timeOptionRange = null;
          }
        }
      }
    }
  }
}
</script>

3.4 el-treeel-select结合实现树状多选

<!-- child.vue -->
<template>
  <div class="select-tree-container">
    <el-popover
      placement="bottom-start"
      popper-class="select-tree-popper"
      v-model="isShowSelect"
      @hide="closePopver"
    >
      <!-- 筛选框 -->
      <el-input v-if="filterable" v-model="filterText" size="mini" suffix-icon="el-icon-search"></el-input>

      <el-tree
        class="common-tree"
        ref="tree"
        :data="treeData"
        node-key="id"
        :default-expand-all="true"
        :expand-on-click-node="false"
        :check-on-click-node="true"
        show-checkbox
        :filter-node-method="filterNode"
        :default-expanded-keys="defaultKey"
        @check-change="nodeClick"
        @node-click="nodeClick"
      ></el-tree>

      <el-select
        slot="reference"
        ref="select"
        v-model="selectVal"
        multiple
        @remove-tag="removeTag"
      >
        <el-option
          v-for="item in options"
          :key="item.value"
          :label="item.label"
          :value="item.value"
        ></el-option>
      </el-select>
      <!-- 全选按钮 -->
      <div v-if="selectAll">
        <el-checkbox
          v-model="checkedAll"
          :indeterminate="selectVal.length === 0 ? false : !checkedAll"
          @change="selectedAll"
        >全选</el-checkbox>
      </div>
    </el-popover>
  </div>
</template>
 
<script>
export default {
  name: 'SelectTree',
  props: {
    // 全选
    selectAll: {
      type: Boolean,
      default() {
        return false;
      },
    },
    // 树结构数据
    treeData: {
      type: Array,
      default() {
        return [];
      },
    },
    // 配置是否可以搜索
    filterable: {
      type: Boolean,
      default() {
        return false;
      },
    },
    // 默认选中的节点key
    defaultKey: {
      type: Array,
      default() {
        return [];
      },
    }
  },

  //上面是父组件可传入参数
  data() {
    return {
      isShowSelect: false, // 是否显示树状选择器
      options: [],
      returnDatas: [], // 返回给父组件数组对象
      selectVal: [],
      filterText: "", // 筛选绑定值
      checkedAll: false, // 是否全选
      treeArrId: [] // 记录所有节点id,用于判断是否全选
    }
  },
  created () {
    this.treeArrId = this.originTreeArrId(this.treeData)
  },
  mounted() {
    if (this.defaultKey.length) {
      this.setKeys(this.defaultKey)
    }
  },
  watch: {
    selectVal(newValue, oldValue) {
      this.checkedAll = newValue.length === this.treeArrId.length;
    },
    filterText(val) {
      this.$refs.tree.filter(val);
    },
    // 隐藏select自带的下拉框
    isShowSelect() {
      this.$refs.select.blur();
    }
  },
  methods: {
    // 记录所有节点id
    originTreeArrId(treeData) {
      let treeArrId = []
      treeData.forEach(data => {
        treeArrId.push(data.id)
        if (data.children && data.children.length) {
          treeArrId.push(...this.originTreeArrId(data.children))
        }
      })

      return treeArrId
    },
    // 节点被点击
    nodeClick() {
      var checkedKeys = this.$refs.tree.getCheckedKeys(true); // 所有被选中的叶子节点的 key 所组成的数组数据
      this.returnDatas = []

      this.options = checkedKeys.map(item => {
        let node = this.$refs.tree.getNode(item); // 所有被选中的节点对应的node
        this.returnDatas.push(node.data);

        // 设置option选项
        return { 
          label: node.label, 
          value: node.key 
        }
      })

      this.selectVal = this.options.map(item => item.value)
      this.closePopver()
    },
    // 设置 or 初始化选中值
    setKeys(checkedKeys) {
      this.$refs.tree.setCheckedKeys(checkedKeys) // 通过 keys 设置目前勾选的节点
      this.selectVal = checkedKeys;
      let dataArr = [];
      checkedKeys.forEach(item => {
        let node = this.$refs.tree.getNode(item); // 获取节点对应的node
        dataArr.push(node.data);
      });
      this.returnDatas = dataArr;
    },
    // 删除任一 select 选项
    removeTag(val) {
      this.$refs.tree.setChecked(val, false); // 设置节点的勾选状态为未选中
      let node = this.$refs.tree.getNode(val); // 获取节点
      if (node.childNodes.length) {
        // 如果去掉的为父节点,则将下面的子节点勾选状态也去掉
        this.getChildrenList(node).forEach(item => {
          this.$refs.tree.setChecked(item, false);
        })
      }
      this.nodeClick()
    },
    // 全选
    selectedAll(val) {
      val
        ? this.setKeys(this.treeArrId)
        : this.clearSelectedNodes()
    },
    // 对节点进行过滤
    filterNode(value, data) {
      if (!value) return true

      return data.label.includes(value)
    },
    // 清空所有勾选
    clearSelectedNodes() {
      let checkedKeys = this.$refs.tree.getCheckedKeys(true) // 所有被选中的节点的 key 所组成的数组数据
      for (let i = 0, len = checkedKeys.length; i < len; i++) {
        this.$refs.tree.setChecked(checkedKeys[i], false)
      }
    },
    // 下拉框关闭
    closePopver() {
      this.$emit("get:value", this.selectVal, this.returnDatas);
    },
    // 递归将所有子节点取出
    getChildrenList(tree) {
      const childNodes = []
      tree.childNodes.forEach(child => {
        childNodes.push(child)

        if (child.childNodes.length) {
          childNodes.push(...this.getChildrenList(child))
        }
      })

      return childNodes
    }
  }
};
</script>
 
<style lang="scss">
  .select-tree-container {
    .el-select {
      width: 280px;
    }
  }

  .select-tree-popper {
    box-sizing: border-box;
    width: 280px;

    // 隐藏下拉箭头
    .el-tree-node__content>.el-tree-node__expand-icon {
      display: none;
    }
  }
</style>
<!-- father.vue -->
<template>
  <div class="app-container">
    <select-tree
      filterable
      select-all
      :tree-data="treeData"
      :defaultKey="defaultCheckedKeys"
      @get:value="getTreeVal"
    />
  </div>
</template>

<script>
import SelectTree from '@/components/SelectTree.vue';

export default {
  components: { SelectTree },
  name: "App",
  data() {
    return {
      treeData: [
        {
          id: 1,
          label: "水果",
          children: [
            { id: 4, label: '香蕉' },
            { id: 5, label: '圣女果' }
          ]
        },
        {
          id: 2,
          label: "食物",
          children: [
            { id: 6, label: '龙虾' },
            { id: 7, label: '螃蟹' }
          ]
        }
      ],
      defaultCheckedKeys: [4, 5]
    }
  },
  methods: {
    getTreeVal(val, data) {
      console.log(val, data);
    }
  }
};
</script>

效果图:

相关文章

网友评论

      本文标题:Element-UI使用及遇到的问题

      本文链接:https://www.haomeiwen.com/subject/itioxrtx.html