Commit 5b19b5f55f0b1022c3bf5e7b7060534b2d9e3676

Authored by 梁灏
1 parent 191068ac

support Transfer

support Transfer
examples/app.vue
... ... @@ -46,6 +46,7 @@ li + li { border-left: solid 1px #bbb; padding-left: 10px; margin-left: 10px; }
46 46 <li><router-link to="/select">Select</router-link></li>
47 47 <li><router-link to="/backtop">Backtop</router-link></li>
48 48 <li><router-link to="/page">Page</router-link></li>
  49 + <li><router-link to="/transfer">Transfer</router-link></li>
49 50 </ul>
50 51 </nav>
51 52 <router-view></router-view>
... ...
examples/main.js
... ... @@ -148,6 +148,10 @@ const router = new VueRouter({
148 148 {
149 149 path: '/page',
150 150 component: require('./routers/page.vue')
  151 + },
  152 + {
  153 + path: '/transfer',
  154 + component: require('./routers/transfer.vue')
151 155 }
152 156 ]
153 157 });
... ...
examples/routers/transfer.vue
  1 +<!--<template>-->
  2 + <!--<div>-->
  3 + <!--<Transfer-->
  4 + <!--:data="data1"-->
  5 + <!--filterable-->
  6 + <!--:target-keys="targetKeys1"-->
  7 + <!--:render-format="render1"-->
  8 + <!--@on-change="handleChange1"></Transfer>-->
  9 + <!--</div>-->
  10 +<!--</template>-->
  11 +<!--<script>-->
  12 + <!--export default {-->
  13 + <!--data () {-->
  14 + <!--return {-->
  15 + <!--data1: this.getMockData(),-->
  16 + <!--targetKeys1: this.getTargetKeys()-->
  17 + <!--}-->
  18 + <!--},-->
  19 + <!--methods: {-->
  20 + <!--getMockData () {-->
  21 + <!--let mockData = [];-->
  22 + <!--for (let i = 1; i <= 20; i++) {-->
  23 + <!--mockData.push({-->
  24 + <!--key: i.toString(),-->
  25 + <!--label: '内容' + i,-->
  26 + <!--description: '内容' + i + '的描述信息',-->
  27 + <!--disabled: Math.random() * 3 < 1-->
  28 + <!--});-->
  29 + <!--}-->
  30 + <!--return mockData;-->
  31 + <!--},-->
  32 + <!--getTargetKeys () {-->
  33 + <!--return this.getMockData()-->
  34 + <!--.filter(() => Math.random() * 2 > 1)-->
  35 + <!--.map(item => item.key);-->
  36 + <!--},-->
  37 + <!--render1 (item) {-->
  38 + <!--return item.label;-->
  39 + <!--},-->
  40 + <!--handleChange1 (newTargetKeys, direction, moveKeys) {-->
  41 + <!--console.log(newTargetKeys);-->
  42 + <!--console.log(direction);-->
  43 + <!--console.log(moveKeys);-->
  44 + <!--this.targetKeys1 = newTargetKeys;-->
  45 + <!--}-->
  46 + <!--}-->
  47 + <!--}-->
  48 +<!--</script>-->
  49 +
  50 +
1 51 <template>
2 52 <Transfer
3   - :data="data2"
4   - :target-keys="targetKeys2"
  53 + :data="data3"
  54 + :target-keys="targetKeys3"
  55 + :list-style="listStyle"
  56 + :render-format="render3"
  57 + :operations="['向左移动','向右移动']"
5 58 filterable
6   - :render-format="rf"
7   - :filter-method="filterMethod"
8   - @on-change="handleChange2"></Transfer>
  59 + @on-change="handleChange3">
  60 + <div :style="{float: 'right', margin: '5px'}">
  61 + <Button type="ghost" size="small" @click.native="reloadMockData">刷新</Button>
  62 + </div>
  63 + </Transfer>
9 64 </template>
10 65 <script>
11 66 export default {
12 67 data () {
13 68 return {
14   - data2: this.getMockData(),
15   - targetKeys2: this.getTargetKeys()
  69 + data3: this.getMockData(),
  70 + targetKeys3: this.getTargetKeys(),
  71 + listStyle: {
  72 + width: '250px',
  73 + height: '300px'
  74 + }
16 75 }
17 76 },
18 77 methods: {
... ... @@ -30,18 +89,62 @@
30 89 },
31 90 getTargetKeys () {
32 91 return this.getMockData()
33   - .filter(() => Math.random() * 2 > 1)
34   - .map(item => item.key);
  92 + .filter(() => Math.random() * 2 > 1)
  93 + .map(item => item.key);
35 94 },
36   - handleChange2 (newTargetKeys) {
37   - this.targetKeys2 = newTargetKeys;
  95 + handleChange3 (newTargetKeys) {
  96 + this.targetKeys3 = newTargetKeys;
38 97 },
39   - filterMethod (data, query) {
40   - return data.label.indexOf(query) > -1;
  98 + render3 (item) {
  99 + return item.label + ' - ' + item.description;
41 100 },
42   - rf (data) {
43   - return '<i class="ivu-icon ivu-icon-alert"></i>' + data.label;
  101 + reloadMockData () {
  102 + this.data3 = this.getMockData();
  103 + this.targetKeys3 = this.getTargetKeys();
44 104 }
45 105 }
46 106 }
47 107 </script>
  108 +
  109 +<!--<template>-->
  110 + <!--<Transfer-->
  111 + <!--:data="data4"-->
  112 + <!--:target-keys="targetKeys4"-->
  113 + <!--:render-format="render4"-->
  114 + <!--@on-change="handleChange4"></Transfer>-->
  115 +<!--</template>-->
  116 +<!--<script>-->
  117 + <!--export default {-->
  118 + <!--data () {-->
  119 + <!--return {-->
  120 + <!--data4: this.getMockData(),-->
  121 + <!--targetKeys4: this.getTargetKeys()-->
  122 + <!--}-->
  123 + <!--},-->
  124 + <!--methods: {-->
  125 + <!--getMockData () {-->
  126 + <!--let mockData = [];-->
  127 + <!--for (let i = 1; i <= 20; i++) {-->
  128 + <!--mockData.push({-->
  129 + <!--key: i.toString(),-->
  130 + <!--label: '内容' + i,-->
  131 + <!--description: '内容' + i + '的描述信息',-->
  132 + <!--disabled: Math.random() * 3 < 1-->
  133 + <!--});-->
  134 + <!--}-->
  135 + <!--return mockData;-->
  136 + <!--},-->
  137 + <!--getTargetKeys () {-->
  138 + <!--return this.getMockData()-->
  139 + <!--.filter(() => Math.random() * 2 > 1)-->
  140 + <!--.map(item => item.key);-->
  141 + <!--},-->
  142 + <!--handleChange4 (newTargetKeys) {-->
  143 + <!--this.targetKeys4 = newTargetKeys;-->
  144 + <!--},-->
  145 + <!--render4 (item) {-->
  146 + <!--return item.label + ' - ' + item.description;-->
  147 + <!--}-->
  148 + <!--}-->
  149 + <!--}-->
  150 +<!--</script>-->
... ...
src/components/transfer/list.vue
1 1 <template>
2 2 <div :class="classes" :style="style">
3 3 <div :class="prefixCls + '-header'">
4   - <Checkbox :checked.sync="checkedAll" :disabled="checkedAllDisabled" @on-change="toggleSelectAll"></Checkbox>
  4 + <Checkbox :value="checkedAll" :disabled="checkedAllDisabled" @on-change="toggleSelectAll"></Checkbox>
5 5 <span>{{ title }}</span>
6 6 <span :class="prefixCls + '-header-count'">{{ count }}</span>
7 7 </div>
... ... @@ -9,21 +9,23 @@
9 9 <div :class="prefixCls + '-body-search-wrapper'" v-if="filterable">
10 10 <Search
11 11 :prefix-cls="prefixCls + '-search'"
12   - :query.sync="query"
  12 + :query="query"
  13 + @on-query-clear="handleQueryClear"
  14 + @on-query-change="handleQueryChange"
13 15 :placeholder="filterPlaceholder"></Search>
14 16 </div>
15 17 <ul :class="prefixCls + '-content'">
16 18 <li
17   - v-for="item in showItems | filterBy filterData"
  19 + v-for="item in filterData"
18 20 :class="itemClasses(item)"
19 21 @click.prevent="select(item)">
20   - <Checkbox :checked="isCheck(item)" :disabled="item.disabled"></Checkbox>
21   - <span>{{{ showLabel(item) }}}</span>
  22 + <Checkbox :value="isCheck(item)" :disabled="item.disabled"></Checkbox>
  23 + <span v-html="showLabel(item)"></span>
22 24 </li>
23 25 <li :class="prefixCls + '-content-not-found'">{{ notFoundText }}</li>
24 26 </ul>
25 27 </div>
26   - <div :class="prefixCls + '-footer'" v-if="showFooter" v-el:footer><slot></slot></div>
  28 + <div :class="prefixCls + '-footer'" v-if="showFooter"><slot></slot></div>
27 29 </div>
28 30 </template>
29 31 <script>
... ... @@ -31,6 +33,7 @@
31 33 import Checkbox from '../checkbox/checkbox.vue';
32 34  
33 35 export default {
  36 + name: 'TransferList',
34 37 components: { Search, Checkbox },
35 38 props: {
36 39 prefixCls: String,
... ... @@ -52,6 +55,11 @@
52 55 showFooter: true
53 56 };
54 57 },
  58 + watch: {
  59 + data () {
  60 + this.updateFilteredData();
  61 + }
  62 + },
55 63 computed: {
56 64 classes () {
57 65 return [
... ... @@ -79,6 +87,9 @@
79 87 },
80 88 checkedAllDisabled () {
81 89 return this.data.filter(data => !data.disabled).length <= 0;
  90 + },
  91 + filterData () {
  92 + return this.showItems.filter(item => this.filterMethod(item, this.query));
82 93 }
83 94 },
84 95 methods: {
... ... @@ -105,25 +116,23 @@
105 116 this.showItems = this.data;
106 117 },
107 118 toggleSelectAll (status) {
108   - this.checkedKeys = status ?
  119 + const keys = status ?
109 120 this.data.filter(data => !data.disabled || this.checkedKeys.indexOf(data.key) > -1).map(data => data.key) :
110 121 this.data.filter(data => data.disabled && this.checkedKeys.indexOf(data.key) > -1).map(data => data.key);
  122 + this.$emit('on-checked-keys-change', keys);
  123 + },
  124 + handleQueryClear () {
  125 + this.query = '';
111 126 },
112   - filterData (value) {
113   - return this.filterMethod(value, this.query);
  127 + handleQueryChange (val) {
  128 + this.query = val;
114 129 }
115 130 },
116 131 created () {
117 132 this.updateFilteredData();
118   -
119   - },
120   - compiled () {
121   - this.showFooter = this.$els.footer.innerHTML !== '';
122 133 },
123   - watch: {
124   - data () {
125   - this.updateFilteredData();
126   - }
  134 + mounted () {
  135 + this.showFooter = this.$slots.default !== undefined;
127 136 }
128 137 };
129 138 </script>
... ...
src/components/transfer/operation.vue
1 1 <template>
2 2 <div :class="prefixCls + '-operation'">
3   - <i-button type="primary" size="small" :disabled="!rightActive" @click="moveToLeft">
  3 + <i-button type="primary" size="small" :disabled="!rightActive" @click.native="moveToLeft">
4 4 <Icon type="ios-arrow-left"></Icon> {{ operations[0] }}
5 5 </i-button>
6   - <i-button type="primary" size="small" :disabled="!leftActive" @click="moveToRight">
  6 + <i-button type="primary" size="small" :disabled="!leftActive" @click.native="moveToRight">
7 7 {{ operations[1] }} <Icon type="ios-arrow-right"></Icon>
8 8 </i-button>
9 9 </div>
... ... @@ -13,6 +13,7 @@
13 13 import Icon from '../icon/icon.vue';
14 14  
15 15 export default {
  16 + name: 'Operation',
16 17 components: { iButton, Icon },
17 18 props: {
18 19 prefixCls: String,
... ...
src/components/transfer/search.vue
1 1 <template>
2 2 <div :class="prefixCls">
3 3 <i-input
4   - :value.sync="query"
  4 + v-model="currentQuery"
5 5 size="small"
6 6 :icon="icon"
7 7 :placeholder="placeholder"
... ... @@ -12,12 +12,26 @@
12 12 import iInput from '../input/input.vue';
13 13  
14 14 export default {
  15 + name: 'Search',
15 16 components: { iInput },
16 17 props: {
17 18 prefixCls: String,
18 19 placeholder: String,
19 20 query: String
20 21 },
  22 + data () {
  23 + return {
  24 + currentQuery: this.query
  25 + };
  26 + },
  27 + watch: {
  28 + query (val) {
  29 + this.currentQuery = val;
  30 + },
  31 + currentQuery (val) {
  32 + this.$emit('on-query-change', val);
  33 + }
  34 + },
21 35 computed: {
22 36 icon () {
23 37 return this.query === '' ? 'ios-search' : 'ios-close';
... ... @@ -25,17 +39,19 @@
25 39 },
26 40 methods: {
27 41 handleClick () {
28   - if (this.query === '') return;
29   - this.query = '';
30   - }
31   - },
32   - events: {
33   - 'on-form-blur' () {
34   - return false;
35   - },
36   - 'on-form-change' () {
37   - return false;
  42 + if (this.currentQuery === '') return;
  43 + this.currentQuery = '';
  44 + this.$emit('on-query-clear');
38 45 }
39 46 }
  47 + // todo 事件
  48 +// events: {
  49 +// 'on-form-blur' () {
  50 +// return false;
  51 +// },
  52 +// 'on-form-change' () {
  53 +// return false;
  54 +// }
  55 +// }
40 56 };
41 57 </script>
... ...
src/components/transfer/transfer.vue
1 1 <template>
2 2 <div :class="classes">
3 3 <List
4   - v-ref:left
  4 + ref="left"
5 5 :prefix-cls="prefixCls + '-list'"
6 6 :data="leftData"
7 7 :render-format="renderFormat"
8   - :checked-keys.sync="leftCheckedKeys"
9   - :valid-keys-count.sync="leftValidKeysCount"
  8 + :checked-keys="leftCheckedKeys"
  9 + @on-checked-keys-change="handleLeftCheckedKeysChange"
  10 + :valid-keys-count="leftValidKeysCount"
10 11 :style="listStyle"
11 12 :title="titles[0]"
12 13 :filterable="filterable"
... ... @@ -19,19 +20,20 @@
19 20 :operations="operations"
20 21 :left-active="leftValidKeysCount > 0"
21 22 :right-active="rightValidKeysCount > 0"></Operation><List
22   - v-ref:right
  23 + ref="right"
23 24 :prefix-cls="prefixCls + '-list'"
24 25 :data="rightData"
25 26 :render-format="renderFormat"
26   - :checked-keys.sync="rightCheckedKeys"
27   - :valid-keys-count.sync="rightValidKeysCount"
  27 + :checked-keys="rightCheckedKeys"
  28 + @on-checked-keys-change="handleRightCheckedKeysChange"
  29 + :valid-keys-count="rightValidKeysCount"
28 30 :style="listStyle"
29 31 :title="titles[1]"
30 32 :filterable="filterable"
31 33 :filter-placeholder="filterPlaceholder"
32 34 :filter-method="filterMethod"
33 35 :not-found-text="notFoundText">
34   - <slot></slot>
  36 + <slot name="right"></slot>
35 37 </List>
36 38 </div>
37 39 </template>
... ... @@ -177,7 +179,14 @@
177 179  
178 180 this.$refs[opposite].toggleSelectAll(false);
179 181 this.$emit('on-change', newTargetKeys, direction, moveKeys);
180   - this.$dispatch('on-form-change', newTargetKeys, direction, moveKeys);
  182 + // todo 事件
  183 +// this.$dispatch('on-form-change', newTargetKeys, direction, moveKeys);
  184 + },
  185 + handleLeftCheckedKeysChange (keys) {
  186 + this.leftCheckedKeys = keys;
  187 + },
  188 + handleRightCheckedKeysChange (keys) {
  189 + this.rightCheckedKeys = keys;
181 190 }
182 191 },
183 192 watch: {
... ...
src/index.js
... ... @@ -39,7 +39,7 @@ import Tag from &#39;./components/tag&#39;;
39 39 import Timeline from './components/timeline';
40 40 // import TimePicker from './components/time-picker';
41 41 import Tooltip from './components/tooltip';
42   -// import Transfer from './components/transfer';
  42 +import Transfer from './components/transfer';
43 43 import Tree from './components/tree';
44 44 import Upload from './components/upload';
45 45 import { Row, Col } from './components/grid';
... ... @@ -107,7 +107,7 @@ const iview = {
107 107 TimelineItem: Timeline.Item,
108 108 // TimePicker,
109 109 Tooltip,
110   - // Transfer,
  110 + Transfer,
111 111 Tree,
112 112 Upload
113 113 };
... ...