mirror of
https://gitee.com/ant-design-vue/ant-design-vue.git
synced 2024-11-29 18:48:32 +08:00
add switch fix spin demo
This commit is contained in:
parent
5471f29705
commit
06cf31cd60
@ -17,6 +17,7 @@ const md = {
|
||||
|
||||
- 对复杂区域进行分组和隐藏,保持页面的整洁。
|
||||
- '手风琴' 是一种特殊的折叠面板,只允许单个内容区域展开。
|
||||
|
||||
## 代码演示`,
|
||||
us: `# When To Use
|
||||
|
||||
|
@ -9,6 +9,7 @@ const md = {
|
||||
## 何时使用
|
||||
- 对不同章节的文本段落进行分割。
|
||||
- 对行内文字/链接进行分割,例如表格的操作列。
|
||||
|
||||
## 代码演示`,
|
||||
us: `# Divider
|
||||
A divider line separates different content.
|
||||
|
@ -76,3 +76,5 @@ const SelectOption = Select.Option
|
||||
const SelectOptGroup = Select.OptGroup
|
||||
export { Select, SelectOption, SelectOptGroup }
|
||||
|
||||
export { default as Switch } from './switch'
|
||||
|
||||
|
@ -11,6 +11,7 @@ const md = {
|
||||
## 何时使用
|
||||
- 可提供成功、警告和错误等反馈信息。
|
||||
- 顶部居中显示并自动消失,是一种不打断用户操作的轻量级提示方式。
|
||||
|
||||
## 代码演示`,
|
||||
us: `# Message
|
||||
Display global messages as feedback in response to user operations.
|
||||
|
@ -16,6 +16,7 @@ const md = {
|
||||
- 较为复杂的通知内容。
|
||||
- 带有交互的通知,给出用户下一步的行动点。
|
||||
- 系统主动推送。
|
||||
|
||||
## 代码演示`,
|
||||
us: `# Notification
|
||||
Display a notification message globally.
|
||||
|
@ -20,6 +20,7 @@ const md = {
|
||||
## 何时使用
|
||||
- 弹出一个下拉菜单给用户选择操作,用于代替原生的选择器,或者需要一个更优雅的多选器时。
|
||||
- 当选项少时(少于 5 项),建议直接将选项平铺,使用 [Radio](#/cn/components/radio/) 是更好的选择。
|
||||
|
||||
## 代码演示`,
|
||||
us: `# Select
|
||||
Select component to select value from options.
|
||||
|
@ -50,13 +50,13 @@ export default {
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
spinning (val) {
|
||||
const { delay, stateSpinning, spinning } = this
|
||||
spinning () {
|
||||
const { delay, spinning } = this
|
||||
|
||||
if (this.debounceTimeout) {
|
||||
clearTimeout(this.debounceTimeout)
|
||||
}
|
||||
if (stateSpinning && !spinning) {
|
||||
if (!spinning) {
|
||||
this.debounceTimeout = window.setTimeout(() => this.setState({ stateSpinning: spinning }), 200)
|
||||
if (this.delayTimeout) {
|
||||
clearTimeout(this.delayTimeout)
|
||||
|
@ -23,7 +23,7 @@ Specifies a delay for loading state. If `spinning` ends during delay, loading st
|
||||
可以点击‘切换’按钮,延迟显示 loading 效果。当 spinning 状态在 `delay` 时间内结束,则不显示 loading 状态。
|
||||
</div>
|
||||
</a-spin>
|
||||
<a-button @click="changeSpinning" style="margin-top: 5px">切换</a-button>
|
||||
Loading state:<a-switch v-model="spinning"></a-switch>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
@ -23,7 +23,7 @@ Embedding content into `Spin` will alter it into loading state.
|
||||
可以点击‘切换’按钮,控制本区域的spin展示。
|
||||
</div>
|
||||
</a-spin>
|
||||
<a-button @click="changeSpinning" style="margin-top: 5px">切换</a-button>
|
||||
Loading state:<a-switch v-model="spinning"></a-switch>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
|
@ -22,3 +22,4 @@ import './notification/style'
|
||||
import './message/style'
|
||||
import './spin/style'
|
||||
import './select/style'
|
||||
import './switch/style'
|
||||
|
30
components/switch/demo/basic.md
Normal file
30
components/switch/demo/basic.md
Normal file
@ -0,0 +1,30 @@
|
||||
<cn>
|
||||
#### 基本用法
|
||||
最简单的用法。
|
||||
</cn>
|
||||
|
||||
<us>
|
||||
#### basic Usage
|
||||
The most basic usage.
|
||||
</us>
|
||||
|
||||
```html
|
||||
<template>
|
||||
<div>
|
||||
<a-switch defaultChecked @change='onChange'/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onChange(checked){
|
||||
console.log(`a-switch to ${checked}`);
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
```
|
33
components/switch/demo/disabled.md
Normal file
33
components/switch/demo/disabled.md
Normal file
@ -0,0 +1,33 @@
|
||||
<cn>
|
||||
#### 不可用
|
||||
Switch 失效状态。
|
||||
</cn>
|
||||
|
||||
<us>
|
||||
#### Disabled
|
||||
Disabled state of `Switch`.
|
||||
</us>
|
||||
|
||||
```html
|
||||
<template>
|
||||
<div>
|
||||
<a-switch defaultChecked :disabled="disabled" style="margin-bottom:5px"/>
|
||||
<br/>
|
||||
<a-button type="primary" @click='onToggle'>Toggle disabled</Button>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
disabled: true,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onToggle(){
|
||||
this.disabled = !this.disabled
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
```
|
55
components/switch/demo/index.vue
Normal file
55
components/switch/demo/index.vue
Normal file
@ -0,0 +1,55 @@
|
||||
<script>
|
||||
import Basic from './basic'
|
||||
import Disabled from './disabled'
|
||||
import Text from './text'
|
||||
import Size from './size'
|
||||
import Loading from './loading'
|
||||
import CN from '../index.zh-CN.md'
|
||||
import US from '../index.en-US.md'
|
||||
|
||||
const md = {
|
||||
cn: `# Switch
|
||||
|
||||
开关选择器。
|
||||
|
||||
## 何时使用
|
||||
|
||||
- 需要表示开关状态/两种状态之间的切换时;
|
||||
- 和 'checkbox'的区别是,切换 'switch' 会直接触发状态改变,而 'checkbox' 一般用于状态标记,需要和提交操作配合。
|
||||
|
||||
## 代码演示`,
|
||||
us: `# Switch
|
||||
|
||||
Switching Selector.
|
||||
|
||||
## When To Use
|
||||
|
||||
- If you need to represent the switching between two states or on-off state.
|
||||
- The difference between 'Switch' and 'Checkbox' is that 'Switch' will trigger a state change directly when you toggle it, while 'Checkbox' is generally used for state marking, which should work in conjunction with submit operation.`,
|
||||
}
|
||||
export default {
|
||||
render () {
|
||||
return (
|
||||
<div>
|
||||
<md cn={md.cn} us={md.us}/>
|
||||
<Basic />
|
||||
<br/>
|
||||
<Disabled />
|
||||
<br/>
|
||||
<Text />
|
||||
<br/>
|
||||
<Size />
|
||||
<br/>
|
||||
<Loading />
|
||||
<br/>
|
||||
<api>
|
||||
<template slot='cn'>
|
||||
<CN/>
|
||||
</template>
|
||||
<US/>
|
||||
</api>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
}
|
||||
</script>
|
19
components/switch/demo/loading.md
Normal file
19
components/switch/demo/loading.md
Normal file
@ -0,0 +1,19 @@
|
||||
<cn>
|
||||
#### 加载中
|
||||
标识开关操作仍在执行中。
|
||||
</cn>
|
||||
|
||||
<us>
|
||||
#### Loading
|
||||
Mark a pending state of switch.
|
||||
</us>
|
||||
|
||||
```html
|
||||
<template>
|
||||
<div>
|
||||
<a-switch loading defaultChecked/>
|
||||
<br>
|
||||
<a-switch size="small" loading/>
|
||||
</div>
|
||||
</template>
|
||||
```
|
19
components/switch/demo/size.md
Normal file
19
components/switch/demo/size.md
Normal file
@ -0,0 +1,19 @@
|
||||
<cn>
|
||||
#### 两种大小
|
||||
`size="small"` 表示小号开关。
|
||||
</cn>
|
||||
|
||||
<us>
|
||||
#### Two sizes
|
||||
`size="small"` represents a small sized switch.
|
||||
</us>
|
||||
|
||||
```html
|
||||
<template>
|
||||
<div>
|
||||
<a-switch defaultChecked/>
|
||||
<br>
|
||||
<a-switch size="small" defaultChecked/>
|
||||
</div>
|
||||
</template>
|
||||
```
|
24
components/switch/demo/text.md
Normal file
24
components/switch/demo/text.md
Normal file
@ -0,0 +1,24 @@
|
||||
<cn>
|
||||
#### 文字和图标
|
||||
带有文字和图标。
|
||||
</cn>
|
||||
|
||||
<us>
|
||||
#### Text & icon
|
||||
With text and icon.
|
||||
</us>
|
||||
|
||||
```html
|
||||
<template>
|
||||
<div>
|
||||
<a-switch checkedChildren="开" unCheckedChildren="关" defaultChecked/>
|
||||
<br>
|
||||
<a-switch checkedChildren="1" unCheckedChildren="0"/>
|
||||
<br>
|
||||
<a-switch defaultChecked >
|
||||
<a-icon type="check" slot="checkedChildren"/>
|
||||
<a-icon type="cross" slot="unCheckedChildren"/>
|
||||
</a-switch>
|
||||
</div>
|
||||
</template>
|
||||
```
|
20
components/switch/index.en-US.md
Normal file
20
components/switch/index.en-US.md
Normal file
@ -0,0 +1,20 @@
|
||||
## API
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
| -------- | ----------- | ---- | ------- |
|
||||
| autoFocus | get focus when component mounted | boolean | false |
|
||||
| checked | determine whether the `Switch` is checked | boolean | false |
|
||||
| checkedChildren | content to be shown when the state is checked | string\|slot | |
|
||||
| defaultChecked | to set the initial state | boolean | false |
|
||||
| disabled | Disable switch | boolean | false |
|
||||
| loading | loading state of switch | boolean | false |
|
||||
| size | the size of the `Switch`, options: `default` `small` | string | default |
|
||||
| unCheckedChildren | content to be shown when the state is unchecked | string\|slot | |
|
||||
| onChange | a callback function, can be executed when the checked state is changing | Function(checked:Boolean) | |
|
||||
|
||||
## Methods
|
||||
|
||||
| Name | Description |
|
||||
| ---- | ----------- |
|
||||
| blur() | remove focus |
|
||||
| focus() | get focus |
|
75
components/switch/index.vue
Normal file
75
components/switch/index.vue
Normal file
@ -0,0 +1,75 @@
|
||||
<script>
|
||||
import PropTypes from '../_util/vue-types'
|
||||
import { getOptionProps } from '../_util/props-util'
|
||||
import VcSwitch from '../vc-switch'
|
||||
|
||||
export default {
|
||||
name: 'vSwitch',
|
||||
model: {
|
||||
prop: 'checked',
|
||||
event: 'change',
|
||||
},
|
||||
props: {
|
||||
prefixCls: PropTypes.string.def('ant-switch'),
|
||||
// size=default and size=large are the same
|
||||
size: PropTypes.oneOf(['small', 'default', 'large']),
|
||||
disabled: PropTypes.bool,
|
||||
checkedChildren: PropTypes.any,
|
||||
unCheckedChildren: PropTypes.any,
|
||||
tabIndex: PropTypes.number,
|
||||
checked: PropTypes.bool,
|
||||
defaultChecked: PropTypes.bool,
|
||||
autoFocus: PropTypes.bool,
|
||||
loading: PropTypes.bool,
|
||||
},
|
||||
monted () {
|
||||
this.$nextTick(() => {
|
||||
this.refSwitchNode = this.$refs.refSwitchNode
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
focus () {
|
||||
this.refSwitchNode.focus()
|
||||
},
|
||||
blur () {
|
||||
this.refSwitchNode.blur()
|
||||
},
|
||||
getChildren () {
|
||||
return {
|
||||
checkedChildren: this.$slots.checkedChildren || null,
|
||||
unCheckedChildren: this.$slots.unCheckedChildren || null,
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
render () {
|
||||
const { prefixCls, size, loading, ...restProps } = getOptionProps(this)
|
||||
const classes = {
|
||||
[`${prefixCls}-small`]: size === 'small',
|
||||
[`${prefixCls}-loading`]: loading,
|
||||
}
|
||||
const switchProps = {
|
||||
props: {
|
||||
...restProps,
|
||||
prefixCls,
|
||||
},
|
||||
on: this.$listeners,
|
||||
class: classes,
|
||||
ref: 'refSwitchNode',
|
||||
}
|
||||
const children = this.getChildren()
|
||||
return (
|
||||
<VcSwitch
|
||||
{...switchProps}
|
||||
>
|
||||
{children.checkedChildren ? (
|
||||
<template slot='checkedChildren'>{children.checkedChildren}</template>
|
||||
) : null}
|
||||
{children.unCheckedChildren ? (
|
||||
<template slot='unCheckedChildren'>{children.unCheckedChildren}</template>
|
||||
) : null}
|
||||
</VcSwitch>
|
||||
)
|
||||
},
|
||||
}
|
||||
</script>
|
20
components/switch/index.zh-CN.md
Normal file
20
components/switch/index.zh-CN.md
Normal file
@ -0,0 +1,20 @@
|
||||
## API
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
| --- | --- | --- | --- |
|
||||
| autoFocus | 组件自动获取焦点 | boolean | false |
|
||||
| checked | 指定当前是否选中 | boolean | false |
|
||||
| checkedChildren | 选中时的内容 | string\|slot | |
|
||||
| defaultChecked | 初始是否选中 | boolean | false |
|
||||
| disabled | 是否禁用 | boolean | false |
|
||||
| loading | 加载中的开关 | boolean | false |
|
||||
| size | 开关大小,可选值:`default` `small` | string | default |
|
||||
| unCheckedChildren | 非选中时的内容 | string\|slot | |
|
||||
| onChange | 变化时回调函数 | Function(checked:Boolean) | |
|
||||
|
||||
## 方法
|
||||
|
||||
| 名称 | 描述 |
|
||||
| --- | --- |
|
||||
| blur() | 移除焦点 |
|
||||
| focus() | 获取焦点 |
|
2
components/switch/style/index.js
Normal file
2
components/switch/style/index.js
Normal file
@ -0,0 +1,2 @@
|
||||
import '../../style/index.less'
|
||||
import './index.less'
|
165
components/switch/style/index.less
Normal file
165
components/switch/style/index.less
Normal file
@ -0,0 +1,165 @@
|
||||
@import "../../style/themes/default";
|
||||
@import "../../style/mixins/index";
|
||||
|
||||
@switch-prefix-cls: ~"@{ant-prefix}-switch";
|
||||
@switch-duration: .36s;
|
||||
|
||||
.@{switch-prefix-cls} {
|
||||
.reset-component;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
height: @switch-height;
|
||||
min-width: 44px;
|
||||
line-height: @switch-height - 2px;
|
||||
vertical-align: middle;
|
||||
border-radius: 100px;
|
||||
border: 1px solid transparent;
|
||||
background-color: @disabled-color;
|
||||
cursor: pointer;
|
||||
transition: all @switch-duration;
|
||||
user-select: none;
|
||||
|
||||
&-inner {
|
||||
color: #fff;
|
||||
font-size: @font-size-sm;
|
||||
margin-left: 24px;
|
||||
margin-right: 6px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
position: absolute;
|
||||
width: @switch-height - 4px;
|
||||
height: @switch-height - 4px;
|
||||
left: 1px;
|
||||
top: 1px;
|
||||
border-radius: 18px;
|
||||
background-color: @component-background;
|
||||
content: " ";
|
||||
cursor: pointer;
|
||||
transition: all @switch-duration @ease-in-out-circ;
|
||||
}
|
||||
|
||||
&:after {
|
||||
box-shadow: 0 2px 4px 0 rgba(0, 35, 11, .2);
|
||||
}
|
||||
|
||||
&:active:before,
|
||||
&:active:after {
|
||||
width: 24px;
|
||||
}
|
||||
|
||||
&:before {
|
||||
content: "\e64d";
|
||||
font-family: anticon;
|
||||
animation: loadingCircle 1s infinite linear;
|
||||
text-align: center;
|
||||
background: transprent;
|
||||
z-index: 1;
|
||||
display: none;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
&-loading:before {
|
||||
display: inline-block;
|
||||
color: @text-color;
|
||||
}
|
||||
|
||||
&-checked&-loading:before {
|
||||
color: @switch-color;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 2px fade(@switch-color, 20%);
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
&:focus:hover {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
&-small {
|
||||
height: @switch-sm-height;
|
||||
min-width: 28px;
|
||||
line-height: @switch-sm-height - 2px;
|
||||
|
||||
.@{switch-prefix-cls}-inner {
|
||||
margin-left: 18px;
|
||||
margin-right: 3px;
|
||||
font-size: @font-size-sm;
|
||||
}
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
width: @switch-sm-height - 4px;
|
||||
height: @switch-sm-height - 4px;
|
||||
}
|
||||
|
||||
&:active:before,
|
||||
&:active:after {
|
||||
width: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
&-small&-checked {
|
||||
&:before,
|
||||
&:after {
|
||||
left: 100%;
|
||||
margin-left: -12.5px;
|
||||
}
|
||||
|
||||
.@{switch-prefix-cls}-inner {
|
||||
margin-left: 3px;
|
||||
margin-right: 18px;
|
||||
}
|
||||
}
|
||||
|
||||
&-small:active&-checked:before,
|
||||
&-small:active&-checked:after {
|
||||
margin-left: -16.5px;
|
||||
}
|
||||
|
||||
&-small&-loading:before {
|
||||
animation: AntSwitchSmallLoadingCircle 1s infinite linear;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
&-checked {
|
||||
background-color: @switch-color;
|
||||
|
||||
.@{switch-prefix-cls}-inner {
|
||||
margin-left: 6px;
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
&:before,
|
||||
&:after {
|
||||
left: 100%;
|
||||
margin-left: -19px;
|
||||
}
|
||||
|
||||
&:active:before,
|
||||
&:active:after {
|
||||
margin-left: -25px;
|
||||
}
|
||||
}
|
||||
|
||||
&-loading,
|
||||
&-disabled {
|
||||
pointer-events: none;
|
||||
opacity: @switch-disabled-opacity;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes AntSwitchSmallLoadingCircle {
|
||||
0% {
|
||||
transform-origin: 50% 50%;
|
||||
transform: rotate(0deg) scale(0.66667);
|
||||
}
|
||||
100% {
|
||||
transform-origin: 50% 50%;
|
||||
transform: rotate(360deg) scale(0.66667);
|
||||
}
|
||||
}
|
15
components/vc-switch/PropTypes.js
Normal file
15
components/vc-switch/PropTypes.js
Normal file
@ -0,0 +1,15 @@
|
||||
import PropTypes from '../_util/vue-types'
|
||||
|
||||
export const switchPropTypes = {
|
||||
prefixCls: PropTypes.string,
|
||||
disabled: PropTypes.bool.def(false),
|
||||
checkedChildren: PropTypes.any,
|
||||
unCheckedChildren: PropTypes.any,
|
||||
// onChange: PropTypes.func,
|
||||
// onMouseUp: PropTypes.func,
|
||||
// onClick: PropTypes.func,
|
||||
tabIndex: PropTypes.number,
|
||||
checked: PropTypes.bool.def(false),
|
||||
defaultChecked: PropTypes.bool.def(false),
|
||||
autoFocus: PropTypes.bool.def(false),
|
||||
}
|
122
components/vc-switch/Switch.vue
Normal file
122
components/vc-switch/Switch.vue
Normal file
@ -0,0 +1,122 @@
|
||||
<script>
|
||||
import { switchPropTypes } from './PropTypes'
|
||||
import BaseMixin from '../_util/BaseMixin'
|
||||
import { hasProp, filterEmpty, getOptionProps } from '../_util/props-util'
|
||||
|
||||
// function noop () {
|
||||
// }
|
||||
export default {
|
||||
name: 'vc-switch',
|
||||
mixins: [BaseMixin],
|
||||
model: {
|
||||
prop: 'checked',
|
||||
event: 'change',
|
||||
},
|
||||
props: {
|
||||
...switchPropTypes,
|
||||
prefixCls: switchPropTypes.prefixCls.def('rc-switch'),
|
||||
checkedChildren: switchPropTypes.checkedChildren.def(null),
|
||||
unCheckedChildren: switchPropTypes.unCheckedChildren.def(null),
|
||||
defaultChecked: switchPropTypes.defaultChecked.def(''),
|
||||
// onChange: switchPropTypes.onChange.def(noop),
|
||||
// onClick: switchPropTypes.onClick.def(noop),
|
||||
},
|
||||
data () {
|
||||
let checked = false
|
||||
if (hasProp(this, 'checked')) {
|
||||
checked = !!this.checked
|
||||
} else {
|
||||
checked = !!this.defaultChecked
|
||||
}
|
||||
return {
|
||||
stateChecked: checked,
|
||||
}
|
||||
},
|
||||
monted () {
|
||||
this.$nextTick(() => {
|
||||
const { autoFocus, disabled } = this
|
||||
if (autoFocus && !disabled) {
|
||||
this.focus()
|
||||
}
|
||||
this.refSwitchNode = this.$refs.refSwitchNode
|
||||
})
|
||||
},
|
||||
watch: {
|
||||
checked (val) {
|
||||
this.stateChecked = val
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
setChecked (checked) {
|
||||
if (this.disabled) {
|
||||
return
|
||||
}
|
||||
if (!hasProp(this, 'checked')) {
|
||||
this.stateChecked = checked
|
||||
}
|
||||
this.$emit('change', checked)
|
||||
},
|
||||
toggle () {
|
||||
const checked = !this.stateChecked
|
||||
this.setChecked(checked)
|
||||
this.$emit('click', checked)
|
||||
},
|
||||
handleKeyDown (e) {
|
||||
if (e.keyCode === 37) { // Left
|
||||
this.setChecked(false)
|
||||
} else if (e.keyCode === 39) { // Right
|
||||
this.setChecked(true)
|
||||
} else if (e.keyCode === 32 || e.keyCode === 13) { // Space, Enter
|
||||
this.toggle()
|
||||
}
|
||||
},
|
||||
handleMouseUp (e) {
|
||||
if (this.refSwitchNode) {
|
||||
this.refSwitchNode.blur()
|
||||
}
|
||||
this.$emit('mouseUp', e)
|
||||
},
|
||||
focus () {
|
||||
this.refSwitchNode.focus()
|
||||
},
|
||||
blur () {
|
||||
this.refSwitchNode.blur()
|
||||
},
|
||||
getChildren (slotName) {
|
||||
if (hasProp(this, slotName)) {
|
||||
return this[slotName]
|
||||
}
|
||||
if (this.$slots && this.$slots[slotName]) {
|
||||
return filterEmpty(this.$slots[slotName])
|
||||
}
|
||||
return null
|
||||
},
|
||||
},
|
||||
render () {
|
||||
const { prefixCls, disabled, tabIndex, ...restProps } = getOptionProps(this)
|
||||
const checked = this.stateChecked
|
||||
const switchTabIndex = disabled ? -1 : (tabIndex || 0)
|
||||
const switchClassName = {
|
||||
[prefixCls]: true,
|
||||
[`${prefixCls}-checked`]: checked,
|
||||
[`${prefixCls}-disabled`]: disabled,
|
||||
}
|
||||
const childrenType = checked ? 'checkedChildren' : 'unCheckedChildren'
|
||||
return (
|
||||
<span
|
||||
{...restProps}
|
||||
class={switchClassName}
|
||||
tabIndex={switchTabIndex}
|
||||
ref='refSwitchNode'
|
||||
onKeydown={this.handleKeyDown}
|
||||
onClick={this.toggle}
|
||||
onMouseup={this.handleMouseUp}
|
||||
>
|
||||
<span class={`${prefixCls}-inner`}>
|
||||
{this.getChildren(childrenType)}
|
||||
</span>
|
||||
</span>
|
||||
)
|
||||
},
|
||||
}
|
||||
</script>
|
115
components/vc-switch/assets/index.less
Normal file
115
components/vc-switch/assets/index.less
Normal file
@ -0,0 +1,115 @@
|
||||
@switchPrefixCls: rc-switch;
|
||||
|
||||
@duration: .3s;
|
||||
|
||||
.@{switchPrefixCls} {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
width: 44px;
|
||||
height: 22px;
|
||||
line-height: 20px;
|
||||
vertical-align: middle;
|
||||
border-radius: 20px 20px;
|
||||
border: 1px solid #ccc;
|
||||
background-color: #ccc;
|
||||
cursor: pointer;
|
||||
transition: all @duration cubic-bezier(0.35, 0, 0.25, 1);
|
||||
|
||||
&-inner {
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
left: 24px;
|
||||
}
|
||||
|
||||
&:after {
|
||||
position: absolute;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
left: 2px;
|
||||
top: 1px;
|
||||
border-radius: 50% 50%;
|
||||
background-color: #fff;
|
||||
content: " ";
|
||||
cursor: pointer;
|
||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.26);
|
||||
transform: scale(1);
|
||||
transition: left @duration cubic-bezier(0.35, 0, 0.25, 1);
|
||||
animation-timing-function: cubic-bezier(0.35, 0, 0.25, 1);
|
||||
animation-duration: @duration;
|
||||
animation-name: rcSwitchOff;
|
||||
}
|
||||
|
||||
&:hover:after {
|
||||
transform: scale(1.1);
|
||||
animation-name: rcSwitchOn;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 2px tint(#2db7f5, 80%);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
&-checked {
|
||||
border: 1px solid #87d068;
|
||||
background-color: #87d068;
|
||||
|
||||
.@{switchPrefixCls}-inner {
|
||||
left: 6px;
|
||||
}
|
||||
|
||||
&:after {
|
||||
left: 22px;
|
||||
}
|
||||
}
|
||||
|
||||
&-disabled {
|
||||
cursor: no-drop;
|
||||
background: #ccc;
|
||||
border-color: #ccc;
|
||||
|
||||
&:after {
|
||||
background: #9e9e9e;
|
||||
animation-name: none;
|
||||
cursor: no-drop;
|
||||
}
|
||||
|
||||
&:hover:after {
|
||||
transform: scale(1);
|
||||
animation-name: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-label {
|
||||
display: inline-block;
|
||||
line-height: 20px;
|
||||
font-size: 14px;
|
||||
padding-left: 10px;
|
||||
vertical-align: middle;
|
||||
white-space: normal;
|
||||
pointer-events: none;
|
||||
user-select: text;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rcSwitchOn {
|
||||
0% {
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
transform: scale(1.25);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rcSwitchOff {
|
||||
0% {
|
||||
transform: scale(1.1);
|
||||
}
|
||||
100% {
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
35
components/vc-switch/demo/simple.vue
Normal file
35
components/vc-switch/demo/simple.vue
Normal file
@ -0,0 +1,35 @@
|
||||
<script>
|
||||
import VcSwitch from '../index'
|
||||
import '../assets/index.less'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
disabled: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
toggle () {
|
||||
this.disabled = !this.disabled
|
||||
},
|
||||
onChange (value) {
|
||||
console.log(`switch checked: ${value}`); // eslint-disable-line
|
||||
},
|
||||
},
|
||||
render () {
|
||||
return (
|
||||
<div style='margin: 20px'>
|
||||
<VcSwitch
|
||||
onChange={this.onChange}
|
||||
disabled={this.disabled}
|
||||
checkedChildren={'开'}
|
||||
unCheckedChildren={'关'}
|
||||
/>
|
||||
<div style='margin-top: 20px'>
|
||||
<button onClick={this.toggle}>toggle disabled</button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
}
|
||||
</script>
|
3
components/vc-switch/index.js
Normal file
3
components/vc-switch/index.js
Normal file
@ -0,0 +1,3 @@
|
||||
import Switch from './Switch'
|
||||
|
||||
export default Switch
|
@ -47,12 +47,11 @@ Badge | done
|
||||
Breadcrumb | done
|
||||
Card | done
|
||||
Collapse | done
|
||||
LocaleProvider
|
||||
Progress
|
||||
Slider
|
||||
Spin
|
||||
Spin | done
|
||||
Steps
|
||||
Switch
|
||||
Switch | done
|
||||
Table
|
||||
Timeline
|
||||
Transfer
|
||||
|
@ -23,4 +23,5 @@ export { default as collapse } from 'antd/collapse/demo/index.vue'
|
||||
export { default as notification } from 'antd/notification/demo/index.vue'
|
||||
export { default as message } from 'antd/message/demo/index.vue'
|
||||
export { default as spin } from 'antd/spin/demo/index.vue'
|
||||
export { default as switch } from 'antd/switch/demo/index.vue'
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user