(component): 完成 select 组件, 新增 tag-input 组件 disabled-input 属性

This commit is contained in:
就眠儀式 2022-09-24 09:50:53 +08:00
parent f52ff6207b
commit 06149b7e77
12 changed files with 142 additions and 54 deletions

View File

@ -43,7 +43,7 @@ const matchModule: string[] = [
"dropdownMenu",
"dropdownMenuItem",
"tag",
"tagInput"
"tagInput",
];
export default (): UserConfigExport => {

View File

@ -70,7 +70,6 @@ export interface LayDropdownProps {
alignPoint?: boolean;
contentClass?: string | Array<string | object> | object;
contentStyle?: StyleValue;
// wip
popupContainer?: string | undefined;
}

View File

@ -26,7 +26,10 @@ const isVertical = computed(() => {
return vNodes.some((vNode) => {
const componentName = (vNode.type as Component).name;
if (!componentName) return false;
return [Header.name].includes(componentName) || [Footer.name].includes(componentName);
return (
[Header.name].includes(componentName) ||
[Footer.name].includes(componentName)
);
});
});

View File

@ -14,7 +14,16 @@
text-overflow: ellipsis;
}
.layui-select-options .layui-select-option .layui-form-checkbox[lay-skin="primary"] {
padding-left: 12px;
}
.layui-select-options .layui-select-option.layui-this {
background-color: var(--global-neutral-color-2);
color: var(--global-checked-color);
font-size: 700;
}
.layui-select-search {
padding: 5px 10px;
}

View File

@ -6,11 +6,13 @@ export default {
<script setup lang="ts">
import "./index.less";
import { provide, computed, WritableComputedRef } from "vue";
import { provide, computed, WritableComputedRef, ref } from "vue";
import LayInput from "../input/index.vue";
import LayTagInput from "../tagInput/index.vue";
import LayDropdown from "../dropdown/index.vue";
import LaySelectOption, { LaySelectOptionProps } from "../selectOption/index.vue";
import LaySelectOption, {
LaySelectOptionProps,
} from "../selectOption/index.vue";
export interface LaySelectProps {
name?: string;
@ -41,37 +43,51 @@ const props = withDefaults(defineProps<LaySelectProps>(), {
const emits = defineEmits<SelectEmits>();
const searchValue = ref("");
const selectedValue = computed({
get() {
return props.modelValue;
},
set(val) {
emits('update:modelValue', val);
emits('change', val);
}
})
emits("update:modelValue", val);
emits("change", val);
},
});
const multiple = computed(() => {
return props.multiple;
})
});
provide('selectedValue', selectedValue);
provide('multiple', multiple);
provide("selectedValue", selectedValue);
provide("searchValue", searchValue);
provide("multiple", multiple);
</script>
<template>
<div class="layui-select">
<lay-dropdown update-at-scroll>
<lay-tag-input v-if="multiple" v-model="selectedValue"></lay-tag-input>
<lay-input v-else :placeholder="placeholder" v-model="selectedValue"></lay-input>
<template #content>
<dl class="layui-select-options">
<template v-if="items">
<lay-select-option v-for="(item, index) in items" v-bind="item" :key="index"></lay-select-option>
</template>
<slot></slot>
</dl>
</template>
<lay-tag-input v-if="multiple" v-model="selectedValue" :disabledInput="true"></lay-tag-input>
<lay-input
v-else
:placeholder="placeholder"
v-model="selectedValue"
></lay-input>
<template #content>
<dl class="layui-select-options">
<div class="layui-select-search">
<lay-input v-model="searchValue" size="sm" placeholder="请选择" prefix-icon="layui-icon-search"></lay-input>
</div>
<template v-if="items">
<lay-select-option
v-for="(item, index) in items"
v-bind="item"
:key="index"
></lay-select-option>
</template>
<slot></slot>
</dl>
</template>
</lay-dropdown>
</div>
</div>
</template>

View File

@ -6,13 +6,13 @@ export default {
<script setup lang="ts">
import LayCheckbox from "../checkbox/index.vue";
import { computed, ComputedRef, inject, WritableComputedRef } from "vue";
import { computed, ComputedRef, inject, WritableComputedRef, Ref } from "vue";
export interface LaySelectOptionProps {
value: string | object;
label: string;
keyword?: string;
value: string | object;
disabled?: boolean;
keyword?: string;
}
const props = withDefaults(defineProps<LaySelectOptionProps>(), {
@ -22,32 +22,38 @@ const props = withDefaults(defineProps<LaySelectOptionProps>(), {
});
const selectedValue: WritableComputedRef<any> = inject("selectedValue") as WritableComputedRef<any>;
const searchValue: Ref<string> = inject('searchValue') as Ref<string>;
const multiple: ComputedRef = inject("multiple") as ComputedRef;
const handleSelect = () => {
if(!multiple.value) {
if (!multiple.value) {
selectedValue.value = props.value;
}
}
};
const isSelected = computed(() => {
const selected = computed(() => {
if (multiple.value) {
return selectedValue.value.indexOf(props.value) != -1;
} else {
// close dropdown
return selectedValue.value === props.value;
}
});
const display = computed(() => {
return props.keyword.indexOf(searchValue.value) > -1 || props.label.indexOf(searchValue.value) > -1;
})
</script>
<template>
<dd class="layui-select-option" :class="{ 'layui-this': isSelected && !multiple }" @click="handleSelect">
<dd
v-show="display"
:class="['layui-select-option', { 'layui-this': selected && !multiple }]"
@click="handleSelect"
>
<template v-if="multiple">
<lay-checkbox v-model="selectedValue" :value="value" skin="primary"
><slot>{{ label }}</slot></lay-checkbox
>
</template>
<template v-else>
<slot>{{ label }}</slot>
<lay-checkbox v-model="selectedValue" :value="value" skin="primary"></lay-checkbox>
</template>
<slot>{{ label }}</slot>
</dd>
</template>

View File

@ -17,6 +17,7 @@ import {
nextTick,
} from "vue";
import { reactiveOmit, useResizeObserver, useVModel } from "@vueuse/core";
import { LayIcon } from "@layui/icons-vue";
export interface TagData {
value?: string | number;
@ -29,6 +30,7 @@ export interface LayInputTagProps {
modelValue?: (string | number | TagData)[];
inputValue?: string;
disabled?: boolean;
disabledInput?: boolean;
placeholder?: string;
readonly?: boolean;
allowClear?: boolean;
@ -41,12 +43,12 @@ export interface LayInputTagProps {
const props = withDefaults(defineProps<LayInputTagProps>(), {
disabled: false,
disabledInput: false,
placeholder: "",
readonly: false,
allowClear: true,
minCollapsedNum: 3,
size: "md",
//max:3
});
const emit = defineEmits(["update:modelValue", "update:inputValue"]);
@ -62,6 +64,7 @@ const tagData = useVModel(props, "modelValue", emit, {
deep: true,
defaultValue: [] as TagData[],
});
const tagProps = reactiveOmit(
props.tagProps ?? {},
"closable",
@ -183,10 +186,10 @@ watch(
);
const moreCount = computed(() => {
if(tagData.value && computedTagData.value) {
return tagData.value.length - computedTagData.value.length
if (tagData.value && computedTagData.value) {
return tagData.value.length - computedTagData.value.length;
}
})
});
onMounted(() => {
handleResize();
@ -240,7 +243,8 @@ defineExpose({
</template>
</LayToopTip>
</template>
<input
<template v-if="!disabledInput">
<input
ref="inputRefEl"
class="layui-tag-input-inner-input"
:style="inputStyle"
@ -254,6 +258,7 @@ defineExpose({
@compositionupdate="handleComposition"
@compositionend="handleComposition"
/>
</template>
</span>
<span v-if="allowClear && tagData?.length" class="layui-tag-input-clear">
<lay-icon type="layui-icon-close-fill" @click.stop="handleClearClick" />

View File

@ -1,3 +1,3 @@
export const check = (arr: any[], value: any) => {
return arr.indexOf(value) > -1;
}
return arr.indexOf(value) > -1;
};

View File

@ -1,3 +1,3 @@
export * from "./DomUtil";
export * from "./withInstall";
export * from "./arrayUtil";
export * from "./arrayUtil";

View File

@ -24,7 +24,7 @@
</lay-dropdown-menu>
</template>
</lay-dropdown>
<lay-dropdown popupContainer=".layui-body>div">
<lay-dropdown>
<lay-button type="primary">下拉菜单</lay-button>
<template #content>
<lay-dropdown-menu>

View File

@ -13,7 +13,7 @@
::: demo 使用 `lay-tag-input` 标签, 创建标签输入框。
<template>
<lay-tag-input v-model="data1" v-model:inputValue="inputValue"></lay-tag-input>
<lay-tag-input v-model="data1" v-model:inputValue="inputValue1"></lay-tag-input>
</template>
<script>
@ -22,17 +22,65 @@ import { ref,watch } from 'vue'
export default {
setup() {
const data1 = ref(['Vue', 'React']);
const inputValue = ref();
watch(data1, (val) => {
console.log("tagData",val)
})
watch(inputValue, (val) => {
console.log("inputValue",val)
})
const inputValue1 = ref("");
return {
data1,
inputValue
inputValue1
}
}
}
</script>
:::
::: title 只读状态
:::
::: demo 使用 `lay-tag-input` 标签, 创建标签输入框。
<template>
<lay-tag-input v-model="data3" v-model:inputValue="inputValue3" :readonly="true"></lay-tag-input>
</template>
<script>
import { ref,watch } from 'vue'
export default {
setup() {
const data3 = ref(['Vue', 'React']);
const inputValue3 = ref("");
return {
data3,
inputValue3
}
}
}
</script>
:::
::: title 禁用状态
:::
::: demo 使用 `lay-tag-input` 标签, 创建标签输入框。
<template>
<lay-tag-input v-model="data4" v-model:inputValue="inputValue4" :disabled="true"></lay-tag-input>
</template>
<script>
import { ref,watch } from 'vue'
export default {
setup() {
const data4 = ref(['Vue', 'React']);
const inputValue4 = ref("");
return {
data4,
inputValue4
}
}
}

View File

@ -3,6 +3,7 @@ export default {
name: "TreadIcon",
};
</script>
<script setup lang="ts">
import LayIcon from "../component/icon/index";
@ -11,6 +12,7 @@ const props = defineProps<{
size?: string;
}>();
</script>
<template>
<lay-icon :color="props.color" :size="props.size" type="layui-icon-tread" />
</template>