提交 444ec976 编写于 作者: D DCloud_LXH

feat: swtich

上级 48235ef3
......@@ -23,7 +23,7 @@ import ScrollView from './scroll-view/index.vue'
import Slider from './slider/index'
// import Swiper from './swiper/index.vue'
import SwiperItem from './swiper-item/index.vue'
import Switch from './switch/index.vue'
import Switch from './switch/index'
import Text from './text/index'
import Textarea from './textarea/index'
import View from './view/index'
......
import {
defineComponent,
ref,
onBeforeUnmount,
watch,
inject,
onUnmounted,
ExtractPropTypes,
Ref,
} from 'vue'
import { useCustomEvent, EmitEvent } from '@dcloudio/uni-components'
import { UniFormCtx, uniFormKey } from '../form'
import { UniLabelCtx, uniLabelKey } from '../label'
import { useListeners } from '../../helpers/useListeners'
import { useBooleanAttr } from '../../helpers/useBooleanAttr'
import {
createSvgIconVNode,
ICON_PATH_SUCCESS_NO_CIRCLE,
} from '@dcloudio/uni-core'
const props = {
name: {
type: String,
default: '',
},
checked: {
type: [Boolean, String],
default: false,
},
type: {
type: String,
default: 'switch',
},
id: {
type: String,
default: '',
},
disabled: {
type: [Boolean, String],
default: false,
},
color: {
type: String,
default: '#007aff',
},
}
type SwitchProps = ExtractPropTypes<typeof props>
export default /*#__PURE__*/ defineComponent({
name: 'Switch',
props,
emits: ['change'],
setup(props, { emit }) {
const rootRef = ref<HTMLElement | null>(null)
const switchChecked = ref(props.checked)
const uniLabel = useSwitchInject(props, switchChecked)
const trigger = useCustomEvent<EmitEvent<typeof emit>>(rootRef, emit)
watch(
() => props.checked,
(val) => {
switchChecked.value = val
}
)
const _onClick = ($event: Event) => {
if (props.disabled) {
return
}
switchChecked.value = !switchChecked.value
trigger('change', $event, {
value: switchChecked.value,
})
}
if (!!uniLabel) {
uniLabel.addHandler(_onClick)
onBeforeUnmount(() => {
uniLabel.removeHandler(_onClick)
})
}
useListeners(props, { 'label-click': _onClick })
return () => {
const { color, type } = props
const { booleanAttrs } = useBooleanAttr(props, 'disabled')
return (
<uni-switch ref={rootRef} {...booleanAttrs} onClick={_onClick}>
<div class="uni-switch-wrapper">
<div
v-show={type === 'switch'}
class="uni-switch-input"
class={[switchChecked.value ? 'uni-switch-input-checked' : '']}
style={{
backgroundColor: switchChecked.value ? color : '#DFDFDF',
borderColor: switchChecked.value ? color : '#DFDFDF',
}}
/>
<div v-show={type === 'checkbox'} class="uni-checkbox-input">
{switchChecked.value
? createSvgIconVNode(
ICON_PATH_SUCCESS_NO_CIRCLE,
props.color,
22
)
: ''}
</div>
</div>
</uni-switch>
)
}
},
})
function useSwitchInject(
props: SwitchProps,
switchChecked: Ref<string | boolean>
) {
const uniForm = inject<UniFormCtx>(
uniFormKey,
(false as unknown) as UniFormCtx
)
const uniLabel = inject<UniLabelCtx>(
uniLabelKey,
(false as unknown) as UniLabelCtx
)
const formField = {
submit: () => {
const data: [string, any] = ['', null]
if (props.name) {
data[0] = props.name
data[1] = switchChecked.value
}
return data
},
reset: () => {
switchChecked.value = false
},
}
if (!!uniForm) {
uniForm.addField(formField)
onUnmounted(() => {
uniForm.removeField(formField)
})
}
return uniLabel
}
<template>
<uni-switch
:disabled="disabled"
v-bind="$attrs"
@click="_onClick"
>
<div class="uni-switch-wrapper">
<div
v-show="type === 'switch'"
:class="[switchChecked ? 'uni-switch-input-checked' : '']"
:style="{backgroundColor: switchChecked ? color : '#DFDFDF',borderColor:switchChecked ? color : '#DFDFDF'}"
class="uni-switch-input"
/>
<div
v-show="type === 'checkbox'"
:class="[switchChecked ? 'uni-checkbox-input-checked' : '']"
:style="{color: color}"
class="uni-checkbox-input"
/>
</div>
</uni-switch>
</template>
<script>
import {
emitter,
listeners
} from '../../mixins'
export default {
name: 'Switch',
mixins: [emitter, listeners],
props: {
name: {
type: String,
default: ''
},
checked: {
type: [Boolean, String],
default: false
},
type: {
type: String,
default: 'switch'
},
id: {
type: String,
default: ''
},
disabled: {
type: [Boolean, String],
default: false
},
color: {
type: String,
default: '#007aff'
}
},
data () {
return {
switchChecked: this.checked
}
},
watch: {
checked (val) {
this.switchChecked = val
}
},
created () {
this.$dispatch('Form', 'uni-form-group-update', {
type: 'add',
vm: this
})
},
beforeDestroy () {
this.$dispatch('Form', 'uni-form-group-update', {
type: 'remove',
vm: this
})
},
listeners: {
'label-click': '_onClick',
'@label-click': '_onClick'
},
methods: {
_onClick ($event) {
if (this.disabled) {
return
}
this.switchChecked = !this.switchChecked
this.$trigger('change', $event, {
value: this.switchChecked
})
},
_resetFormData () {
this.switchChecked = false
},
_getFormData () {
const data = {}
if (this.name !== '') {
data.value = this.switchChecked
data.key = this.name
}
return data
}
}
}
</script>
\ No newline at end of file
......@@ -12,13 +12,16 @@ uni-switch[disabled] {
cursor: not-allowed;
}
.uni-switch-wrapper {
uni-switch .uni-switch-wrapper {
display: -webkit-inline-flex;
display: inline-flex;
-webkit-align-items: center;
align-items: center;
vertical-align: middle;
}
.uni-switch-input {
uni-switch .uni-switch-input {
-webkit-appearance: none;
appearance: none;
position: relative;
width: 52px;
......@@ -36,7 +39,7 @@ uni-switch[disabled] .uni-switch-input {
opacity: 0.7;
}
.uni-switch-input:before {
uni-switch .uni-switch-input:before {
content: ' ';
position: absolute;
top: 0;
......@@ -45,10 +48,12 @@ uni-switch[disabled] .uni-switch-input {
height: 30px;
border-radius: 15px;
background-color: #fdfdfd;
transition: -webkit-transform 0.3s;
transition: transform 0.3s;
transition: transform 0.3s, -webkit-transform 0.3s;
}
.uni-switch-input:after {
uni-switch .uni-switch-input:after {
content: ' ';
position: absolute;
top: 0;
......@@ -58,24 +63,29 @@ uni-switch[disabled] .uni-switch-input {
border-radius: 15px;
background-color: #ffffff;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
transition: -webkit-transform 0.3s;
transition: transform 0.3s;
transition: transform 0.3s, -webkit-transform 0.3s;
}
.uni-switch-input.uni-switch-input-checked {
uni-switch .uni-switch-input.uni-switch-input-checked {
border-color: #007aff;
background-color: #007aff;
}
.uni-switch-input.uni-switch-input-checked:before {
uni-switch .uni-switch-input.uni-switch-input-checked:before {
-webkit-transform: scale(0);
transform: scale(0);
}
.uni-switch-input.uni-switch-input-checked:after {
uni-switch .uni-switch-input.uni-switch-input-checked:after {
-webkit-transform: translateX(20px);
transform: translateX(20px);
}
uni-switch .uni-checkbox-input {
margin-right: 5px;
-webkit-appearance: none;
appearance: none;
outline: 0;
border: 1px solid #d1d1d1;
......@@ -91,15 +101,14 @@ uni-switch:not([disabled]) .uni-checkbox-input:hover {
border-color: #007aff;
}
uni-switch .uni-checkbox-input.uni-checkbox-input-checked:before {
font: normal normal normal 14px/1 'uni';
content: '\EA08';
.uni-checkbox-input svg {
color: inherit;
font-size: 22px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -48%) scale(0.73);
-webkit-transform: translate(-50%, -48%) scale(0.73);
}
uni-switch .uni-checkbox-input.uni-checkbox-input-disabled {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册