fix(slider): [slider] value of input does not change when using max and min (#1056)

This commit is contained in:
yoyo 2023-12-08 16:29:04 +08:00 committed by GitHub
parent 2a2383b0bb
commit 3bb0f0ff12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 71 additions and 23 deletions

View File

@ -59,7 +59,8 @@ export default {
'demoId': 'shortcut-operation',
'name': { 'zh-CN': '快捷键操作', 'en-US': 'Shortcut Key Operations' },
'desc': {
'zh-CN': '<p>通过设置<code>num-pages</code>总步数,即按快捷键 PageDown/PageUp 时,每次移动的距离是 "⌈(max-min)/num-pages⌉"。</p>',
'zh-CN':
'<p>通过设置<code>num-pages</code>总步数,即按快捷键 PageDown/PageUp 时,每次移动的距离是 "⌈(max-min)/num-pages⌉"。</p>',
'en-US':
'<p>Set <code>num-pages</code>the total number of steps. That is, when you press the shortcut key PageDown or PageUp, the moving distance is "⌈(max-min)/num-pages⌉"。</p>'
},
@ -104,7 +105,7 @@ export default {
'name': { 'zh-CN': '事件', 'en-US': 'Event' },
'desc': { 'zh-CN': '<p>change、start、stop 事件。</p>', 'en-US': '<p>change, start, stop events.</p>' },
'codeFiles': ['slider-event.vue']
},
}
],
apis: [
{
@ -114,7 +115,10 @@ export default {
{
'name': 'v-model',
'type': 'number | [number, number]',
'desc': { 'zh-CN': '设置单滑块的当前值,必需是整数或数组', 'en-US': 'Sets the current value of a single slider. The value must be an integer or an array.' },
'desc': {
'zh-CN': '设置单滑块的当前值,必需是整数或数组',
'en-US': 'Sets the current value of a single slider. The value must be an integer or an array.'
},
'demoId': 'basic-usage'
},
{
@ -180,7 +184,10 @@ export default {
'name': 'height',
'type': 'string',
'defaultValue': `'300px'`,
'desc': { 'zh-CN': 'Slider组件的高度当vertical为true时有效', 'en-US': 'Height of Slider component, effective when vertical is true' },
'desc': {
'zh-CN': 'Slider 组件的高度,当 vertical 为 true 时有效',
'en-US': 'Height of Slider component, effective when vertical is true'
},
'demoId': 'vertical-mode'
},
{
@ -188,8 +195,7 @@ export default {
'type': 'number',
'defaultValue': '1',
'desc': {
'zh-CN':
'设置总步数,即按快捷键 PageDown/PageUp 时,每次移动的距离是 "⌈(max-min)/num-pages⌉"',
'zh-CN': '设置总步数,即按快捷键 PageDown/PageUp 时,每次移动的距离是 "⌈(max-min)/num-pages⌉"',
'en-US':
'Set the total number of steps. That is, when you press PageDown or PageUp, the moving distance is "⌈(max-min)/num-pages⌉".'
},
@ -209,8 +215,7 @@ export default {
'type': '(value: number | [number, number]) => void',
'defaultValue': '',
'desc': {
'zh-CN':
'值改变时触发(使用鼠标拖曳时,只在松开鼠标后触发)',
'zh-CN': '值改变时触发(使用鼠标拖曳时,只在松开鼠标后触发)',
'en-US':
'Triggered when the value changes (When you drag the mouse, it is triggered only after you release the mouse).'
},
@ -221,22 +226,18 @@ export default {
'type': '(event: Event, value: number | [number, number]) => void',
'defaultValue': '',
'desc': {
'zh-CN':
'设置滑块滑动开始时,触发该事件',
'en-US':
'This event is triggered when the slider starts to slide.'
'zh-CN': '设置滑块滑动开始时,触发该事件',
'en-US': 'This event is triggered when the slider starts to slide.'
},
'demoId': 'slider-event'
},
{
'name': 'Stop',
'name': 'stop',
'type': '(value: number | [number, number]) => void',
'defaultValue': '',
'desc': {
'zh-CN':
'设置滑块滑动结束时,触发该事件',
'en-US':
'This event is triggered when the slider sliding ends. '
'zh-CN': '设置滑块滑动结束时,触发该事件',
'en-US': 'This event is triggered when the slider sliding ends. '
},
'demoId': 'slider-event'
}
@ -246,7 +247,11 @@ export default {
'name': 'default',
'type': '',
'defaultValue': '',
'desc': { 'zh-CN': '显示滑块值的插槽仅仅v-model是单数值时才有效插槽参数为slotArg: { slotScope: number }', 'en-US': 'Slot for displaying slider values, valid only if v-model is a single value. Slot parameters are: slotArg: {slotScope: number}' },
'desc': {
'zh-CN': '显示滑块值的插槽,仅仅 v-model 是单数值时才有效插槽参数为slotArg: { slotScope: number }',
'en-US':
'Slot for displaying slider values, valid only if v-model is a single value. Slot parameters are: slotArg: {slotScope: number}'
},
'demoId': 'slider-slot'
}
]

View File

@ -483,6 +483,11 @@ export const watchActiveValue =
} else {
state.activeValue = nNewValue || 0
}
// 正在输入时,不应该改变输入的内容
if (!state.isSlotTyping) {
state.slotValue = state.activeValue
}
}
export const watchModelValue =
@ -554,3 +559,16 @@ export const inputValueChange =
}
api.initSlider([Math.min(...state.inputValue), Math.max(...state.inputValue)])
}
export const handleSlotInputFocus = (state: ISliderRenderlessParams['state']) => () => {
state.isSlotTyping = true
}
export const handleSlotInputBlur = (state: ISliderRenderlessParams['state']) => () => {
state.isSlotTyping = false
state.slotValue = state.activeValue
}
export const handleSlotInput = (state: ISliderRenderlessParams['state']) => (event: Event) => {
state.activeValue = Number((event.target as HTMLInputElement).value)
}

View File

@ -38,7 +38,10 @@ import {
watchModelValue,
getPoints,
getLabels,
inputValueChange
inputValueChange,
handleSlotInputFocus,
handleSlotInputBlur,
handleSlotInput
} from './index'
import type {
@ -74,7 +77,10 @@ export const api = [
'customBeforeAppearHook',
'customAppearHook',
'customAfterAppearHook',
'inputValueChange'
'inputValueChange',
'handleSlotInputFocus',
'handleSlotInputBlur',
'handleSlotInput'
]
const initState = ({ reactive, computed, props, api, parent, inject }) => {
@ -106,7 +112,9 @@ const initState = ({ reactive, computed, props, api, parent, inject }) => {
rangeDiff: computed(() => props.max - props.min),
tipValue: computed(() => api.formatTipValue(state.activeValue)),
formDisabled: computed(() => (parent.tinyForm || {}).disabled),
disabled: computed(() => props.disabled || state.formDisabled)
disabled: computed(() => props.disabled || state.formDisabled),
slotValue: '',
isSlotTyping: false
})
return state
@ -150,7 +158,10 @@ export const renderless = (
watchActiveValue: watchActiveValue({ api, emit, props, state }),
getPoints: getPoints({ props, state }),
getLabels: getLabels({ props, state }),
inputValueChange: inputValueChange({ props, api, state })
inputValueChange: inputValueChange({ props, api, state }),
handleSlotInputFocus: handleSlotInputFocus(state),
handleSlotInputBlur: handleSlotInputBlur(state),
handleSlotInput: handleSlotInput(state)
})
watch(() => props.modelValue, api.watchModelValue, { immediate: true })

View File

@ -34,6 +34,10 @@ export interface ISliderState {
tipValue: ComputedRef<string>
formDisabled: ComputedRef<boolean>
disabled: ComputedRef<boolean>
/** 使用这个值作为插槽中输入的值而不是直接用activeValue来实现在输入时不会被max min属性计算而改变 */
slotValue: number
/** 是否正在输入 */
isSlotTyping: boolean
}
export interface ISliderApi {
@ -65,6 +69,9 @@ export interface ISliderApi {
getPoints: () => void
getLabels: () => void
inputValueChange: () => void
handleSlotInputFocus: () => void
handleSlotInputBlur: () => void
handleSlotInput: (event: Event) => void
}
export type ISliderRenderlessParams = ISharedRenderlessFunctionParams<ISliderConstants> & {

View File

@ -74,7 +74,14 @@
<template v-if="showInput && !state.isDouble">
<div class="tiny-slider__input">
<slot :slot-scope="state.activeValue">
<input type="text" v-model="state.activeValue" :disabled="state.disabled" /><span>%</span>
<input
type="text"
v-model="state.slotValue"
@focus="handleSlotInputFocus"
@blur="handleSlotInputBlur"
@input="handleSlotInput"
:disabled="state.disabled"
/><span>%</span>
</slot>
</div>
</template>