feat(Form): support using switch

This commit is contained in:
陈嘉涵 2020-02-10 16:30:17 +08:00
parent 0e23124c3a
commit 1db9536182
6 changed files with 125 additions and 110 deletions

View File

@ -1,13 +1,14 @@
<template> <template>
<demo-block :title="$t('fieldType')"> <demo-block :title="$t('fieldType')">
<van-form> <van-form @submit="onSubmit">
<van-field <van-field name="checkbox" :label="$t('checkbox')">
name="checkbox"
:label="$t('checkbox')"
:rules="[{ required: true, message: $t('requireCheckbox') }]"
>
<van-checkbox v-model="checkbox" slot="input" shape="square" /> <van-checkbox v-model="checkbox" slot="input" shape="square" />
</van-field> </van-field>
<van-field name="switch" :label="$t('switch')">
<van-switch v-model="switchChecked" slot="input" size="24" />
</van-field>
<div style="margin: 16px;"> <div style="margin: 16px;">
<van-button type="info" round block>{{ $t('submit') }}</van-button> <van-button type="info" round block>{{ $t('submit') }}</van-button>
</div> </div>
@ -20,12 +21,14 @@ export default {
i18n: { i18n: {
'zh-CN': { 'zh-CN': {
submit: '提交', submit: '提交',
switch: '开关',
checkbox: '复选框', checkbox: '复选框',
fieldType: '表单项类型', fieldType: '表单项类型',
requireCheckbox: '请勾选复选框', requireCheckbox: '请勾选复选框',
}, },
'en-US': { 'en-US': {
submit: 'Submit', submit: 'Submit',
switch: 'Switch',
checkbox: 'Checkbox', checkbox: 'Checkbox',
fieldType: 'Field Type', fieldType: 'Field Type',
requireCheckbox: 'Checkbox is required', requireCheckbox: 'Checkbox is required',
@ -35,7 +38,14 @@ export default {
data() { data() {
return { return {
checkbox: false, checkbox: false,
switchChecked: false,
}; };
}, },
methods: {
onSubmit(values) {
console.log(values);
},
},
}; };
</script> </script>

View File

View File

@ -5,22 +5,27 @@ exports[`renders demo correctly 1`] = `
<div> <div>
<form class="van-form"> <form class="van-form">
<div class="van-cell van-field"> <div class="van-cell van-field">
<div class="van-cell__title van-field__label"><span>username</span></div> <div class="van-cell__title van-field__label"><span>用户名</span></div>
<div class="van-cell__value"> <div class="van-cell__value">
<div class="van-field__body"><input type="text" name="username" placeholder="username" class="van-field__control"></div> <div class="van-field__body"><input type="text" name="username" placeholder="用户名" class="van-field__control"></div>
</div> </div>
</div> </div>
<div class="van-cell van-field"> <div class="van-cell van-field">
<div class="van-cell__title van-field__label"><span>password</span></div> <div class="van-cell__title van-field__label"><span>密码</span></div>
<div class="van-cell__value"> <div class="van-cell__value">
<div class="van-field__body"><input type="password" name="password" placeholder="password" class="van-field__control"></div> <div class="van-field__body"><input type="password" name="password" placeholder="密码" class="van-field__control"></div>
</div> </div>
</div> </div>
<div style="margin: 16px;"><button class="van-button van-button--info van-button--normal van-button--block van-button--round"><span class="van-button__text">提交</span></button></div>
</form>
</div>
<div>
<form class="van-form">
<div class="van-cell van-field"> <div class="van-cell van-field">
<div class="van-cell__title van-field__label"><span>agree</span></div> <div class="van-cell__title van-field__label"><span>复选框</span></div>
<div class="van-cell__value"> <div class="van-cell__value">
<div class="van-field__body"> <div class="van-field__body">
<div class="van-field__control"> <div class="van-field__control van-field__control--custom">
<div role="checkbox" tabindex="0" aria-checked="false" class="van-checkbox"> <div role="checkbox" tabindex="0" aria-checked="false" class="van-checkbox">
<div class="van-checkbox__icon van-checkbox__icon--square"><i class="van-icon van-icon-success"> <div class="van-checkbox__icon van-checkbox__icon--square"><i class="van-icon van-icon-success">
<!----></i></div> <!----></i></div>
@ -28,7 +33,20 @@ exports[`renders demo correctly 1`] = `
</div> </div>
</div> </div>
</div> </div>
</div> <button class="van-button van-button--primary van-button--normal"><span class="van-button__text">submit</span></button> </div>
<div class="van-cell van-field">
<div class="van-cell__title van-field__label"><span>开关</span></div>
<div class="van-cell__value">
<div class="van-field__body">
<div class="van-field__control van-field__control--custom">
<div role="switch" aria-checked="false" class="van-switch" style="font-size: 24px;">
<div class="van-switch__node"></div>
</div>
</div>
</div>
</div>
</div>
<div style="margin: 16px;"><button class="van-button van-button--info van-button--normal van-button--block van-button--round"><span class="van-button__text">提交</span></button></div>
</form> </form>
</div> </div>
</div> </div>

73
src/switch/index.js Normal file
View File

@ -0,0 +1,73 @@
// Utils
import { createNamespace, addUnit } from '../utils';
import { BLUE } from '../utils/constant';
import { switchProps } from './shared';
// Mixins
import { FieldMixin } from '../mixins/field';
// Components
import Loading from '../loading';
const [createComponent, bem] = createNamespace('switch');
export default createComponent({
mixins: [FieldMixin],
props: switchProps,
computed: {
checked() {
return this.value === this.activeValue;
},
style() {
return {
fontSize: addUnit(this.size),
backgroundColor: this.checked ? this.activeColor : this.inactiveColor,
};
},
},
methods: {
onClick(event) {
this.$emit('click', event);
if (!this.disabled && !this.loading) {
const newValue = this.checked ? this.inactiveValue : this.activeValue;
this.$emit('input', newValue);
this.$emit('change', newValue);
}
},
genLoading() {
if (this.loading) {
const color = this.checked
? this.activeColor || BLUE
: this.inactiveColor || '';
return <Loading class={bem('loading')} color={color} />;
}
},
},
render() {
const { checked, loading, disabled } = this;
return (
<div
class={bem({
on: checked,
loading,
disabled,
})}
role="switch"
style={this.style}
aria-checked={String(checked)}
onClick={this.onClick}
>
<div class={bem('node')}>{this.genLoading()}</div>
</div>
);
},
});

View File

@ -1,78 +0,0 @@
// Utils
import { createNamespace, addUnit } from '../utils';
import { BLUE } from '../utils/constant';
import { emit, inherit } from '../utils/functional';
import { switchProps, SharedSwitchProps } from './shared';
// Components
import Loading from '../loading';
// Types
import { CreateElement, RenderContext } from 'vue/types';
import { DefaultSlots } from '../utils/types';
export type SwitchEvents = {
onChange?(checked: boolean): void;
};
const [createComponent, bem] = createNamespace('switch');
function Switch(
h: CreateElement,
props: SharedSwitchProps,
slots: DefaultSlots,
ctx: RenderContext<SharedSwitchProps>
) {
const {
size,
value,
loading,
disabled,
activeColor,
activeValue,
inactiveColor,
inactiveValue,
} = props;
const checked = value === activeValue;
const switchStyle = {
fontSize: addUnit(size),
backgroundColor: checked ? activeColor : inactiveColor,
};
const loadingColor = checked ? activeColor || BLUE : inactiveColor || '';
function onClick(event: PointerEvent) {
emit(ctx, 'click', event);
if (!disabled && !loading) {
const newValue = checked ? inactiveValue : activeValue;
emit(ctx, 'input', newValue);
emit(ctx, 'change', newValue);
}
}
return (
<div
class={bem({
on: checked,
loading,
disabled,
})}
role="switch"
style={switchStyle}
aria-checked={String(checked)}
onClick={onClick}
{...inherit(ctx)}
>
<div class={bem('node')}>
{loading && <Loading class={bem('loading')} color={loadingColor} />}
</div>
</div>
);
}
Switch.props = switchProps;
export default createComponent<SharedSwitchProps, SwitchEvents>(Switch);

View File

@ -5,11 +5,9 @@ test('emit event', () => {
const input = jest.fn(); const input = jest.fn();
const change = jest.fn(); const change = jest.fn();
const wrapper = mount(Switch, { const wrapper = mount(Switch, {
context: { listeners: {
on: { input,
input, change,
change,
},
}, },
}); });
wrapper.trigger('click'); wrapper.trigger('click');
@ -22,11 +20,9 @@ test('disabled', () => {
const input = jest.fn(); const input = jest.fn();
const change = jest.fn(); const change = jest.fn();
const wrapper = mount(Switch, { const wrapper = mount(Switch, {
context: { listeners: {
on: { input,
input, change,
change,
},
}, },
propsData: { propsData: {
disabled: true, disabled: true,
@ -47,11 +43,9 @@ test('active-value & inactive-value prop', () => {
activeValue: '1', activeValue: '1',
inactiveValue: '2', inactiveValue: '2',
}, },
context: { listeners: {
on: { input,
input, change,
change,
},
}, },
}); });
@ -86,10 +80,8 @@ test('size prop', () => {
test('click event', () => { test('click event', () => {
const click = jest.fn(); const click = jest.fn();
const wrapper = mount(Switch, { const wrapper = mount(Switch, {
context: { listeners: {
on: { click,
click,
},
}, },
}); });