基于elementui源码实现自定义穿梭框transfer组件

elementUI实现表格穿梭框 elementUI有一个穿梭框组件,但是这个组件局限性比较大,就是不能实现类似表格的效果,不像antDesign的穿梭框,可以搭配Table组件实现表格穿梭框的效果,所以就花时间用elementUI自己封装了一个(源码在最后面)。 阅读详情

需求:更改elementui中el-transfer样式, 实现单击左侧选项即加入右边选框,单击右侧选项即可回到左侧选框,中间左右来回按钮更改为左侧全选右侧全选,最终修改后效果图如下

下图源码可通过github下载:https://github.com/applebring/elementui



本以为自己能够不看elementui源码实现这需求,在折腾了一天还没实现后,还是回归到其源码进行研究,自己通过纯vue实现主要遇到了以下问题:

若是不需要进行模糊查询可通过index进行增删改查实现穿梭框功能,但是若是加入模糊查询则问题百出,但进行filter过滤器过滤后,数组index发生了变化,通过index进行增删改查行不通,当然,本人在同事指点下换了思路,通过给每个选项一个固定的识别id进行对象查找和增删改,虽然增删改查实现了,但是全选却不知如何能实现,毕竟通过计算属性得到数组,当把数组清空时,无法让对象复制到右边选框~

因此,值此星期六日之际,对elementui代码进行研究,以解心中之虑

1、首先是上github拉取elementui源码https://github.com/ElemeFE/element

2、本人在名为elementui源码文件夹下克隆github上element源码,在拉取后的element文件夹中packages文件目录下找到transfer文件夹,该文件即为el-transfer源码

3、将源码复制到自己项目中,通过组件方式将其引入,本人将main.vue复制在transfermain.vue文件夹下,将transfer-panel.vue复制在transferPanel.vue文件下,如

通过观察源代码,可以看出el-transfer实际上是将穿梭框分成两部分,左右边选择框分别为重复引入transferPanel组件,即tranfermain.vue实际上可分解为如下


因此,想要修改tranfer-panel样式可在transferPanel.vue里面更改,中间的按钮组在tansfermain.vue里更改,由上面可知,我们需要引入三个文件,内容分别如下:(以下文件为范例)

transfer.vue

<template>
<div>
<el-card class="box-card">
      <dir-transfer v-model="value2" filter-placeholder="请输入城市拼音"
    :data="data2" :titles="titles"></dir-transfer>
</el-card>
</div>
</template>
<script>
import DirTransfer from './transfermain.vue'
  export default {
    data() {
      const generateData2 = _ => {
        const data = [];
        const cities = ['上海', '北京', '广州', '深圳', '南京', '西安', '成都'];
        const pinyin = ['shanghai', 'beijing', 'guangzhou', 'shenzhen', 'nanjing', 'xian', 'chengdu'];
        cities.forEach((city, index) => {
          data.push({
            label: city,
            key: index,
            pinyin: pinyin[index]
          });
        });
        return data;
      };
      return {
        data2: generateData2(),
        value2: [],
        titles:['选择成员','选中成员'],//左右穿梭框的标题
        filterMethod(query, item) {
          return item.pinyin.indexOf(query) > -1;
        }
      };
    },
    components:{DirTransfer}
  };
</script>

在该页面dir-transfer即与el-transfer一致,属性,方法,事件均与官方文档一致

transfermain.vue(本应该为源码,本处直接粘贴更改后的代码)

<template>
  <div class="el-transfer">
    <transfer-panel
      v-bind="$props"
      ref="leftPanel"
      :filterable="true"
      :data="sourceData"
      :title="titles[0] || t('el.transfer.titles.0')"
      :default-checked="leftDefaultChecked"
      @checked-change="onSourceCheckedChange">
      <slot name="left-footer"></slot>
    </transfer-panel>
    <div class="el-transfer__buttons">
      <el-button
        type="primary"
        :class="['el-transfer__button', hasButtonTexts ? 'is-with-texts' : '']"
        @click.native="allToLeft">
        <span>左全选</span><!--此处本人更改为自己所需按钮,按钮事件名字也从addToLeft改为allToLeft-->
      </el-button>
      <el-button
        type="primary"
        :class="['el-transfer__button', hasButtonTexts ? 'is-with-texts' : '']"
        @click.native="allToRight">
        <span>右全选</span><!--此处本人更改为自己所需按钮,按钮事件名字也从addToRight改为allToRight-->
      </el-button>
    </div>
    <transfer-panel
      v-bind="$props"
      :filterable="false"
      :isRight="true"
      ref="rightPanel"
      :data="targetData"
      :title="titles[1] || t('el.transfer.titles.1')"
      :default-checked="rightDefaultChecked"
      :placeholder="filterPlaceholder || t('el.transfer.filterPlaceholder')"
      @checked-change="onTargetCheckedChange">
      <slot name="right-footer"></slot>
    </transfer-panel>
  </div>
</template>

<script>
  import ElButton from 'element-ui/packages/button';
  import Emitter from 'element-ui/src/mixins/emitter';
  import Locale from 'element-ui/src/mixins/locale';
  import TransferPanel from './transferPanel.vue';
  import Migrating from 'element-ui/src/mixins/migrating';

  export default {
    name: 'ElTransfer',

    mixins: [Emitter, Locale, Migrating],

    components: {
      TransferPanel,
      ElButton
    },

    props: {
      data: {
        type: Array,
        default() {
          return [];
        }
      },
      titles: {
        type: Array,
        default() {
          return [];
        }
      },
      buttonTexts: {
        type: Array,
        default() {
          return [];
        }
      },
      filterPlaceholder: {
        type: String,
        default: ''
      },
      filterMethod: Function,
      leftDefaultChecked: {
        type: Array,
        default() {
          return [];
        }
      },
      rightDefaultChecked: {
        type: Array,
        default() {
          return [];
        }
      },
      renderContent: Function,
      value: {
        type: Array,
        default() {
          return [];
        }
      },
      format: {
        type: Object,
        default() {
          return {};
        }
      },
      filterable: Boolean,
      props: {
        type: Object,
        default() {
          return {
            label: 'label',
            key: 'key',
            disabled: 'disabled'
          };
        }
      },
      targetOrder: {
        type: String,
        default: 'original'
      }
    },

    data() {
      return {
        leftChecked: [],
        rightChecked: [],
        checkedleft:true,
        checkedright:false
      };
    },

    computed: {
      dataObj() {
        const key = this.props.key;
        return this.data.reduce((o, cur) => (o[cur[key]] = cur) && o, {});
      },
  
      sourceData() {
        console.log("this",this.data);
        return this.data.filter(item => this.value.indexOf(item[this.props.key]) === -1);
      },

      targetData() {
        return this.targetOrder === 'original'
          ? this.data.filter(item => this.value.indexOf(item[this.props.key]) > -1)
          : this.value.map(key => this.dataObj[key]);
      },

      hasButtonTexts() {
        return this.buttonTexts.length === 2;
      }
    },

    watch: {
      value(val) {
        this.dispatch('ElFormItem', 'el.form.change', val);
      }
    },

    methods: {
      getMigratingConfig() {
        return {
          props: {
            'footer-format': 'footer-format is renamed to format.'
          }
        };
      },

      onSourceCheckedChange(val, movedKeys) {
        console.log("this leftCheck",this.leftChecked)
        this.leftChecked = val;
        if (movedKeys === undefined) return;
        this.$emit('left-check-change', val, movedKeys);
        this.addToRight();//在此处直接把选中项添加到右边框,实现单击操作,而不需通过按钮再次操作
      },

      onTargetCheckedChange(val, movedKeys) {
        this.rightChecked = val;
        if (movedKeys === undefined) return;
        this.$emit('right-check-change', val, movedKeys);
        this.addToLeft();//在此处直接把选中项添加到左边框,实现单击操作,而不需通过按钮再次操作
      },
      allToLeft(){
         this.$refs.leftPanel.handleAllCheckedChange(true);//直接出发全选事件,父组件调用子组件方法需要通过this.$refs.组件ref值.子组件方法名
      },
      addToLeft() {
        let currentValue = this.value.slice();
        this.rightChecked.forEach(item => {
          const index = currentValue.indexOf(item);
          if (index > -1) {
            currentValue.splice(index, 1);
          }
        });
        this.$emit('input', currentValue);
        this.$emit('change', currentValue, 'left', this.rightChecked);
      },
      allToRight(){
         this.$refs.rightPanel.handleAllCheckedChange(true);//直接出发全选事件,父组件调用子组件方法需要通过this.$refs.组件ref值.子组件方法名
      },
      addToRight() {
        let currentValue = this.value.slice();
        const itemsToBeMoved = [];
        const key = this.props.key;
        this.data.forEach(item => {
          const itemKey = item[key];
          if (
            this.leftChecked.indexOf(itemKey) > -1 &&
            this.value.indexOf(itemKey) === -1
          ) {
            itemsToBeMoved.push(itemKey);
          }
        });
        currentValue = this.targetOrder === 'unshift'
          ? itemsToBeMoved.concat(currentValue)
          : currentValue.concat(itemsToBeMoved);
        this.$emit('input', currentValue);
        this.$emit('change', currentValue, 'right', this.leftChecked);
      },

      clearQuery(which) {
        if (which === 'left') {
          this.$refs.leftPanel.query = '';
        } else if (which === 'right') {
          this.$refs.rightPanel.query = '';
        }
      }
    }
  };
</script>

该文件修改的主要难点在于如何通过按钮实现全选功能,摸索了半天,终于发现入口,通过调用handleAllCheckedChange(true),传入值为true即可完美实现,此处注意父组件调用子组件的方法需要通过this.$refs.组件ref值.子组件方法(参数)来调用

transferPanel.vue

<template>
  <div class="el-transfer-panel" style="border:1px solid #409EFF">
    <p class="el-transfer-panel__header">
      <el-checkbox v-show="false" 
        v-model="allChecked"
        @change="handleAllCheckedChange"
        :indeterminate="isIndeterminate">
        {{ title }}
        <span>{{ checkedSummary }}</span>
      </el-checkbox>
       {{ title }}
    </p>
    
    <div :class="['el-transfer-panel__body', hasFooter ? 'is-with-footer' : '']">
      <el-input
        class="el-transfer-panel__filter"
        v-model="query"
        size="small"
        :placeholder="placeholder"
        @mouseenter.native="inputHover = true"
        @mouseleave.native="inputHover = false"
        v-if="filterable">
        <i slot="prefix"
          :class="['el-input__icon', 'el-icon-' + inputIcon]"
          @click="clearQuery"
        ></i>
      </el-input>
      <el-checkbox-group
        v-model="checked"
        v-show="!hasNoMatch && data.length > 0"
        :class="{ 'is-filterable': filterable }"
        class="el-transfer-panel__list">
        <el-checkbox
          class="el-transfer-panel__item"
          :label="item[keyProp]"
          :disabled="item[disabledProp]"
          :key="item[keyProp]"
          v-for="item in filteredData">
          <option-content :option="item"></option-content>
          <span v-if="isRight" class="icon-close" style="float:right;margin-right:10px;width:20px;margin-top:5px;line-height:20px;text-align:center;height:20px;background-color:#ddd;border-radius:50%;">×</span>
        </el-checkbox><!--此处加了个判断是否为右边框给其加上相应的关闭按钮,isRight通过属性值进行传入-->
      </el-checkbox-group>
      <p
        class="el-transfer-panel__empty"
        v-show="hasNoMatch">{{ t('el.transfer.noMatch') }}</p>
      <p
        class="el-transfer-panel__empty"
        v-show="data.length === 0 && !hasNoMatch">{{ t('el.transfer.noData') }}</p>
    </div>
    <p class="el-transfer-panel__footer" v-if="hasFooter">
      <slot></slot>
    </p>
  </div>
</template>

<script>
  import ElCheckboxGroup from 'element-ui/packages/checkbox-group';
  import ElCheckbox from 'element-ui/packages/checkbox';
  import ElInput from 'element-ui/packages/input';
  import Locale from 'element-ui/src/mixins/locale';

  export default {
    mixins: [Locale],

    name: 'ElTransferPanel',

    componentName: 'ElTransferPanel',

    components: {
      ElCheckboxGroup,
      ElCheckbox,
      ElInput,
      OptionContent: {
        props: {
          option: Object
        },
        render(h) {
          const getParent = vm => {
            if (vm.$options.componentName === 'ElTransferPanel') {
              return vm;
            } else if (vm.$parent) {
              return getParent(vm.$parent);
            } else {
              return vm;
            }
          };
          const panel = getParent(this);
          const transfer = panel.$parent || panel;
          return panel.renderContent
            ? panel.renderContent(h, this.option)
            : transfer.$scopedSlots.default
              ? transfer.$scopedSlots.default({ option: this.option })
              : <span>{ this.option[panel.labelProp] || this.option[panel.keyProp] }</span>;
        }
      }
    },

    props: {
      data: {
        type: Array,
        default() {
          return [];
        }
      },
      renderContent: Function,
      placeholder: String,
      title: String,
      filterable: Boolean,
      isRight:Boolean,
      format: Object,
      filterMethod: Function,
      defaultChecked: Array,
      props: Object
    },

    data() {
      return {
        checked: [],
        allChecked: false,
        query: '',
        inputHover: false,
        checkChangeByUser: true
      };
    },

    watch: {
      checked(val, oldVal) {
        this.updateAllChecked();
        if (this.checkChangeByUser) {
          const movedKeys = val.concat(oldVal)
            .filter(v => val.indexOf(v) === -1 || oldVal.indexOf(v) === -1);
          this.$emit('checked-change', val, movedKeys);
        } else {
          this.$emit('checked-change', val);
          console.log("Check by User");
          this.checkChangeByUser = true;
        }
      },

      data() {
        const checked = [];
        const filteredDataKeys = this.filteredData.map(item => item[this.keyProp]);
        this.checked.forEach(item => {
          if (filteredDataKeys.indexOf(item) > -1) {
            checked.push(item);
          }
        });
        this.checkChangeByUser = false;
        this.checked = checked;
      },

      checkableData() {
        this.updateAllChecked();
      },

      defaultChecked: {
        immediate: true,
        handler(val, oldVal) {
          if (oldVal && val.length === oldVal.length &&
            val.every(item => oldVal.indexOf(item) > -1)) return;
          const checked = [];
          const checkableDataKeys = this.checkableData.map(item => item[this.keyProp]);
          val.forEach(item => {
            if (checkableDataKeys.indexOf(item) > -1) {
              checked.push(item);
            }
          });
          this.checkChangeByUser = false;
          this.checked = checked;
        }
      }
    },

    computed: {
      filteredData() {
        return this.data.filter(item => {
          if (typeof this.filterMethod === 'function') {
            return this.filterMethod(this.query, item);
          } else {
            const label = item[this.labelProp] || item[this.keyProp].toString();
            return label.toLowerCase().indexOf(this.query.toLowerCase()) > -1;
          }
        });
      },

      checkableData() {
        return this.filteredData.filter(item => !item[this.disabledProp]);
      },

      checkedSummary() {
        const checkedLength = this.checked.length;
        const dataLength = this.data.length;
        const { noChecked, hasChecked } = this.format;
        if (noChecked && hasChecked) {
          return checkedLength > 0
            ? hasChecked.replace(/\${checked}/g, checkedLength).replace(/\${total}/g, dataLength)
            : noChecked.replace(/\${total}/g, dataLength);
        } else {
          return `${ checkedLength }/${ dataLength }`;
        }
      },

      isIndeterminate() {
        const checkedLength = this.checked.length;
        return checkedLength > 0 && checkedLength < this.checkableData.length;
      },

      hasNoMatch() {
        return this.query.length > 0 && this.filteredData.length === 0;
      },

      inputIcon() {
        return this.query.length > 0 && this.inputHover
          ? 'circle-close'
          : 'search';
      },

      labelProp() {
        return this.props.label || 'label';
      },

      keyProp() {
        return this.props.key || 'key';
      },

      disabledProp() {
        return this.props.disabled || 'disabled';
      },

      hasFooter() {
        return !!this.$slots.default;
      }
    },

    methods: {
      updateAllChecked() {
        const checkableDataKeys = this.checkableData.map(item => item[this.keyProp]);
        this.allChecked = checkableDataKeys.length > 0 &&
          checkableDataKeys.every(item => this.checked.indexOf(item) > -1);
      },

      handleAllCheckedChange(value) {
        console.log("value",value);
        this.checked = value
          ? this.checkableData.map(item => item[this.keyProp])
          : [];
      },

      clearQuery() {
        if (this.inputIcon === 'circle-close') {
          this.query = '';
        }
      }
    }
  };
</script>

通过上面对elementui穿梭框的自定义样式,可类比其他组件的自定义修改

element ui transfer 穿梭框 分页实现,接口获取、更新数据 使用穿梭框数据量大时需要分页,官方的组件并不能满足需求。数据大时不分页一次渲染页面卡。通过重新修改官方源码、封装实现分页。 1、新建TransferPanel 组件,根据官方源码修改适配 <template> <div class="el-transfer-panel" style="width: 17.5rem"> <p class="el-transfer-panel__header"> <el-checkbox v 阅读详情

相关推荐

el-transfer和el-tree进行结合搞一个树形穿梭框

由于业务需求需要在穿梭框里使用树形结构,但是本身element里并不支持,于是参考了别的大佬发的文章作为思路及后续自己新增了一些处理功能。

bbkhhvv的博客 6307

ElementUi源码修改之transfer修改的爬坑之旅

前端永远是根据老板需求的变化而进行升级改进,存在必定合理。产品经理眼里能够见到你没有见过的,所以新的需求在你这是新奇。就好比说,产品让你用element然后又跟你说我不想让他这样出现,你说你改不改源码? 源码初始效果如下: 源码中不管你选中添加进右边的是谁,总是按照左边的排列顺序添加的,而我要改的需求是:不管我选中的顺序如何,我要按照我选中添加的顺序走,即取消组件的默认排序。 源码如下:...

前端-尔嵘 2794

Vue 实现高级穿梭框 Transfer 封装

使用Element-UI、Vue2、lodash技术栈实现高级穿梭框的封装,即当穿梭框内条目较多+展示多样信息+对条目进行筛选时,采用简化的分页表格组件,使用穿梭框高级模式,且支持搜索功能,也可以使用插槽自定义表格列,支持对待选择表格的搜索区域,已添加表格的搜索项等进行自定义...

Yuki_yuhan的博客 3260

element el-transfer穿梭框的使用,自定义穿梭框的数据项

List item 查看element官方文档可以了解到 el-transfer穿梭框的基本使用方法,本文主要介绍数据项的自定义渲染和右侧列表元素变化时触发方法的实现。 自定义数据项,除了基本的el-transfer使用方法,还需要使用Scoped Slot。 查看官方文档,Transfer 的数据通过 data 属性传入。数据需要是一个对象数组,每个对象有以下属性:key 为数据的唯一性标...

weixin_43128854的博客 3万+

ElementUI穿梭框改造指南:给Transfer组件添加表格视图和异步加载能力

本文详细介绍了如何对ElementUI的Transfer组件进行深度改造,通过添加表格视图和异步加载能力,解决原生组件在复杂业务场景下的局限性。文章涵盖表格重构、异步数据加载、自定义插槽扩展等核心技术,帮助开发者提升Vue企业级应用中的交互体验和性能表现。

weixin_30790841的博客 409

前后端分离系列 -- SpringBoot + Vue ElementUI Transfer(穿梭框)组件实现班级学生管理系统 -- 班级模块学生的添加与移除 Transfer不过如此

前后端分离系列 -- SpringBoot + Vue ElementUI Transfer(穿梭框)组件实现班级学生管理系统 -- 班级模块学生的添加与移除 Transfer不过如此

wanghuichen的博客 1958

element ui 穿梭框_改造ElementUI穿梭框

最近,在做公司项目过程中,遇到了一个小需求,就是给客户选择套餐的某一种属性的时候,有些属性是有数值的,开始想用table去做但是太low,因为项目是用vuejs作为前端技术,element作为辅助ui,所以就想用element-ui的穿梭框来完成这样一件事情。但是,穿梭框的功能有限,所以想到自己来改造一下他。先去github上看一下element的源码:https://github.com/Ele...

weixin_39881387的博客 2066

elementUI-使用el-table自定义transfer组件

在elementUI中使用el-table自定义完成transfer组件功能。内有注释使用说明

关于Element ui Transfer (穿梭框)使用心得

最近在使用Element ui做一个大型的智能监测项目

sanghongxv的博客 3万+

SNAP计算哨兵二号的叶面积指数(LAI)

对于哨兵二号数据以及LANDSAT8数据,SNAP提供已经集成好的模块计算LAI。在Optical->Thematic Land Processing->Biopyhsical Processor目录下面。 对于经过Sen2Cor处理好的数据,需经过重采样才可进行计算。重采样工具在Raster->Geometric->Resampling。 如果选择Biopyhsical Processor S2_10m进行计算,需要将所有的波段都重采样为10米(哨兵二号的第二波段为10米,可据此波

gxwwww的博客 9417

ESP8266红外控制美的空调:从协议解析到Home Assistant集成

红外遥控技术作为一种经典的非接触式控制方式,其原理是通过红外发光二极管发射经过特定频率调制的光信号来传递指令。在物联网和智能家居领域,利用微控制器如ESP8266模拟红外信号,成为将传统家电接入智能生态系统的关键技术。这项技术通过精准解析和生成符合设备厂商私有协议的红外编码,实现了对空调、电视等设备的远程与自动化控制,具有很高的实用价值。本文聚焦于美的空调的红外协议,深入探讨了其脉冲宽度调制(PWM)和全量式编码的特点,并提供了基于ESP8266的完整解决方案,包括硬件连接、库函数API详解以及如何将其无缝

weixin_30718391的博客 402

tree结构穿梭 vue_结合el-tree和el-transfer搞一个树形穿梭框

最近遇到个需求,穿梭框中的内容是树形结构的数据。查看elementUI的transfer组件是不支持树形结构的数据,也就不能直接使用了。但是el-tree组件支持啊,那如果让tree组件和transfer组件结合一下岂不完美????。准备clone一份element的源码,找到package/tansfer/src文件夹,里面的vue文件就是我们的目标。复制一份出来到自己的项目(同时复制mixins里的...

weixin_33571513的博客 3242

从科研小白到动物行为分析:我的DeepLabCut 3.0安装与初体验全记录

本文记录了从科研小白到成功安装并使用DeepLabCut 3.0进行动物行为分析的全过程。详细介绍了Anaconda环境配置、CUDA版本选择、DeepLabCut安装步骤及验证方法,并分享了初体验中的实用技巧和跨学科研究心得,为生物研究者提供了AI工具应用的实战指南。

weixin_30235225的博客 402

element-ui transfer 组件源码分享

transfer 穿梭框组件源码简单分享,主要从以下几个方面:1、transfer 组件页面结构。2、transfer 组件属性。3、transfer 组件方法。4、transfer 组件事件。5、transfer slot 挂载。

qq_37309987的博客 1191

最新打赏系统打赏源码麒麟最新打赏源码喜盈门打赏知识付费课程教程直播讲解

打赏源码打赏系统

qq_41095398的博客 2037

从零开始:Basler相机与pylon Viewer的工业视觉入门指南

本文详细介绍了Basler相机与pylon Viewer在工业视觉系统中的入门指南,涵盖硬件连接、软件安装、核心功能解析及实战案例。通过pylon Viewer的全面控制和参数调整功能,帮助新手快速掌握工业视觉检测技术,提升生产效率。

julia4scientist的博客 1136

vue+elmentUI (el-tree,el-transfer)制作穿梭树踩坑

el-tree和el-transfer穿梭树踩坑首先,在网上搜穿梭树,可以找到这个插件: 首先,在网上搜穿梭树,可以找到这个插件: 穿梭树github地址: https://github.com/hql7/tree-transfer 先 npm 下载插件 npm install el-tree-transfer --save 或 npm i el-tree-transfer -S 然后你可以像使用普通组件一样使用 el-tree-transfer html代码: <template> &

采花小盗周的博客 4234

《网络安全自学教程》- 802.1x协议

802.1x协议架构,工作原理/认证流程,认证方式,MAB认证,触发认证的三种方式,EAP报文格式,EAPOL报文格式

wangyuxiang946的博客 2万+

【vue2】element-ui el-transfer扩展 实现多列效果一对多

element-ui el-transfer扩展 实现多列效果一对多

有趣愉悦的学习冒险 4200

cadence17.4和16.6同时安装无法使用的问题

经过对报错的问题分析,发现还是17.4的lic文件和16.6的不一样,16.6的版本总是无法找到自己对应的lic文件。卸载了,重新单独安装16.6,这里就是正确的。包括使用这些工具去修复这些问题,都无法接近。已经放弃了,使用哪个版本就安装 哪个版本。这个也无法解决问题。

D_Katter的博客 2324

华为OD机试真题2025双机位C卷 Python&JS 实现【卡牌游戏】

小明正在尝试一种新的牌游戏。游戏规则只如下:首先,小明拿到一张写有数字m的牌。 然后,他会拿到另外n张牌,上面分别写有不同的数字,牌排成一排。小明的目标是从这排牌中找到一串连续的牌,这些牌上数字的总和可以被 m整除。你的任务是判断小明是否可以完成这个目标。

MISAYAONE的博客 403

iview穿梭框(Transfer) filterable搜索条件清除

问题: iview提供的穿梭框组件未提供在filterable开启时,清除搜索框中输入内容功能。在项目中遇到问题,将穿梭框放在model中操作,有搜索条件时模态框再次打开搜索条件仍然存在。 解决: 1、首先在iview官网上未找到可解决该问题的方式,但是去看了Element-UI提供了相应的功能 2、其次去GitHub上也没有找到类似的issue 3、重点来了: 在查看 ...

pobu168的博客 7034

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

element 穿梭框的使用

element 穿梭框的使用 废话不多说,上源码 <!-- 穿梭框 --> <el-form-item label="xxx:" class="DrawerRight" > <el-transfer @change="choose($event)" filterable filter-

m0_55336994的博客 1275

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

修改ElementUI源码实践

 提要 Vue2.0+Vuex+ElementUI是现在很多项目都在使用的BS软件的开发组合。 Vue相较于Angular具有学习成本低,上手快以及组件轻量化的特点;相较于React,其官方提供的很多指令以及可以自定义的指令能够为让开发更加高效。并且相较于React生命周期监听所有props和state的变化,Vue中提供的watch方法监听单个数据的变化,能够更加直观的进行数

halibote330的博客 6557

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

上一篇: CSP内容安全策略与vue-cli中转化为base64文件冲突解决方法
下一篇: Vue通过for循环随机生成不同的颜色或随机数
小简GoGo
博客等级 码龄10年 50粉丝 32原创
评论 8
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值