perf: 优化分段控制器组件,添加v-model支持

This commit is contained in:
xiaoxian521 2023-10-21 19:46:26 +08:00
parent 59fcac86c4
commit af224dceea
2 changed files with 37 additions and 48 deletions

View File

@ -2,31 +2,33 @@ import "./index.css";
import { import {
h, h,
ref, ref,
toRef,
watch, watch,
nextTick, nextTick,
defineComponent, defineComponent,
getCurrentInstance getCurrentInstance
} from "vue"; } from "vue";
import type { OptionsType } from "./type"; import type { OptionsType } from "./type";
import { isFunction, useDark } from "@pureadmin/utils";
import { useRenderIcon } from "@/components/ReIcon/src/hooks"; import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import { isFunction, isNumber, useDark } from "@pureadmin/utils";
const props = { const props = {
options: { options: {
type: Array<OptionsType>, type: Array<OptionsType>,
default: () => [] default: () => []
}, },
/** 默认选中,按照第一个索引为 `0` 的模式 */ /** 默认选中,按照第一个索引为 `0` 的模式,可选(`modelValue`只有传`number`类型时才为响应式) */
defaultValue: { modelValue: {
type: Number, type: undefined,
default: 0 require: false,
default: "0"
} }
}; };
export default defineComponent({ export default defineComponent({
name: "ReSegmented", name: "ReSegmented",
props, props,
emits: ["change"], emits: ["change", "update:modelValue"],
setup(props, { emit }) { setup(props, { emit }) {
const width = ref(0); const width = ref(0);
const translateX = ref(0); const translateX = ref(0);
@ -35,12 +37,16 @@ export default defineComponent({
const curMouseActive = ref(-1); const curMouseActive = ref(-1);
const segmentedItembg = ref(""); const segmentedItembg = ref("");
const instance = getCurrentInstance()!; const instance = getCurrentInstance()!;
const curIndex = ref(props.defaultValue); const curIndex = isNumber(props.modelValue)
? toRef(props, "modelValue")
: ref(0);
function handleChange({ option, index }, event: Event) { function handleChange({ option, index }, event: Event) {
if (option.disabled) return; if (option.disabled) return;
event.preventDefault(); event.preventDefault();
curIndex.value = index; isNumber(props.modelValue)
? emit("update:modelValue", index)
: (curIndex.value = index);
segmentedItembg.value = ""; segmentedItembg.value = "";
emit("change", { index, option }); emit("change", { index, option });
} }

View File

@ -1,5 +1,5 @@
<script setup lang="tsx"> <script setup lang="tsx">
import { h } from "vue"; import { h, ref } from "vue";
import { message } from "@/utils/message"; import { message } from "@/utils/message";
import HomeFilled from "@iconify-icons/ep/home-filled"; import HomeFilled from "@iconify-icons/ep/home-filled";
import { useRenderIcon } from "@/components/ReIcon/src/hooks"; import { useRenderIcon } from "@/components/ReIcon/src/hooks";
@ -10,51 +10,43 @@ defineOptions({
}); });
/** 基础用法 */ /** 基础用法 */
const value = ref(4); // number
const optionsBasis: Array<OptionsType> = [ const optionsBasis: Array<OptionsType> = [
{ {
label: "周一", label: "周一"
value: 1
}, },
{ {
label: "周二", label: "周二"
value: 2
}, },
{ {
label: "周三", label: "周三"
value: 3
}, },
{ {
label: "周四", label: "周四"
value: 4
}, },
{ {
label: "周五", label: "周五"
value: 5
} }
]; ];
/** 禁用 */ /** 禁用 */
const optionsDisabled: Array<OptionsType> = [ const optionsDisabled: Array<OptionsType> = [
{ {
label: "周一", label: "周一"
value: 1
}, },
{ {
label: "周二", label: "周二"
value: 2
}, },
{ {
label: "周三", label: "周三",
value: 3,
disabled: true disabled: true
}, },
{ {
label: "周四", label: "周四"
value: 4
}, },
{ {
label: "周五", label: "周五",
value: 5,
disabled: true disabled: true
} }
]; ];
@ -63,26 +55,21 @@ const optionsDisabled: Array<OptionsType> = [
const optionsIcon: Array<OptionsType> = [ const optionsIcon: Array<OptionsType> = [
{ {
label: "周一", label: "周一",
value: 1,
icon: HomeFilled icon: HomeFilled
}, },
{ {
label: "周二", label: "周二"
value: 2
}, },
{ {
label: "周三", label: "周三",
value: 3,
icon: "terminalWindowLine" icon: "terminalWindowLine"
}, },
{ {
label: "周四", label: "周四",
value: 4,
icon: "streamline-emojis:airplane" icon: "streamline-emojis:airplane"
}, },
{ {
label: "周五", label: "周五",
value: 5,
icon: "streamline-emojis:2" icon: "streamline-emojis:2"
} }
]; ];
@ -90,23 +77,18 @@ const optionsIcon: Array<OptionsType> = [
/** 只设置图标 */ /** 只设置图标 */
const optionsOnlyIcon: Array<OptionsType> = [ const optionsOnlyIcon: Array<OptionsType> = [
{ {
value: 1,
icon: HomeFilled icon: HomeFilled
}, },
{ {
value: 2,
icon: "terminalWindowLine" icon: "terminalWindowLine"
}, },
{ {
value: 3,
icon: "streamline-emojis:cow-face" icon: "streamline-emojis:cow-face"
}, },
{ {
value: 4,
icon: "streamline-emojis:airplane" icon: "streamline-emojis:airplane"
}, },
{ {
value: 5,
icon: "streamline-emojis:2" icon: "streamline-emojis:2"
} }
]; ];
@ -121,8 +103,7 @@ const optionsLabel: Array<OptionsType> = [
})} })}
<p>周一</p> <p>周一</p>
</div> </div>
), )
value: 1
}, },
{ {
label: () => ( label: () => (
@ -132,8 +113,7 @@ const optionsLabel: Array<OptionsType> = [
})} })}
<p>周二</p> <p>周二</p>
</div> </div>
), )
value: 2
}, },
{ {
label: () => ( label: () => (
@ -143,8 +123,7 @@ const optionsLabel: Array<OptionsType> = [
})} })}
<p>周三</p> <p>周三</p>
</div> </div>
), )
value: 3
} }
]; ];
@ -179,11 +158,15 @@ function onChange({ index, option }) {
<span class="font-medium">分段控制器</span> <span class="font-medium">分段控制器</span>
</div> </div>
</template> </template>
<p class="mb-2">基础用法</p> <p class="mb-2">
<Segmented :options="optionsBasis" /> 基础用法v-model<span class="text-primary">
{{ optionsBasis[value].label }}
</span>
</p>
<Segmented :options="optionsBasis" v-model="value" />
<el-divider /> <el-divider />
<p class="mb-2">默认选中和禁用</p> <p class="mb-2">禁用</p>
<Segmented :options="optionsDisabled" :defaultValue="2" /> <Segmented :options="optionsDisabled" />
<el-divider /> <el-divider />
<p class="mb-2">设置图标</p> <p class="mb-2">设置图标</p>
<Segmented :options="optionsIcon" /> <Segmented :options="optionsIcon" />