使用dom扩展第三方组件来满足业务需求

前言

在日常的开发中,我们偶尔会遇到一些我们使用组件库不能实现的业务场景。这篇文章就是跟大家分享一下,我遇到的业务场景及解决的方法,给大家提供一个思路。

业务场景

具体的业务场景是一个选人的下拉列表,这个下拉列表要支持多选和搜索功能。这个需求还是挺常见的,并且element-ui的select提供了对应的属性可供我们完成多选及搜索的效果。于是我就欻欻欻的实现了一个,实现效果如下。(搜索功能就是在select框内输入对应的人名或者手机号,这里先不展示,主要看选中之后的效果)

使用dom扩展第三方组件来满足业务需求

产品看完不满意,说你这选完人之后那么大空白呢,为什么不多展示一个人名。并且你这+1 +2 +3的不好看,给我显示成等n人的形式。下面是产品期望的效果

使用dom扩展第三方组件来满足业务需求

我刚开始没当回事,element-ui这么强大的组件库是吧。这种场景应该挺常见的,应该提供了对应的api,我查查改改不完事了。我就去找了找,然后发现杯具了。

使用dom扩展第三方组件来满足业务需求

这组件库就提供了collapse-tags这玩意,要不就全展示,要不就展示一个后面跟个+n,完了巴比Q了。

摆在我面前有两条路可走:

  1. 解决不了问题就从提出问题的人下手(doge)

这些组件库不能满足的业务场景,往往是为了更好的用户体验提出的,一般对主流程不是那么必要。所以可以用自己出色的口才和产品谈一谈。很不幸我失败了,然后走第二条了

  1. 只能想办法克服困难了。。。

直接使用原生重写一个可以满足该功能的组件,成本略高暂不考虑。

那就在原有的el-select基础上改写,直接操作它的dom节点达成目的。

解决方案

由于没撕过产品,我们采用操作dom,使用js和css改变原来第三方的视觉效果来实现达到目标。

collapse-tags属性只能展示一个内容,并且选择多个+1 +2这种展示不符合我们的要求,在collapse-tags属性的基础上改造比较困难,所以我们要去掉collapse-tags属性。

使用dom扩展第三方组件来满足业务需求

去掉以后会展示多行,我们的目标是一行展示两个,多余的展示等n人。首先我们要通过css的方式让选中的第三个及以后的元素不显示到页面上。

我们来观察一下dom元素

使用dom扩展第三方组件来满足业务需求

经过观察我们可知,页面上的人员姓名的dom元素的类名是el-tag el-tag--info。我们可以使用选择器让第二个的元素添加dispaly:none不展示到页面上。

.el-tag.el-tag--info:nth-child(n+3){
    display:none
}

使用dom扩展第三方组件来满足业务需求

可以看到加上css后,第三个元素开始都隐藏起来了。接下来我们要向el-select内部插入一个dom来实现我们想要的文本。

    this.dom = document.createElement('span')
    this.dom.style.cssText = `
    background-color: #f4f4f5;
    border-color: #e9e9eb;
    color: #909399;
    height: 24px;
    padding: 0 8px;
    line-height: 22px;
    display:inline-block;
    border-radius: 4px;
    position: absolute;
     top: 50%;
     transform: translateY(-50%);
     right: 5px;
    `
    this.dom.innerText = `等5人`
    // this.$refs.select.$el 为el-select的真实dom
    this.$refs.select.$el.appendChild(this.dom)

使用dom扩展第三方组件来满足业务需求

创建一个<span>,根据element-ui原有的样式进行还原,再加上我们想要的文案即可,当然写死是不行的,下面我们来完善逻辑。当页面初始化的时候根据父组件是否有值,如果有值就说明需要回显,根据父组件传递的userId数组可以判断出选择的数量,根据数量动态展示或隐藏<span>

当触发el-selectchange事件时也要根据选中的数量对<span>的展示做对应的逻辑

  // 展示几个人
  const showPersonsCount = 2
  mounted() {
    this.dom = document.createElement('span')
    this.dom.style.cssText = `
    background-color: #f4f4f5;
    border-color: #e9e9eb;
    color: #909399;
    height: 24px;
    padding: 0 8px;
    line-height: 22px;
    display:inline-block;
    border-radius: 4px;
    position: absolute;
     top: 50%;
     transform: translateY(-50%);
     right: 5px;
    `
    // value为父元素传递过来,用于回显的值。本例中value为userid的数组
    if (this.value && this.value.length > showPersonsCount) {
      this.dom.style.display = 'inline-block'
      this.dom.innerText = `等${this.value.length}人`
    } else {
      this.dom.style.display = 'none'
    }
    this.$refs.select.$el.appendChild(this.dom)
  },
  
// el-select的change事件
handleChange(newValue) {
  if (newValue.length > showPersonsCount) {
    this.dom.style.display = 'inline-block'
    this.dom.innerText = `等${newValue.length}人`
  } else {
    this.dom.style.display = 'none'
  }
  this.$emit('input', newValue)
}

使用dom扩展第三方组件来满足业务需求

到此为止就实现了我们想要的功能。具体的代码还存在优化的空间,主要是给大家介绍一个思路。

结尾

使用vue/react多了,我们渐渐的忘记了使用原生dom的方法。今天分享的这种使用原生dom拓展第三方组件的方法,希望能作为大家以后开发的一个思路。让大家能够低成本的完成业务需求。

希望大家都能有所收获!

原文链接:https://juejin.cn/post/7321596167584923684 作者:欲买炸鸡同载可乐

(0)
上一篇 2024年1月9日 上午10:42
下一篇 2024年1月9日 上午10:52

相关推荐

发表回复

登录后才能评论