Vue extends拓展任意组件功能(el-select实例)-两种写法_el-select 拓展-程序员宅基地

技术标签: Vue拓展组件功能  vue  Vue  Vue extend  

用到ElementUI的select组件,要求能够多选并且重复选择。如果直接使用的话,首先el-tag会报错,因为循环中key值重复;其次,他的移除是通过indexof搜索移除的tag的值,且在remove-tag事件中未抛出被移除tag的索引,这样的后果是存在多个相同值的tag时,只会移除第一个相同值的tag

思路

el-tag的循环中,给close事件增加一个参数index,然后重写deleteTag方法,直接通过index删除该tag

  1. Vue: @close="deleteTag($event, item)"
  2. JSX: on-close={e => this.deleteTag(e, this.selected[0])}
deleteTag(event, tag, tagIndex){
    
  const value = this.value.slice();
  value.splice(tagIndex, 1);// 核心代码,其他代码省略
}

写法一、Vue template(推荐)

非常简单,改动特别少,可以使用Vue的所有用法,只需要复制el-select的template

  1. 新建一个vue文件
  2. 复制el-select的template模板内容过来
  3. 导入el-select,继承
  4. 覆盖methods中的deleteTag

结果

<template>
  <div
    class="el-select"
    :class="[selectSize ? 'el-select--' + selectSize : '']"
    @click.stop="toggleMenu"
    v-clickoutside="handleClose">
    我是示例代码,此处为自定义模板内容
  </div>
</template>

<script>
  import {
     Select} from 'element-ui';
  export default {
    
    extends: Select,//继承
    name: 'my-el-select',
    methods: {
    
      deleteTag(event, tag, tagIndex) {
    
// 重写该方法
    },
  },
  };
</script>

写法二、JSX(比较麻烦)

需要手动将Vue template转为jsx写法,无法使用事件修饰符,部分指令等等,改动比较大

1、导入继承

import {
    Select} from 'element-ui';

const myElSelect = {
    
  extends: Select
}

2、 重写render

Vue template最终编译之后也是生成render函数,这里覆盖render函数,
生成自定义内容。此处的意义只是为了记录以便于方便我用render函数时的jsx写法

render()
{
    
    const tagContent = () => {
    
      if (this.collapseTags && this.selected.length) {
    
        const tag0 = (
          <el-tag
            closable={
    !this.selectDisabled}
            size={
    this.collapseTagSize}
            hit={
    this.selected[0].hitState}
            type='info'
            on-close={
    e => this.deleteTag(e, this.selected[0])}
            disable-transitions={
    true}>
            <span class='el-select__tags-text'>{
    this.selected[0].currentLabel}</span>
          </el-tag>
        );
        const tag1 = (
          <el-tag
            closable={
    false}
            size={
    this.collapseTagSize}
            type='info'
            disable-transitions={
    true}>
            <span class='el-select__tags-text'>+ {
    this.selected.length - 1}</span>
          </el-tag>
        );

        if (this.selected.length > 1) {
    
          return (
            <span>
              {
    tag0}
              {
    tag1}
            </span>
          );
        }
        return (
          <span>
            {
    tag0}
          </span>
        );
      }
    };
    const emptyText = () => {
    
      if (this.emptyText && (!this.allowCreate || this.loading || (this.allowCreate && this.options.length === 0))) {
    
        return (
          <p class='el-select-dropdown__empty'>{
    this.emptyText}</p>
        );
      }
    };
    const selectOption = () => {
    
      return (
        <transition
          name='el-zoom-in-top'
          on-before-enter={
    this.handleMenuEnter}
          on-after-leave={
    this.doDestroy}>
          <el-select-menu
            ref='popper'
            append-to-body={
    this.popperAppendToBody}
            v-show={
    this.visible && this.emptyText !== false}>
            <el-scrollbar
              tag='ul'
              wrap-class='el-select-dropdown__wrap'
              view-class='el-select-dropdown__list'
              ref='scrollbar'
              class={
    {
    'is-empty': !this.allowCreate && this.query && this.filteredOptionsCount === 0}}
              v-show={
    this.options.length > 0 && !this.loading}>
              {
    this.showNewOption ? (
                <el-option
                  value={
    this.query}
                  created={
    true}>
                </el-option>
              ) : null}
              {
    
                this.$slots.default
              }
            </el-scrollbar>
            {
    emptyText()}
          </el-select-menu>
        </transition>
      );
    };
    return (
      <div
        class={
    ['el-select', this.selectSize ? 'el-select--' + this.selectSize : '']}
        on-click={
    this.toggleMenu} v-clickoutside={
    this.handleClose}>
        <div
          class='el-select__tags'
          ref='tags'
          style={
    {
    'max-width': this.inputWidth - 32 + 'px'}}>
          {
    tagContent()}
          <transition-group onAfterLeave={
    this.resetInputHeight}>
            {
    this.selected.map((item, index) => {
    
              return (
                <el-tag
                  key={
    index}
                  closable={
    !this.selectDisabled}
                  size={
    this.collapseTagSize}
                  hit={
    item.hitState}
                  type='info'
                  on-close={
    (e) => this.deleteTag(e, item, index)}
                  disable-transitions={
    false}>
                  <span class='el-select__tags-text'>{
    item.currentLabel}</span>
                </el-tag>
              );
            })}
          </transition-group>
        </div>
        <el-input
          ref='reference'
          value={
    this.selectedLabel}
          type='text'
          placeholder={
    this.currentPlaceholder}
          name={
    this.name}
          id={
    this.id}
          auto-complete={
    this.autoComplete}
          size={
    this.selectSize}
          disabled={
    this.selectDisabled}
          readonly={
    this.readonly}
          validate-event={
    false}
          class={
    {
    'is-focus': this.visible}}
          on-focus={
    this.handleFocus}
          on-blur={
    this.handleBlur}
          on-keyup_native={
    this.debouncedOnInputChange}
          on-paste_native={
    this.debouncedOnInputChange}
          on-mouseenter_native={
    (this.inputHovering = true)}
          on-mouseleave_native={
    (this.inputHovering = false)}
        >
          <i slot='suffix'
             class={
    ['el-select__caret', 'el-input__icon', 'el-icon-' + this.iconClass]}
             on-click={
    () => this.handleIconClick}/>
        </el-input>
        {
    selectOption()}
      </div>
    );
  }

3、 重写method里的deleteTag方法

4、结果

import {
    Select} from 'element-ui';

const myElSelect = {
    
  extends: Select,
  methods: {
    
    deleteTag(event, tag, tagIndex) {
    
     // *****略
    },
  },
  render() {
    
    return (
      <div>例子</div>
    );
  }
};
export default myElSelect;
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_31201781/article/details/101427594

智能推荐

利用计算机的数字化技术和人机交换,数字摄影测量学习题-程序员宅基地

文章浏览阅读190次。数字摄影测量学习题与参考答案一、名词解释1、数字摄影测量:基于数字影像和摄影测量的基本原理,应用计算机技术、数字影像处理、影像匹配,模式识别等多学科的理论与方法,提取所摄对像以数字方式表达的几何与物理信息的摄影测量学的分支学科。2、计算机辅助测图(机助测图)以计算机及其输入、输出设备为主要制图工具实现从影像中提取地图信息及其转换、传输、存贮、处理与显示。3、影像的颗粒噪声:采用摄影方式获得光学影像..._数字摄影测量课后题答案

VIM代码 格式化与注释 自动对齐_vim模式备注对齐-程序员宅基地

文章浏览阅读9k次。最近在逛CSDN论坛时经常会苦恼一个问题——有些网友贴上去的代码没有用规范的格式贴上去,我贴到VIM里常常会需要手动调整格式,非常麻烦。每当这个时候就异常怀念以前用VC6.0时的ALT+F8……想下VIM作为一个程序员们最贴心的编辑器,显然不会对此坐视不理。经过一番的Search,果然就找到了一些最常用的简单技巧,笔记一下以备后来不时之需。 VIM格式化代码: 格式化全文指令 gg=G _vim模式备注对齐

eclipse 中自定义EL表达式时创建tld文件-程序员宅基地

文章浏览阅读82次。eclipse本身不带有tld文件,所以一般会创建一个xml文件,修改为tld文件1.在WEB-INF文件下创建一个xml文件,修改名字为ELTest.tld2.点击next,选择,然后点击next3.依次选择下面三个选项4.直接finish5这时候已经创建好了一个tld文件,下面重点来了,对tld文件进行配置,在 1.0这个标签上面,用直接覆盖你文件里面这..._eclipse 自定义tld 和使用

修改树莓派交换分区 SWAP 的正确姿势_树莓派派 failed to activate swap /swapfile-程序员宅基地

文章浏览阅读2.5k次,点赞2次,收藏6次。树莓派实验室按:Swap分区是磁盘上的一个特殊用途的分区。是当系统的物理内存不够用的时候,把物理内存中的一部分空间释放出来,以供当前运行的程序使用。那些被释放的空间可能来自一些很长时间没有什么操作的程序,这些被释放的空间被临时保存到Swap分区中,等到那些程序要运行时,再从Swap分区中恢复保存的数据到内存中。分配太多的Swap空间,会浪费磁盘空间,而Swap空间太少,则系统会发生错误。一般在内存..._树莓派派 failed to activate swap /swapfile

悟懂Linux学习笔记第11章资源监控②vmstat-程序员宅基地

文章浏览阅读1.4k次,点赞3次,收藏3次。解决办法: 当发生以上问题的时候请先调整应用程序对 CPU 的占用情况.使得应用程序能够更有效的使用 CPU.同时可以考虑增加更多的 CPU. 关于 CPU 的使用情况还可以结合 mpstat, ps aux top prstat –a 等等一些相应的命令来综合考虑关于具体的CPU的使用情况,和那些进程在占用大量的CPU时间.一般情况下,应用程序的问题会比较大一些.比如一些 SQL 语句不合理等等都会造成这样的现象.还有就是收银员的速度了,如果碰上了连钱都点不清楚的新手,那就有的 等了。_悟懂linux学习笔记第11章资源监控②vmstat

Nginx_nginx kic-程序员宅基地

文章浏览阅读110次。Nginx一、Nginx介绍1.什么是Nginx2.Nginx优点二、应用场景三、Nginx安装1.安装环境配置①因为Nginx是C语言编写的,所以需要配置C语言编译环境 (一定要在联网状态下安装)②第三方的开发包, 在编译之前需要安装这些第三方包2.安装Nginx 步骤3.启动并访问 Nginx四、配置虚拟主机1.通过端口区分不同的虚拟主机2.通过域名区分不同的虚拟主机①什么是域名②域名级别③域名绑定④配置域名映射⑤配置nginx.conf五、反向代理1.什么是代理2.正向代理3.反向代理4.Nginx实_nginx kic

随便推点

rxjs用简单的英语解释-程序员宅基地

文章浏览阅读233次。React式编程(Reactive Programming)介绍(Introduction)Do you want to start learning RxJs but get confused with some of the terminology that surrounds it? Or are you already using it and want to understand i..._rxjs 吐出数据 英文

faad warning: Bitstream value not allowed by specification-程序员宅基地

文章浏览阅读3.4k次。h264和aac mux成mp4, 用VLC打开mp4报如下错误:faad warning:Bitstream value not allowed by specification出错原因, mp4音频采样率参数没有配置。_bitstream value not allowed by specification

【数字信号处理】线性常系数差分方程 ( 使用 matlab 求解 “ 线性常系数差分方程 “ 示例 | A 向量分析 | B 向量分析 | 输入序列分析 | matlab 代码 )_matlab差分方程例题程序-程序员宅基地

文章浏览阅读1.1w次,点赞18次,收藏108次。一、使用 matlab 求解 “ 线性常系数差分方程 “ 示例、1、B 向量元素 : x(n) 参数、2、A 向量元素 : y(n) 参数、3、输入序列、4、matlab 代码、_matlab差分方程例题程序

React全家桶项目搭建-程序员宅基地

文章浏览阅读84次。React全家桶项目搭建

Java 开发 (实习生/应届生) 完整学习路线和规划,希望能够帮到屏幕前迷茫的你_java实习计划-程序员宅基地

文章浏览阅读7.7k次,点赞75次,收藏280次。这是来自一个没有团队,没有机构,仅仅是一个热爱Java开发的带学生UP主完成的学习路线,所有的资料、源码可以直接下载。各位小伙伴大家好,也许这是你们第一次见到我,我和你一样,曾也是一个对于未来充满迷茫的带学生,也许你现在正在担心Java开发这条路能否是自己最终的归宿,不知道自己是否能够在这条路上走得更远,作为一个过来人,我可以很明确的告诉你,Java的学习并不难,它需要的只是你的热情和坚持而已,不要犹豫,行动起来,希望各位能够在秋招/春招找到自己满意的工作。......_java实习计划

一文详解|老阳分享的Temu电商项目赚钱容易吗?-程序员宅基地

文章浏览阅读305次,点赞2次,收藏2次。同时,全托管模式为商家提供了全方位的运营支持和售后服务,降低了商家的运营成本和风险。老阳分享的项目信息,为我们提供了宝贵的经验和指导,但真正的成功还需靠个人的运营能力和市场洞察力。综上所述,老阳分享的Temu电商项目赚钱并不容易,但只要商家具备足够的运营能力和市场洞察力,结合Temu项目的优势,完全有可能在这个平台上取得成功。在当今跨境电商风起云涌的时代,Temu作为拼多多推出的跨境电商平台,引起了广泛关注。此外,售后服务和物流配送也是不可忽视的环节,它们直接影响着消费者的购物体验和商家的口碑。

推荐文章

热门文章

相关标签