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\transfer\src\main.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\theme-chalk\src\transfer.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   width: $--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       width: 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     width: auto;
144 
145     .el-input__inner {
146       height: $--transfer-filter-height;
147       width: 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     width: 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     width: 14px;
230     border-radius: 3px;
231     &::after {
232       height: 6px;
233       width: 3px;
234       left: 4px;
235     }
236   }
237 }

查看效果可以在examples\docs\zh-CN\transfer.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

如有错误,请指正

猜你喜欢

转载自www.cnblogs.com/bunuo/p/9021080.html