Commit a25314e846ea4fc00848bc66a85b5a240ac9ce29

Authored by Aresn
Committed by GitHub
2 parents 1c35a44d d77476f8

Merge pull request #4228 from VanMess/better-button

Better button
src/components/button/button.vue
1 1 <template>
2   - <a
3   - v-if="to"
4   - :class="classes"
5   - :disabled="disabled"
6   - :href="linkUrl"
7   - :target="target"
8   - @click.exact="handleClickLink($event, false)"
9   - @click.ctrl="handleClickLink($event, true)"
10   - @click.meta="handleClickLink($event, true)">
  2 + <component :is="tagName" :class="classes" :disabled="disabled" @click="handleClickLink" v-bind="tagProps">
11 3 <Icon class="ivu-load-loop" type="ios-loading" v-if="loading"></Icon>
12 4 <Icon :type="icon" :custom="customIcon" v-if="(icon || customIcon) && !loading"></Icon>
13 5 <span v-if="showSlot" ref="slot"><slot></slot></span>
14   - </a>
15   - <button
16   - v-else
17   - :type="htmlType"
18   - :class="classes"
19   - :disabled="disabled"
20   - @click="handleClickLink">
21   - <Icon class="ivu-load-loop" type="ios-loading" v-if="loading"></Icon>
22   - <Icon :type="icon" :custom="customIcon" v-if="(icon || customIcon) && !loading"></Icon>
23   - <span v-if="showSlot" ref="slot"><slot></slot></span>
24   - </button>
  6 + </component>
25 7 </template>
26 8 <script>
27 9 import Icon from '../icon';
... ... @@ -98,14 +80,34 @@
98 80 [`${prefixCls}-ghost`]: this.ghost
99 81 }
100 82 ];
  83 + },
  84 + // Point out if it should render as <a> tag
  85 + isHrefPattern() {
  86 + const {to} = this;
  87 + return !!to;
  88 + },
  89 + tagName() {
  90 + const {isHrefPattern} = this;
  91 + return isHrefPattern ? 'a' : 'button';
  92 + },
  93 + tagProps() {
  94 + const {isHrefPattern} = this;
  95 + if(isHrefPattern) {
  96 + const {linkUrl,target}=this;
  97 + return {href: linkUrl, target};
  98 + } else {
  99 + const {htmlType} = this;
  100 + return {type: htmlType};
  101 + }
101 102 }
102 103 },
103 104 methods: {
104 105 // Ctrl or CMD and click, open in new window when use `to`
105   - handleClickLink (event, new_window = false) {
  106 + handleClickLink (event) {
106 107 this.$emit('click', event);
  108 + const openInNewWindow = event.ctrlKey || event.metaKey;
107 109  
108   - this.handleCheckClick(event, new_window);
  110 + this.handleCheckClick(event, openInNewWindow);
109 111 }
110 112 },
111 113 mounted () {
... ...
test/unit/specs/button.spec.js 0 → 100644
  1 +import { createVue, destroyVM } from '../util';
  2 +
  3 +describe('Button.vue', () => {
  4 + let vm;
  5 + afterEach(() => {
  6 + destroyVM(vm);
  7 + });
  8 +
  9 + it('should render as <a>', done => {
  10 + vm = createVue(`
  11 + <Button to="http://www.thinkinfe.tech/">Think in FE</Button>
  12 + `);
  13 + expect(vm.$el.tagName).to.equal('A');
  14 + done();
  15 + });
  16 +
  17 + it('should render as <button>', done => {
  18 + vm = createVue(`
  19 + <Button>Think in FE</Button>
  20 + `);
  21 + expect(vm.$el.tagName).to.equal('BUTTON');
  22 + done();
  23 + });
  24 +
  25 + it('handle with `type` attribute', done => {
  26 + // should render with `type` attribute
  27 + // if it is a <button>
  28 + vm = createVue(`
  29 + <Button htmlType="reset">Think in FE</Button>
  30 + `);
  31 + expect(vm.$el.getAttribute('type')).to.equal('reset');
  32 +
  33 + // should't render with `type` attribute
  34 + // if it is a <button>
  35 + vm = createVue(`
  36 + <Button to="http://www.thinkinfe.tech/" htmlType="reset">Think in FE</Button>
  37 + `);
  38 + expect(vm.$el.getAttribute('type')).to.equal(null);
  39 + done();
  40 + });
  41 +
  42 + it('should change loading state', done => {
  43 + vm = createVue({
  44 + template: `
  45 + <Button :loading="loading" @click="fetch">Think in FE</Button>
  46 + `,
  47 + data() {
  48 + return {loading: false};
  49 + },
  50 + methods: {
  51 + fetch() {
  52 + this.loading = true;
  53 + }
  54 + }
  55 + });
  56 + vm.$el.click();
  57 + vm.$nextTick(() => {
  58 + expect(vm.$el.classList.contains('ivu-btn-loading')).to.equal(true);
  59 + const $icons = vm.$el.querySelectorAll('.ivu-icon');
  60 + expect($icons.length).to.equal(1);
  61 + expect($icons[0].classList.contains('ivu-load-loop')).to.equal(true);
  62 + expect($icons[0].classList.contains('ivu-icon-ios-loading')).to.equal(true);
  63 + done();
  64 + });
  65 + });
  66 +});
... ...