!17 [修复] select组件中外部参数变更后组件内的数值变化不生效的问题

Merge pull request !17 from 鄢鹏权/develop
This commit is contained in:
就眠儀式 2022-01-08 04:47:16 +00:00 committed by Gitee
commit de3b058f07
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
5 changed files with 276 additions and 208 deletions

View File

@ -27,6 +27,40 @@ export default {
} }
</script> </script>
::: title 数据联动
:::
::: demo
<template>
<lay-select v-model="value">
<lay-select-option value="1" label="学习"></lay-select-option>
<lay-select-option value="2" label="编码"></lay-select-option>
<lay-select-option value="3" label="运动"></lay-select-option>
</lay-select>
<lay-button @click="change1">点击切换(当前值:{{value}})</lay-button>
</template>
<script>
import { ref } from 'vue'
export default {
name:'selectChange',
setup() {
const value = ref(null);
var i = 1;
function change1(){
value.value=i++%3+1
}
return {
value,
change1
}
}
}
</script>
::: :::
::: title 选择禁用 ::: title 选择禁用
@ -74,6 +108,7 @@ export default {
<lay-select-option value="6" label="打篮球"></lay-select-option> <lay-select-option value="6" label="打篮球"></lay-select-option>
<lay-select-option value="7" label="rap"></lay-select-option> <lay-select-option value="7" label="rap"></lay-select-option>
</lay-select> </lay-select>
<lay-button @click="mvalue=[1,5,7]">点击切换(当前值:{{mvalue.join()}})</lay-button>
</template> </template>
<script> <script>

View File

@ -48,6 +48,7 @@
到第 到第
<input <input
v-model="currentPageShow" v-model="currentPageShow"
@keypress.enter="jumpPage()"
type="number" type="number"
class="layui-input layui-input-number" class="layui-input layui-input-number"
/> />

View File

@ -1,91 +1,91 @@
<template> <template>
<div <div
ref="selectRef" ref="selectRef"
class="layui-unselect layui-form-select" class="layui-unselect layui-form-select"
:class="{ 'layui-form-selected': openState }" :class="{ 'layui-form-selected': openState }"
> >
<div class="layui-select-title" @click="open"> <div class="layui-select-title" @click="open">
<input <input
type="text" type="text"
:placeholder=" :placeholder="
selectItem.value !== null && selectItem.value !== null &&
Array.isArray(selectItem.value) && Array.isArray(selectItem.value) &&
selectItem.value.length > 0 selectItem.value.length > 0
? '' ? ''
: emptyMessage ?? placeholder : emptyMessage ?? placeholder
" "
:disabled="disabled" :disabled="disabled"
readonly readonly
:value=" :value="
!selectItem.multiple && selectItem.value !== null !selectItem.multiple && selectItem.value !== null
? selectItem.label ? selectItem.label
: null : null
" "
:name="name" :name="name"
:class="[ :class="[
'layui-input', 'layui-input',
'layui-unselect', 'layui-unselect',
{ 'layui-disabled': disabled }, { 'layui-disabled': disabled },
]" ]"
/> />
<i :class="['layui-edge', { 'layui-disabled': disabled }]"></i> <i :class="['layui-edge', { 'layui-disabled': disabled }]"></i>
<!-- 多选 --> <!-- 多选 -->
<div <div
v-if="selectItem.multiple && Array.isArray(selectItem.label)" v-if="selectItem.multiple && Array.isArray(selectItem.label)"
class="layui-multiple-select-row" class="layui-multiple-select-row"
> >
<div class="layui-multiple-select-badge"> <div class="layui-multiple-select-badge">
<template v-for="(item, index) in selectItem.label" :key="index"> <template v-for="(item, index) in selectItem.label" :key="index">
<lay-badge theme="green"> <lay-badge theme="green">
<span>{{ item }}</span> <span>{{ item }}</span>
<i <i
:class="['layui-icon', { 'layui-icon-close': true }]" :class="['layui-icon', { 'layui-icon-close': true }]"
v-if=" v-if="
!disabled && !disabled &&
!( !(
Array.isArray(selectItem.value) && Array.isArray(selectItem.value) &&
selectItem.value.length > 0 && selectItem.value.length > 0 &&
disabledItemMap[selectItem.value[index]] disabledItemMap[selectItem.value[index]]
) )
" "
@click=" @click="
removeItemHandle($event, { removeItemHandle($event, {
label: item, label: item,
value: Array.isArray(selectItem.value) value: Array.isArray(selectItem.value)
? selectItem.value[index] ? selectItem.value[index]
: null, : null,
}) })
" "
> >
</i> </i>
</lay-badge> </lay-badge>
</template> </template>
</div> </div>
</div> </div>
</div> </div>
<dl class="layui-anim layui-anim-upbit"> <dl class="layui-anim layui-anim-upbit">
<!-- 多选不支持空提示 --> <!-- 多选不支持空提示 -->
<template v-if="!multiple && showEmpty"> <template v-if="!multiple && showEmpty">
<lay-select-option :value="null" :label="emptyMessage ?? placeholder" /> <lay-select-option :value="null" :label="emptyMessage ?? placeholder" />
</template> </template>
<slot></slot> <slot></slot>
</dl> </dl>
</div> </div>
</template> </template>
<script setup name="LaySelect" lang="ts"> <script setup name="LaySelect" lang="ts">
import "./index.less"; import "./index.less";
import LaySelectOption from "../selectOption/index.vue"; import LaySelectOption from "../selectOption/index.vue";
import { import {
defineProps, defineProps,
provide, provide,
isProxy, isProxy,
ref, ref,
watch, watch,
computed, computed,
reactive, reactive,
toRefs, toRefs,
Ref, Ref,
} from "vue"; } from "vue";
import { useClickOutside } from "@layui/hooks-vue"; import { useClickOutside } from "@layui/hooks-vue";
import { SelectItem } from "../type"; import { SelectItem } from "../type";
@ -94,115 +94,127 @@ const selectRef = ref<null | HTMLElement>(null);
const isClickOutside = useClickOutside(selectRef); const isClickOutside = useClickOutside(selectRef);
watch(isClickOutside, () => { watch(isClickOutside, () => {
if (isClickOutside.value) { if (isClickOutside.value) {
openState.value = false; openState.value = false;
} }
}); });
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
modelValue?: string | number | [] | null; modelValue?: string | number | [] | null;
name?: string; name?: string;
placeholder?: string; placeholder?: string;
disabled?: boolean; disabled?: boolean;
showEmpty?: boolean; showEmpty?: boolean;
emptyMessage?: string; emptyMessage?: string;
multiple?: boolean; multiple?: boolean;
}>(), }>(),
{ {
modelValue: null, modelValue: null,
placeholder: "请选择", placeholder: "请选择",
disabled: false, disabled: false,
showEmpty: true, showEmpty: true,
multiple: false, multiple: false,
} }
); );
const openState = ref(false); const openState = ref(false);
const open = function () { const open = function () {
// //
if (props.disabled) { if (props.disabled) {
openState.value = false; openState.value = false;
return; return;
} }
openState.value = !openState.value; openState.value = !openState.value;
}; };
const emit = defineEmits(["update:modelValue", "change"]); const emit = defineEmits(["update:modelValue", "change"]);
const selectItem = ref<SelectItem>({ const selectItem = ref<SelectItem>({
value: !props.multiple value: !props.multiple
? props.modelValue ? props.modelValue
: props.modelValue : props.modelValue
? ([] as any[]).concat(props.modelValue) ? ([] as any[]).concat(props.modelValue)
: [], : [],
label: props.multiple ? [] : null, label: props.multiple ? [] : null,
multiple: props.multiple, multiple: props.multiple,
} as SelectItem); } as SelectItem);
watch( watch(
() => selectItem.value.value, () => selectItem.value.value,
(val) => { (val) => {
emit("update:modelValue", val); emit("update:modelValue", val);
emit("change", val); emit("change", val);
}, },
{ {
deep: true, deep: true,
} }
); );
watch( watch(props, () => {
() => props.modelValue, let value = props.modelValue;
(value) => { if (props.multiple) {
selectItem.value.value = value; if (Array.isArray(value)) {
if (!value && value !== 0) { selectItem.value.value = value;
props.multiple && (selectItem.value.value = []); selectItem.value.label = value.map((o) => ItemsMap.value[o]);
selectItem.value.label = props.multiple ? [] : null; } else {
} console.error("多选时请传入数组值");
} }
); } else {
selectItem.value.value = value;
//@ts-ignore
selectItem.value.label = ItemsMap.value[value] || "";
}
});
// //
const disabledItemMap: { [key: string | number]: boolean } = {}; const disabledItemMap: { [key: string | number]: boolean } = {};
const selectItemHandle = function ( const selectItemHandle = function (
_selectItem: SelectItem, _selectItem: SelectItem,
isChecked?: boolean isChecked?: boolean
) { ) {
if (!props.multiple) { if (!props.multiple) {
openState.value = false; openState.value = false;
} }
disabledItemMap[_selectItem.value as string | number] = disabledItemMap[_selectItem.value as string | number] =
_selectItem.disabled as boolean; _selectItem.disabled as boolean;
if (typeof isChecked !== "boolean") { if (typeof isChecked !== "boolean") {
props.multiple props.multiple
? (selectItem.value.label as any[]).push(_selectItem.label) ? (selectItem.value.label as any[]).push(_selectItem.label)
: (selectItem.value.label = _selectItem.label); : (selectItem.value.label = _selectItem.label);
return; return;
} }
let values = selectItem.value.value; let values = selectItem.value.value;
if (props.multiple && Array.isArray(values)) { if (props.multiple && Array.isArray(values)) {
const _values = values as any[]; const _values = values as any[];
const _labels = selectItem.value.label as any[]; const _labels = selectItem.value.label as any[];
if (isChecked) { if (isChecked) {
_values.push(_selectItem.value); _values.push(_selectItem.value);
_labels.push(_selectItem.label); _labels.push(_selectItem.label);
} else { } else {
_values.splice(_values.indexOf(_selectItem.value), 1); _values.splice(_values.indexOf(_selectItem.value), 1);
_labels.splice(_labels.indexOf(_selectItem.label), 1); _labels.splice(_labels.indexOf(_selectItem.label), 1);
} }
selectItem.value.value = _values; selectItem.value.value = _values;
selectItem.value.label = _labels; selectItem.value.label = _labels;
} else { } else {
selectItem.value.value = _selectItem.value; selectItem.value.value = _selectItem.value;
selectItem.value.label = _selectItem.label; selectItem.value.label = _selectItem.label;
} }
}; };
const removeItemHandle = function (e: MouseEvent, _selectItem: SelectItem) { const removeItemHandle = function (e: MouseEvent, _selectItem: SelectItem) {
e.stopPropagation(); e.stopPropagation();
selectItemHandle(_selectItem, false); selectItemHandle(_selectItem, false);
};
const ItemsMap: Ref<{ [index: string]: string }> = ref({});
const selectItemPush = function (p: SelectItem) {
if (p.value !== null) {
//@ts-ignore
ItemsMap.value[p.value] = p.label;
}
}; };
provide("selectItemHandle", selectItemHandle); provide("selectItemHandle", selectItemHandle);
provide("selectItem", selectItem); provide("selectItem", selectItem);
provide("selectItemPush", selectItemPush);
</script> </script>

View File

@ -1,65 +1,81 @@
<template> <template>
<dd <dd
:value="value" :value="value"
:class="[{ 'layui-this': selected }, { 'layui-disabled': disabled }]" :class="[{ 'layui-this': selected }, { 'layui-disabled': disabled }]"
@click="selectHandle" @click="selectHandle"
> >
<template v-if="selectItem.multiple"> <template v-if="selectItem.multiple">
<lay-checkbox <lay-checkbox
skin="primary" skin="primary"
v-model="selected" v-model="selected"
@change="selectHandle" @change="selectHandle"
label="" label=""
/> />
</template> </template>
<slot>{{ label }}</slot> <slot>{{ label }}</slot>
</dd> </dd>
</template> </template>
<script lang="ts"> <script lang="ts">
export default { export default {
name: "LaySelectOption", name: "LaySelectOption",
}; };
</script> </script>
<script setup lang="ts"> <script setup lang="ts">
import LayCheckbox from "../checkbox"; import LayCheckbox from "../checkbox";
import { SelectItem, SelectItemHandle } from "../type"; import { SelectItem, SelectItemHandle, SelectItemPush } from "../type";
import { computed, defineProps, inject, onMounted, Ref } from "vue"; import { computed, defineProps, inject, onMounted, Ref } from "vue";
const props = withDefaults( const props = withDefaults(
defineProps<{ defineProps<{
value: string | null | undefined; value: string | null | undefined;
label?: string; label?: string;
disabled?: boolean; disabled?: boolean;
}>(), }>(),
{ {
disabled: false, disabled: false,
} }
); );
const selectItemHandle = inject("selectItemHandle") as SelectItemHandle; const selectItemHandle = inject("selectItemHandle") as SelectItemHandle;
const selectItem = inject("selectItem") as Ref<SelectItem>; const selectItem = inject("selectItem") as Ref<SelectItem>;
const selectItemPush = inject("selectItemPush") as Ref<SelectItemPush>;
const selectHandle = function () { const selectHandle = function () {
!props.disabled && callSelectItemHandle(!selected.value); !props.disabled && callSelectItemHandle(!selected.value);
} };
const callSelectItemHandle = function(isChecked ?: boolean){ const callSelectItemHandle = function (isChecked?: boolean) {
selectItemHandle({ // console.log("callSelectItemHandle");
value : props.value, selectItemHandle(
label : props.label, {
disabled : props.disabled value: props.value,
}, isChecked); label: props.label,
} disabled: props.disabled,
},
isChecked
);
};
const selected = computed({ const selected = computed({
get(){ get() {
const selectValues = selectItem.value.value; const selectValues = selectItem.value.value;
if (Array.isArray(selectValues)) { if (Array.isArray(selectValues)) {
return (selectValues as any[]).indexOf(props.value) > -1; return (selectValues as any[]).indexOf(props.value) > -1;
} }
return selectItem.value.value === props.value return selectItem.value.value === props.value;
}, },
set(val){} set(val) {},
}) });
onMounted(() => selected.value && callSelectItemHandle()) const callSelectItemPush = function () {
let item = {
value: props.value,
label: props.label,
disabled: props.disabled,
};
selectItemPush(item);
};
onMounted(() => {
callSelectItemPush();
selected.value && callSelectItemHandle();
});
</script> </script>

View File

@ -9,3 +9,7 @@ export interface SelectItem {
export interface SelectItemHandle { export interface SelectItemHandle {
(selectItem: SelectItem, isChecked?: boolean): void; (selectItem: SelectItem, isChecked?: boolean): void;
} }
export interface SelectItemPush {
(selectItem: SelectItem): void
}