Commit 30510c3d9e7850fb52691a6f9fdc5a7592002591
1 parent
b2d29401
support Tabs
support Tabs
Showing
8 changed files
with
98 additions
and
38 deletions
Show diff stats
CHANGE.md
| ... | ... | @@ -25,4 +25,6 @@ class 改为了 className |
| 25 | 25 | ### Tree |
| 26 | 26 | 废弃 data,改为 value,使用 v-model,key 更名为 name,不能再 template 的prop 上使用 this |
| 27 | 27 | ### Circle |
| 28 | -改名为 iCircle | |
| 29 | 28 | \ No newline at end of file |
| 29 | +改名为 iCircle | |
| 30 | +### Tabs | |
| 31 | +废弃 activeKey,改用 value,使用 v-model,key 更名为 name | |
| 30 | 32 | \ No newline at end of file | ... | ... |
README.md
src/components/tabs/pane.vue
| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | export default { |
| 8 | 8 | name: 'TabPane', |
| 9 | 9 | props: { |
| 10 | - key: { | |
| 10 | + name: { | |
| 11 | 11 | type: String |
| 12 | 12 | }, |
| 13 | 13 | label: { |
| ... | ... | @@ -29,7 +29,8 @@ |
| 29 | 29 | data () { |
| 30 | 30 | return { |
| 31 | 31 | prefixCls: prefixCls, |
| 32 | - show: true | |
| 32 | + show: true, | |
| 33 | + currentName: this.name | |
| 33 | 34 | }; |
| 34 | 35 | }, |
| 35 | 36 | methods: { |
| ... | ... | @@ -38,6 +39,10 @@ |
| 38 | 39 | } |
| 39 | 40 | }, |
| 40 | 41 | watch: { |
| 42 | + name (val) { | |
| 43 | + this.currentName = val; | |
| 44 | + this.updateNav(); | |
| 45 | + }, | |
| 41 | 46 | label () { |
| 42 | 47 | this.updateNav(); |
| 43 | 48 | }, |
| ... | ... | @@ -48,7 +53,7 @@ |
| 48 | 53 | this.updateNav(); |
| 49 | 54 | } |
| 50 | 55 | }, |
| 51 | - ready () { | |
| 56 | + mounted () { | |
| 52 | 57 | this.updateNav(); |
| 53 | 58 | } |
| 54 | 59 | }; | ... | ... |
src/components/tabs/tabs.vue
| ... | ... | @@ -4,12 +4,12 @@ |
| 4 | 4 | <div :class="[prefixCls + '-nav-container']"> |
| 5 | 5 | <div :class="[prefixCls + '-nav-wrap']"> |
| 6 | 6 | <div :class="[prefixCls + '-nav-scroll']"> |
| 7 | - <div :class="[prefixCls + '-nav']" v-el:nav> | |
| 7 | + <div :class="[prefixCls + '-nav']" ref="nav"> | |
| 8 | 8 | <div :class="barClasses" :style="barStyle"></div> |
| 9 | - <div :class="tabCls(item)" v-for="item in navList" @click="handleChange($index)"> | |
| 9 | + <div :class="tabCls(item)" v-for="(item, index) in navList" @click="handleChange(index)"> | |
| 10 | 10 | <Icon v-if="item.icon !== ''" :type="item.icon"></Icon> |
| 11 | 11 | {{ item.label }} |
| 12 | - <Icon v-if="showClose(item)" type="ios-close-empty" @click.stop="handleRemove($index)"></Icon> | |
| 12 | + <Icon v-if="showClose(item)" type="ios-close-empty" @click.native.stop="handleRemove(index)"></Icon> | |
| 13 | 13 | </div> |
| 14 | 14 | </div> |
| 15 | 15 | </div> |
| ... | ... | @@ -26,9 +26,10 @@ |
| 26 | 26 | const prefixCls = 'ivu-tabs'; |
| 27 | 27 | |
| 28 | 28 | export default { |
| 29 | + name: 'Tabs', | |
| 29 | 30 | components: { Icon }, |
| 30 | 31 | props: { |
| 31 | - activeKey: { | |
| 32 | + value: { | |
| 32 | 33 | type: [String, Number] |
| 33 | 34 | }, |
| 34 | 35 | type: { |
| ... | ... | @@ -57,7 +58,8 @@ |
| 57 | 58 | prefixCls: prefixCls, |
| 58 | 59 | navList: [], |
| 59 | 60 | barWidth: 0, |
| 60 | - barOffset: 0 | |
| 61 | + barOffset: 0, | |
| 62 | + activeKey: this.value | |
| 61 | 63 | }; |
| 62 | 64 | }, |
| 63 | 65 | computed: { |
| ... | ... | @@ -88,7 +90,7 @@ |
| 88 | 90 | ]; |
| 89 | 91 | }, |
| 90 | 92 | contentStyle () { |
| 91 | - const x = this.navList.findIndex((nav) => nav.key === this.activeKey); | |
| 93 | + const x = this.navList.findIndex((nav) => nav.name === this.activeKey); | |
| 92 | 94 | const p = x === 0 ? '0%' : `-${x}00%`; |
| 93 | 95 | |
| 94 | 96 | let style = {}; |
| ... | ... | @@ -124,13 +126,13 @@ |
| 124 | 126 | this.navList.push({ |
| 125 | 127 | label: pane.label, |
| 126 | 128 | icon: pane.icon || '', |
| 127 | - key: pane.key || index, | |
| 129 | + name: pane.currentName || index, | |
| 128 | 130 | disabled: pane.disabled, |
| 129 | 131 | closable: pane.closable |
| 130 | 132 | }); |
| 131 | - if (!pane.key) pane.key = index; | |
| 133 | + if (!pane.currentName) pane.currentName = index; | |
| 132 | 134 | if (index === 0) { |
| 133 | - if (!this.activeKey) this.activeKey = pane.key || index; | |
| 135 | + if (!this.activeKey) this.activeKey = pane.currentName || index; | |
| 134 | 136 | } |
| 135 | 137 | }); |
| 136 | 138 | this.updateStatus(); |
| ... | ... | @@ -138,8 +140,8 @@ |
| 138 | 140 | }, |
| 139 | 141 | updateBar () { |
| 140 | 142 | this.$nextTick(() => { |
| 141 | - const index = this.navList.findIndex((nav) => nav.key === this.activeKey); | |
| 142 | - const prevTabs = this.$els.nav.querySelectorAll(`.${prefixCls}-tab`); | |
| 143 | + const index = this.navList.findIndex((nav) => nav.name === this.activeKey); | |
| 144 | + const prevTabs = this.$refs.nav.querySelectorAll(`.${prefixCls}-tab`); | |
| 143 | 145 | const tab = prevTabs[index]; |
| 144 | 146 | this.barWidth = parseFloat(getStyle(tab, 'width')); |
| 145 | 147 | |
| ... | ... | @@ -158,29 +160,30 @@ |
| 158 | 160 | }, |
| 159 | 161 | updateStatus () { |
| 160 | 162 | const tabs = this.getTabs(); |
| 161 | - tabs.forEach(tab => tab.show = (tab.key === this.activeKey) || this.animated); | |
| 163 | + tabs.forEach(tab => tab.show = (tab.currentName === this.activeKey) || this.animated); | |
| 162 | 164 | }, |
| 163 | 165 | tabCls (item) { |
| 164 | 166 | return [ |
| 165 | 167 | `${prefixCls}-tab`, |
| 166 | 168 | { |
| 167 | 169 | [`${prefixCls}-tab-disabled`]: item.disabled, |
| 168 | - [`${prefixCls}-tab-active`]: item.key === this.activeKey | |
| 170 | + [`${prefixCls}-tab-active`]: item.name === this.activeKey | |
| 169 | 171 | } |
| 170 | 172 | ]; |
| 171 | 173 | }, |
| 172 | 174 | handleChange (index) { |
| 173 | 175 | const nav = this.navList[index]; |
| 174 | 176 | if (nav.disabled) return; |
| 175 | - this.activeKey = nav.key; | |
| 176 | - this.$emit('on-click', nav.key); | |
| 177 | + this.activeKey = nav.name; | |
| 178 | + this.$emit('input', nav.name); | |
| 179 | + this.$emit('on-click', nav.name); | |
| 177 | 180 | }, |
| 178 | 181 | handleRemove (index) { |
| 179 | 182 | const tabs = this.getTabs(); |
| 180 | 183 | const tab = tabs[index]; |
| 181 | 184 | tab.$destroy(true); |
| 182 | 185 | |
| 183 | - if (tab.key === this.activeKey) { | |
| 186 | + if (tab.currentName === this.activeKey) { | |
| 184 | 187 | const newTabs = this.getTabs(); |
| 185 | 188 | let activeKey = -1; |
| 186 | 189 | |
| ... | ... | @@ -189,16 +192,16 @@ |
| 189 | 192 | const rightNoDisabledTabs = tabs.filter((item, itemIndex) => !item.disabled && itemIndex > index); |
| 190 | 193 | |
| 191 | 194 | if (rightNoDisabledTabs.length) { |
| 192 | - activeKey = rightNoDisabledTabs[0].key; | |
| 195 | + activeKey = rightNoDisabledTabs[0].currentName; | |
| 193 | 196 | } else if (leftNoDisabledTabs.length) { |
| 194 | - activeKey = leftNoDisabledTabs[leftNoDisabledTabs.length - 1].key; | |
| 197 | + activeKey = leftNoDisabledTabs[leftNoDisabledTabs.length - 1].currentName; | |
| 195 | 198 | } else { |
| 196 | - activeKey = newTabs[0].key; | |
| 199 | + activeKey = newTabs[0].currentName; | |
| 197 | 200 | } |
| 198 | 201 | } |
| 199 | 202 | this.activeKey = activeKey; |
| 200 | 203 | } |
| 201 | - this.$emit('on-tab-remove', tab.key); | |
| 204 | + this.$emit('on-tab-remove', tab.currentName); | |
| 202 | 205 | this.updateNav(); |
| 203 | 206 | }, |
| 204 | 207 | showClose (item) { |
| ... | ... | @@ -214,6 +217,9 @@ |
| 214 | 217 | } |
| 215 | 218 | }, |
| 216 | 219 | watch: { |
| 220 | + value (val) { | |
| 221 | + this.activeKey = val; | |
| 222 | + }, | |
| 217 | 223 | activeKey () { |
| 218 | 224 | this.updateBar(); |
| 219 | 225 | this.updateStatus(); | ... | ... |
src/index.js
| ... | ... | @@ -34,7 +34,7 @@ import Rate from './components/rate'; |
| 34 | 34 | import Steps from './components/steps'; |
| 35 | 35 | import Switch from './components/switch'; |
| 36 | 36 | // import Table from './components/table'; |
| 37 | -// import Tabs from './components/tabs'; | |
| 37 | +import Tabs from './components/tabs'; | |
| 38 | 38 | import Tag from './components/tag'; |
| 39 | 39 | import Timeline from './components/timeline'; |
| 40 | 40 | // import TimePicker from './components/time-picker'; |
| ... | ... | @@ -100,8 +100,8 @@ const iview = { |
| 100 | 100 | Steps, |
| 101 | 101 | iSwitch: Switch, |
| 102 | 102 | // iTable: Table, |
| 103 | - // Tabs: Tabs, | |
| 104 | - // TabPane: Tabs.Pane, | |
| 103 | + Tabs: Tabs, | |
| 104 | + TabPane: Tabs.Pane, | |
| 105 | 105 | Tag, |
| 106 | 106 | Timeline, |
| 107 | 107 | TimelineItem: Timeline.Item, | ... | ... |
test/app.vue
| ... | ... | @@ -34,6 +34,7 @@ li + li { border-left: solid 1px #bbb; padding-left: 10px; margin-left: 10px; } |
| 34 | 34 | <li><router-link to="/tree">Tree</router-link></li> |
| 35 | 35 | <li><router-link to="/rate">Rate</router-link></li> |
| 36 | 36 | <li><router-link to="/circle">Circle</router-link></li> |
| 37 | + <li><router-link to="/tabs">Tabs</router-link></li> | |
| 37 | 38 | </ul> |
| 38 | 39 | </nav> |
| 39 | 40 | <router-view></router-view> | ... | ... |
test/main.js
test/routers/tabs.vue
| 1 | +<style> | |
| 2 | + .demo-tabs-style1 > .ivu-tabs-card > .ivu-tabs-content { | |
| 3 | + height: 120px; | |
| 4 | + margin-top: -16px; | |
| 5 | + } | |
| 6 | + | |
| 7 | + .demo-tabs-style1 > .ivu-tabs-card > .ivu-tabs-content > .ivu-tabs-tabpane { | |
| 8 | + background: #fff; | |
| 9 | + padding: 16px; | |
| 10 | + } | |
| 11 | + | |
| 12 | + .demo-tabs-style1 > .ivu-tabs.ivu-tabs-card > .ivu-tabs-bar .ivu-tabs-tab { | |
| 13 | + border-color: transparent; | |
| 14 | + } | |
| 15 | + | |
| 16 | + .demo-tabs-style1 > .ivu-tabs-card > .ivu-tabs-bar .ivu-tabs-tab-active { | |
| 17 | + border-color: #fff; | |
| 18 | + } | |
| 19 | + .demo-tabs-style2 > .ivu-tabs.ivu-tabs-card > .ivu-tabs-bar .ivu-tabs-tab{ | |
| 20 | + border-radius: 0; | |
| 21 | + background: #fff; | |
| 22 | + } | |
| 23 | + .demo-tabs-style2 > .ivu-tabs.ivu-tabs-card > .ivu-tabs-bar .ivu-tabs-tab-active{ | |
| 24 | + border-top: 1px solid #3399ff; | |
| 25 | + } | |
| 26 | + .demo-tabs-style2 > .ivu-tabs.ivu-tabs-card > .ivu-tabs-bar .ivu-tabs-tab-active:before{ | |
| 27 | + content: ''; | |
| 28 | + display: block; | |
| 29 | + width: 100%; | |
| 30 | + height: 1px; | |
| 31 | + background: #3399ff; | |
| 32 | + position: absolute; | |
| 33 | + top: 0; | |
| 34 | + left: 0; | |
| 35 | + } | |
| 36 | +</style> | |
| 1 | 37 | <template> |
| 2 | - <Tabs active-key="key1"> | |
| 3 | - <Tab-pane label="标签一" key="key1">标签一的内容</Tab-pane> | |
| 4 | - <Tab-pane label="标签二" key="key2">标签二的内容</Tab-pane> | |
| 5 | - <Tab-pane label="标签三" key="key3">标签三的内容</Tab-pane> | |
| 6 | - </Tabs> | |
| 7 | - <Tabs type="card" > | |
| 8 | - <Tab-pane label="标签一">标签一的内容</Tab-pane> | |
| 9 | - <Tab-pane label="标签二" :closable="true">标签二的内容</Tab-pane> | |
| 10 | - <Tab-pane label="标签三">标签三的内容</Tab-pane> | |
| 11 | - </Tabs> | |
| 38 | + <Row :gutter="32"> | |
| 39 | + <i-col span="12" class="demo-tabs-style1" style="background: #e3e8ee;padding:16px;"> | |
| 40 | + <Tabs type="card"> | |
| 41 | + <Tab-pane label="标签一">标签一的内容</Tab-pane> | |
| 42 | + <Tab-pane label="标签二">标签二的内容</Tab-pane> | |
| 43 | + <Tab-pane label="标签三">标签三的内容</Tab-pane> | |
| 44 | + </Tabs> | |
| 45 | + </i-col> | |
| 46 | + <i-col span="12" class="demo-tabs-style2"> | |
| 47 | + <Tabs type="card"> | |
| 48 | + <Tab-pane label="标签一">标签一的内容</Tab-pane> | |
| 49 | + <Tab-pane label="标签二">标签二的内容</Tab-pane> | |
| 50 | + <Tab-pane label="标签三">标签三的内容</Tab-pane> | |
| 51 | + </Tabs> | |
| 52 | + </i-col> | |
| 53 | + </Row> | |
| 12 | 54 | </template> |
| 13 | 55 | <script> |
| 14 | 56 | export default { | ... | ... |