!17 [修复] select组件中外部参数变更后组件内的数值变化不生效的问题
Merge pull request !17 from 鄢鹏权/develop
This commit is contained in:
commit
de3b058f07
@ -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>
|
||||||
|
@ -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"
|
||||||
/>页
|
/>页
|
||||||
|
@ -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>
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user