Skip to content

Commit

Permalink
feat: 完善 select 组件
Browse files Browse the repository at this point in the history
  • Loading branch information
Tyh2001 committed Dec 23, 2023
1 parent 4103a03 commit 854d2de
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 44 deletions.
4 changes: 2 additions & 2 deletions packages/fighting-design/_hooks/use-form-check/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export const useFormCheck = (prop: FormProps): UseFormCheckReturn => {
/**
* 校验方法
*
* 获取到每个自组件,检测输入的内容是否符合规则
* 获取到每个子组件,检测输入的内容是否符合规则
*/
const validate = (): boolean => {
getChildrenList.value.forEach((item: VNode): void => {
Expand All @@ -109,7 +109,7 @@ export const useFormCheck = (prop: FormProps): UseFormCheckReturn => {
/** 子组件名字 */
const _name: FormItemProps['name'] = item.props && item.props.name

// 判断的每个自组件必须有 rules 和 name 参数
// 判断的每个子组件必须有 rules 和 name 参数
if (item.props && _rules && _name && prop.model) {
/** 检测父组件绑定的对象上是否存在子组件绑定的 name 属性 */
if (_name in prop.model) {
Expand Down
1 change: 0 additions & 1 deletion packages/fighting-design/_hooks/use-input/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ export const useInput = (
* @param { Object } evt 事件对象
*/
const handleInput = (evt: Event): void => {
console.log(modelValue.value)
run(prop.onInput, modelValue.value, evt)
}

Expand Down
36 changes: 33 additions & 3 deletions packages/fighting-design/option/src/option.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,35 @@
/** 获取到 trigger 注入的依赖项 */
const triggerInject: TriggerProvide | null = inject(TRIGGER_CLOSE_KEY, null)
/** 控制是否显示 */
const isVisible = computed(() => {
// 父组件没有依赖则不显示
if (!parentInject) {
return false
}
if (!parentInject.filter) {
return true
}
const slotText: VNodeNormalizedChildren | string | undefined =
slot.default && slot.default()[0].children
const label = isString(slotText)
? slotText
: '' || prop.label.toString() || prop.value.toString()
const currentItem = parentInject.childrenLabels.find(item => {
return item.slot === label
})
if (currentItem) {
return currentItem.show
}
return true
})
/** 获取插槽内容 */
const slotLabel = computed((): string => {
if (!slot.default) {
Expand Down Expand Up @@ -95,7 +124,7 @@
* @param { Object } evt 事件对象
*/
const handleClick = (evt: MouseEvent): void => {
/**如果没有获取到注入的依赖项或者禁用状态 则返回 */
// 如果没有获取到注入的依赖项或者禁用状态 则返回
if (!parentInject || prop.disabled) return
const { value, label } = toRefs(prop)
Expand All @@ -122,9 +151,9 @@
slotLabel.value
)
/** 执行父组件的设置方法 */
// 执行父组件的设置方法
parentInject && run(parentInject.setValue, currentValue, currentLabel, evt)
/** 点击之后关闭 */
// 点击之后关闭
triggerInject && run(triggerInject.close)
}
</script>
Expand All @@ -136,6 +165,7 @@
'f-option',
{ 'f-option__disabled': disabled, 'f-option__active': labelActive }
]"
v-show="isVisible"
@click="handleClick"
>
<slot v-if="$slots.default" />
Expand Down
6 changes: 5 additions & 1 deletion packages/fighting-design/select/src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,18 @@ export type SelectChange = (
) => void

/**
* 提供给自组件注入的依赖项类型接口
* 提供给子组件注入的依赖项类型接口
*
* @param { Function } setValue 设置新的选中值
* @param { Object } modelValue 绑定的值
* @param { Object } childrenLabels 绑定的值
* @param { Object } filter 绑定的值
*/
export interface SelectProvide {
setValue: SelectChange
modelValue: SelectModelValue
childrenLabels: { slot: string; show: boolean }[]
filter: boolean
}

/** 获取子元素插槽类型接口 */
Expand Down
70 changes: 41 additions & 29 deletions packages/fighting-design/select/src/select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@
import { Props, SELECT_PROPS_TOKEN } from './props'
import { FInput } from '../../input'
import { useList, useRun } from '../../_hooks'
import { provide, computed, useSlots, ref, reactive, toRef, nextTick } from 'vue'
import { provide, computed, useSlots, ref, reactive, toRef, nextTick, watch } from 'vue'
import { FDropdown } from '../../dropdown'
import { getChildren, isFunction } from '../../_utils'
import { FSvgIcon } from '../../svg-icon'
import { FIconChevronDown } from '../../_svg'
import type { VNode, Slots } from 'vue'
import type { SelectProvide, SelectModelValue, SelectChildren } from './interface'
import type { InputUpdate } from '../../input'
defineOptions({ name: 'FSelect' })
Expand All @@ -32,26 +31,14 @@
// 如果没有插槽内容,返回空数组
if (!slot.default) return []
const childrens = getChildren(slot.default(), 'FOption')
if (prop.filter && modelValue.value.toString()) {
childrens.map((item: VNode) => {
/** 获取到当前子元素的插槽内容 */
const slot: string | undefined =
item.children && (item.children as { default: Function }).default()[0].children
console.log(slot)
})
}
console.log(childrens)
return childrens
return getChildren(slot.default(), 'FOption')
})
/** 当前绑定的值 */
const keyword = computed({
get: (): string => {
// console.log(options.value)
if (prop.filter) {
return modelValue.value.toString()
}
Expand Down Expand Up @@ -106,7 +93,6 @@
return slot || label || (value && value.toString()) || ''
},
set: (val: string): string => {
console.log('set')
modelValue.value = val
return val
}
Expand All @@ -124,22 +110,32 @@
currentLabel: SelectModelValue,
evt: MouseEvent
): void => {
/** 设置文本框展示的内容 */
// 设置文本框展示的内容
keyword.value = currentValue.toString()
/** 如果最新的 value 和绑定的 value 不一致时,才触发 change 事件 */
// 如果最新的 value 和绑定的 value 不一致时,才触发 change 事件
if (currentLabel !== prop.modelValue) {
run(prop.onChange, currentValue, currentLabel, evt)
}
modelValue.value = currentValue
}
/** 向自组件注入依赖项 */
provide<SelectProvide>(
SELECT_PROPS_TOKEN,
reactive({ setValue, modelValue: toRef(prop, 'modelValue') })
)
const childrenLabels = ref<{ slot: string; show: boolean }[]>([])
const setChildrenLabels = () => {
if (!options.value || !options.value.length) {
childrenLabels.value = []
}
childrenLabels.value = options.value.map((item: VNode) => {
/** 获取到当前子元素的插槽内容 */
const slot: string =
item.children && (item.children as { default: Function }).default()[0].children
return { slot, show: slot?.includes(modelValue.value.toString()) }
})
}
/** 样式列表 */
const styleList = styles(['width'])
Expand All @@ -154,6 +150,14 @@
const onOpen = async (): Promise<void> => {
await nextTick()
childrenLabels.value = options.value.map((item: VNode) => {
/** 获取到当前子元素的插槽内容 */
const slot: string =
item.children && (item.children as { default: Function }).default()[0].children
return { slot, show: true }
})
/** 获取到当前选中的元素 */
const active =
secletContentRef.value &&
Expand All @@ -169,9 +173,18 @@
}
}
const inputInput: InputUpdate = (value: string): void => {
console.log(value)
}
watch(() => modelValue.value, setChildrenLabels, { immediate: true })
// 向子组件注入依赖项
provide<SelectProvide>(
SELECT_PROPS_TOKEN,
reactive({
setValue,
childrenLabels,
modelValue: toRef(prop, 'modelValue'),
filter: toRef(prop, 'filter')
})
)
</script>

<template>
Expand All @@ -187,7 +200,6 @@
:clear="clear"
:on-focus="() => (isFocus = true)"
:on-blur="() => (isFocus = false)"
:on-input="filter ? inputInput : undefined"
>
<template #after>
<f-svg-icon
Expand Down
10 changes: 2 additions & 8 deletions start/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,16 @@
<template>
{{ value }}
<h1>{{ value || '1' }}</h1>
<f-select v-model="value" placeholder="请选择……" filter>
<f-option>香蕉</f-option>
<f-option>苹果</f-option>
<f-option>哈密瓜</f-option>
<f-option>樱桃</f-option>
<f-option>西瓜</f-option>
</f-select>

<!-- <f-input v-model="value1" :on-input="inp"></f-input> -->
</template>

<script lang="ts" setup>
import { ref } from 'vue'
const value = ref('')
const value1 = ref('')
const inp = (v, e) => {
console.log(v, e)
}
</script>

0 comments on commit 854d2de

Please sign in to comment.