• element-ui 修改源码实践 --tranfer


    1.element-ui 地址:https://github.com/ElemeFE/element

    2.修改elelment-ui版本:2.2.2(请选择和项目相对应的版本)

    3.修改内容:穿梭框组件(transfer),实现上下移动排序

    4.效果:

                  

    步骤

    从github上把项目克隆到本地

    全局安装yarn :npm install -g yarn

    安装依赖并启动项目:npm run dev (已经使用 yarn 进行依赖版本的锁定,所以请不要使用 npm install 安装依赖。)

    目录介绍

     我们修改源码主要也是修改这两个位置

    打开packages ransfersrcmain.vue(红色部分是我修改过的代码)

      1 <template>
      2   <div class="el-transfer">
      3     <transfer-panel
      4       v-bind="$props"
      5       ref="leftPanel"
      6       :data="sourceData"
      7       :title="titles[0] || t('el.transfer.titles.0')"
      8       :default-checked="leftDefaultChecked"
      9       :placeholder="filterPlaceholder || t('el.transfer.filterPlaceholder')"
     10       @checked-change="onSourceCheckedChange">
     11       <slot name="left-footer"></slot>
     12     </transfer-panel>
     13     <div class="el-transfer__buttons">
     14       <el-button
     15         type="primary"
     16         :class="['el-transfer__button', hasButtonTexts ? 'is-with-texts' : '']"
     17         @click.native="addToLeft"
     18         :disabled="rightChecked.length === 0">
     19         <i class="el-icon-arrow-left"></i>
     20         <span v-if="buttonTexts[0] !== undefined">{{ buttonTexts[0] }}</span>
     21       </el-button>
     22       <el-button
     23         type="primary"
     24         :class="['el-transfer__button', hasButtonTexts ? 'is-with-texts' : '']"
     25         @click.native="addToRight"
     26         :disabled="leftChecked.length === 0">
     27         <span v-if="buttonTexts[1] !== undefined">{{ buttonTexts[1] }}</span>
     28         <i class="el-icon-arrow-right"></i>
     29       </el-button>
     30       <el-button
     31         v-if="moveable"
     32         type="primary"
     33         :class="['el-transfer__button', hasButtonTexts ? 'is-with-texts' : '']"
     34         @click.native="toUp"
     35         :disabled="rightChecked.length === 0 || rightChecked.length > 1">
     36         <span v-if="buttonTexts[2] !== undefined">{{ buttonTexts[2] }}</span>
     37         <i class="el-icon-arrow-up"></i>
     38       </el-button>
     39       <el-button
     40         v-if="moveable"
     41         type="primary"
     42         :class="['el-transfer__button', hasButtonTexts ? 'is-with-texts' : '']"
     43         @click.native="toDown"
     44         :disabled="rightChecked.length === 0 || rightChecked.length > 1">
     45         <span v-if="buttonTexts[3] !== undefined">{{ buttonTexts[3] }}</span>
     46         <i class="el-icon-arrow-down"></i>
     47       </el-button>
     48     </div>
     49     <transfer-panel
     50       v-bind="$props"
     51       ref="rightPanel"
     52       :data="targetData"
     53       :title="titles[1] || t('el.transfer.titles.1')"
     54       :default-checked="rightDefaultChecked"
     55       :placeholder="filterPlaceholder || t('el.transfer.filterPlaceholder')"
     56       @checked-change="onTargetCheckedChange">
     57       <slot name="right-footer"></slot>
     58     </transfer-panel>
     59   </div>
     60 </template>
     61 
     62 <script>
     63   import ElButton from 'element-ui/packages/button';
     64   import Emitter from 'element-ui/src/mixins/emitter';
     65   import Locale from 'element-ui/src/mixins/locale';
     66   import TransferPanel from './transfer-panel.vue';
     67   import Migrating from 'element-ui/src/mixins/migrating';
     68 
     69   export default {
     70     name: 'ElTransfer',
     71 
     72     mixins: [Emitter, Locale, Migrating],
     73 
     74     components: {
     75       TransferPanel,
     76       ElButton
     77     },
     78 
     79     props: {
     80       data: {
     81         type: Array,
     82         default() {
     83           return [];
     84         }
     85       },
     86       titles: {
     87         type: Array,
     88         default() {
     89           return [];
     90         }
     91       },
     92       buttonTexts: {
     93         type: Array,
     94         default() {
     95           return [];
     96         }
     97       },
     98       filterPlaceholder: {
     99         type: String,
    100         default: ''
    101       },
    102       filterMethod: Function,
    103       leftDefaultChecked: {
    104         type: Array,
    105         default() {
    106           return [];
    107         }
    108       },
    109       rightDefaultChecked: {
    110         type: Array,
    111         default() {
    112           return [];
    113         }
    114       },
    115       renderContent: Function,
    116       value: {
    117         type: Array,
    118         default() {
    119           return [];
    120         }
    121       },
    122       format: {
    123         type: Object,
    124         default() {
    125           return {};
    126         }
    127       },
    128       filterable: Boolean,
    129       props: {
    130         type: Object,
    131         default() {
    132           return {
    133             label: 'label',
    134             key: 'key',
    135             disabled: 'disabled'
    136           };
    137         }
    138       },
    139       targetOrder: {
    140         type: String,
    141         default: 'original'
    142       },
    143       moveable: Boolean
    144     },
    145 
    146     data() {
    147       return {
    148         leftChecked: [],
    149         rightChecked: []
    150       };
    151     },
    152 
    153     computed: {
    154       dataObj() {
    155         const key = this.props.key;
    156         return this.data.reduce((o, cur) => (o[cur[key]] = cur) && o, {});
    157       },
    158   
    159       sourceData() {
    160         return this.data.filter(item => this.value.indexOf(item[this.props.key]) === -1);
    161       },
    162 
    163       targetData() {
    164         return this.targetOrder === 'original'
    165           ? this.data.filter(item => this.value.indexOf(item[this.props.key]) > -1)
    166           : this.value.map(key => this.dataObj[key]);
    167       },
    168 
    169       hasButtonTexts() {
    170         return this.buttonTexts.length === 4;
    171       }
    172     },
    173 
    174     watch: {
    175       value(val) {
    176         this.dispatch('ElFormItem', 'el.form.change', val);
    177       }
    178     },
    179 
    180     methods: {
    181       getMigratingConfig() {
    182         return {
    183           props: {
    184             'footer-format': 'footer-format is renamed to format.'
    185           }
    186         };
    187       },
    188 
    189       onSourceCheckedChange(val, movedKeys) {
    190         this.leftChecked = val;
    191         if (movedKeys === undefined) return;
    192         this.$emit('left-check-change', val, movedKeys);
    193       },
    194 
    195       onTargetCheckedChange(val, movedKeys) {
    196         this.rightChecked = val;
    197         if (movedKeys === undefined) return;
    198         this.$emit('right-check-change', val, movedKeys);
    199       },
    200 
    201       addToLeft() {
    202         let currentValue = this.value.slice();
    203         this.rightChecked.forEach(item => {
    204           const index = currentValue.indexOf(item);
    205           if (index > -1) {
    206             currentValue.splice(index, 1);
    207           }
    208         });
    209         this.$emit('input', currentValue);
    210         this.$emit('change', currentValue, 'left', this.rightChecked);
    211       },
    212 
    213       addToRight() {
    214         let currentValue = this.value.slice();
    215         const itemsToBeMoved = [];
    216         const key = this.props.key;
    217         this.data.forEach(item => {
    218           const itemKey = item[key];
    219           if (
    220             this.leftChecked.indexOf(itemKey) > -1 &&
    221             this.value.indexOf(itemKey) === -1
    222           ) {
    223             itemsToBeMoved.push(itemKey);
    224           }
    225         });
    226         currentValue = this.targetOrder === 'unshift'
    227           ? itemsToBeMoved.concat(currentValue)
    228           : currentValue.concat(itemsToBeMoved);
    229         this.$emit('input', currentValue);
    230         this.$emit('change', currentValue, 'right', this.leftChecked);
    231       },
    232       toUp() {
    233         let currentValue = this.value.slice();
    234         let index = currentValue.indexOf(this.rightChecked[0]);
    235         currentValue = this.upRecord(currentValue, index);
    236         this.$emit('input', currentValue);
    237         this.$emit('change', currentValue, 'right');
    238       },
    239       toDown() {
    240         let currentValue = this.value.slice();
    241         let index = currentValue.indexOf(this.rightChecked[0]);
    242         currentValue = this.downRecord(currentValue, index);
    243         this.$emit('input', currentValue);
    244         this.$emit('change', currentValue, 'right');
    245       },
    246 
    247       clearQuery(which) {
    248         if (which === 'left') {
    249           this.$refs.leftPanel.query = '';
    250         } else if (which === 'right') {
    251           this.$refs.rightPanel.query = '';
    252         }
    253       },
    254 
    255       swapItems(arr, index1, index2) {
    256         arr[index1] = arr.splice(index2, 1, arr[index1])[0];
    257         return arr;
    258       },
    259 
    260       upRecord(arr, $index) {
    261         if ($index === 0) {
    262           return arr;
    263         }
    264         return this.swapItems(arr, $index, $index - 1);
    265       },
    266 
    267       downRecord(arr, $index) {
    268         if ($index === arr.length - 1) {
    269           return arr;
    270         }
    271         return this.swapItems(arr, $index, $index + 1);
    272       }
    273     }
    274   };
    275 </script>

     packages heme-chalksrc ransfer.scss

      1 @import "mixins/mixins";
      2 @import "mixins/utils";
      3 @import "common/var";
      4 @import "input";
      5 @import "button";
      6 @import "checkbox";
      7 @import "checkbox-group";
      8 
      9 @include b(transfer) {
     10   font-size: $--font-size-base;
     11 
     12   @include e(buttons) {
     13     display: inline-block;
     14     vertical-align: middle;
     15     padding: 0 30px;
     16   }
     17 
     18   @include e(button) {
     19     display: block;
     20     margin: 0 auto;
     21     padding: 10px;
     22     border-radius: 50%;
     23     color: $--color-white;
     24     background-color: $--color-primary;
     25     font-size: 0;
     26 
     27     @include when(with-texts) {
     28       border-radius: $--border-radius-base;
     29     }
     30 
     31     @include when(disabled) {
     32       border: $--border-base;
     33       background-color: $--background-color-base;
     34       color: $--color-text-placeholder;
     35 
     36       &:hover {
     37         border: $--border-base;
     38         background-color: $--background-color-base;
     39         color: $--color-text-placeholder;
     40       }
     41     }
     42 
     43     &:first-child {
     44       margin-bottom: 10px;
     45     }
     46 
     47     &:nth-child(2) {
     48       margin: 0;
     49       margin-bottom: 10px;
     50     }
     51 
     52     &:nth-child(3) {
     53       margin: 0;
     54       margin-bottom: 10px;
     55     }
     56 
     57     &:nth-child(4) {
     58       margin: 0;
     59     }
     60 
     61     i, span {
     62       font-size: 14px;
     63     }
     64 
     65     & [class*="el-icon-"] + span {
     66       margin-left: 0;
     67     }
     68   }
     69 }
     70 
     71 @include b(transfer-panel) {
     72   border: 1px solid $--transfer-border-color;
     73   border-radius: $--transfer-border-radius;
     74   overflow: hidden;
     75   background: $--color-white;
     76   display: inline-block;
     77   vertical-align: middle;
     78    $--transfer-panel-width;
     79   max-height: 100%;
     80   box-sizing: border-box;
     81   position: relative;
     82 
     83   @include e(body) {
     84     height: $--transfer-panel-body-height;
     85 
     86     @include when(with-footer) {
     87       padding-bottom: $--transfer-panel-footer-height;
     88     }
     89   }
     90 
     91   @include e(list) {
     92     margin: 0;
     93     padding: 6px 0;
     94     list-style: none;
     95     height: $--transfer-panel-body-height;
     96     overflow: auto;
     97     box-sizing: border-box;
     98 
     99     @include when(filterable) {
    100       height: #{$--transfer-panel-body-height - $--transfer-filter-height - 20px};
    101       padding-top: 0;
    102     }
    103   }
    104 
    105   @include e(item) {
    106     height: $--transfer-item-height;
    107     line-height: $--transfer-item-height;
    108     padding-left: 15px;
    109     display: block;
    110 
    111     & + .el-transfer-panel__item {
    112       margin-left: 0;
    113     }
    114 
    115     &.el-checkbox {
    116       color: $--color-text-regular;
    117     }
    118 
    119     &:hover {
    120       color: $--color-primary;
    121     }
    122 
    123     &.el-checkbox .el-checkbox__label {
    124        100%;
    125       @include utils-ellipsis;
    126       display: block;
    127       box-sizing: border-box;
    128       padding-left: 24px;
    129       line-height: $--transfer-item-height;
    130     }
    131 
    132     .el-checkbox__input {
    133       position: absolute;
    134       top: 8px;
    135     }
    136   }
    137 
    138   @include e(filter) {
    139     text-align: center;
    140     margin: 15px;
    141     box-sizing: border-box;
    142     display: block;
    143      auto;
    144 
    145     .el-input__inner {
    146       height: $--transfer-filter-height;
    147        100%;
    148       font-size: 12px;
    149       display: inline-block;
    150       box-sizing: border-box;
    151       border-radius: #{$--transfer-filter-height / 2};
    152       padding-right: 10px;
    153       padding-left: 30px;
    154     }
    155 
    156     .el-input__icon {
    157       margin-left: 5px;
    158     }
    159 
    160     .el-icon-circle-close {
    161       cursor: pointer;
    162     }
    163   }
    164 
    165   .el-transfer-panel__header {
    166     height: $--transfer-panel-header-height;
    167     line-height: $--transfer-panel-header-height;
    168     background: $--transfer-panel-header-background;
    169     margin: 0;
    170     padding-left: 15px;
    171     border-bottom: 1px solid $--transfer-border-color;
    172     box-sizing: border-box;
    173     color: $--color-black;
    174 
    175     .el-checkbox {
    176       display: block;
    177       line-height: 40px;
    178 
    179       .el-checkbox__label {
    180         font-size: 16px;
    181         color: $--color-text-primary;
    182         font-weight: normal;
    183 
    184         span {
    185           position: absolute;
    186           right: 15px;
    187           color: $--color-text-secondary;
    188           font-size: 12px;
    189           font-weight: normal;
    190         }
    191       }
    192     }
    193   }
    194 
    195   .el-transfer-panel__footer {
    196     height: $--transfer-panel-footer-height;
    197     background: $--color-white;
    198     margin: 0;
    199     padding: 0;
    200     border-top: 1px solid $--transfer-border-color;
    201     position: absolute;
    202     bottom: 0;
    203     left: 0;
    204      100%;
    205     z-index: $--index-normal;
    206     @include utils-vertical-center;
    207 
    208     .el-checkbox {
    209       padding-left: 20px;
    210       color: $--color-text-regular;
    211     }
    212   }
    213 
    214   .el-transfer-panel__empty {
    215     margin: 0;
    216     height: $--transfer-item-height;
    217     line-height: $--transfer-item-height;
    218     padding: 6px 15px 0;
    219     color: $--color-text-secondary;
    220     text-align: center;
    221   }
    222 
    223   .el-checkbox__label {
    224     padding-left: 8px;
    225   }
    226 
    227   .el-checkbox__inner {
    228     height: 14px;
    229      14px;
    230     border-radius: 3px;
    231     &::after {
    232       height: 6px;
    233        3px;
    234       left: 4px;
    235     }
    236   }
    237 }

    查看效果可以在examplesdocszh-CN ransfer.md中修改后查看

    修改第80行

    <template>
      <el-transfer v-model="value1" :data="data" target-order="push" :moveable=true></el-transfer>
    </template>

    项目打包: npm run dist         (请注意代码书写规范,否则可能打包失败)

    将打包生成的lib文件替换项目中的lib文件,这样我们就可以用了

    因为element-ui官方暂时不提供这样的功能,所以只能自己修改,我已经把代码上传到github,地址:https://github.com/BuNuo/element

    如有错误,请指正

  • 相关阅读:
    C++中的空类,编译器默认可以产生哪些成员函数
    野指针(Wild pointer)和悬垂指针(dangling pointer)
    WHY C++ ?(by Herb Sutter) & C++17 standard
    mapreduce 多路输出
    stdout 编码 vim 删除左边,右边
    积累碎片shell
    python logging模块
    shell 流程控制
    shell 变量
    时间管理法则
  • 原文地址:https://www.cnblogs.com/bunuo/p/9021080.html
Copyright © 2020-2023  润新知