完成下拉列表的实现
This commit is contained in:
parent
8f1153e739
commit
f82d972038
@ -1,15 +1,28 @@
|
|||||||
<template>
|
<template>
|
||||||
<li><slot></slot></li>
|
<li :ref="element" @click="onClick($event)">
|
||||||
|
<slot></slot>
|
||||||
|
</li>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import {defineComponent} from "vue";
|
import {defineComponent, onMounted, onUpdated, ref} from "vue";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "POption",
|
name: "POption",
|
||||||
props:{
|
props: {
|
||||||
value:{
|
value: {
|
||||||
type: [String,Number,Object],
|
type: [String, Number, Object],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emits: ['select'],
|
||||||
|
setup(props,context) {
|
||||||
|
function onClick(e) {
|
||||||
|
e.target.data = props.value
|
||||||
|
}
|
||||||
|
const element = ref<HTMLElement>()
|
||||||
|
|
||||||
|
return {
|
||||||
|
element,onClick
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="select-wrapper" :class="{active:isActive}" v-click-outside="onClose">
|
<div class="select-wrapper" :class="{active:isActive}" v-click-outside="onClose">
|
||||||
<div class="select-box-wrapper" @click="isActive = !isActive">
|
<div class="select-box-wrapper" @click="isActive = !isActive">
|
||||||
<div class="select-value">{{ selectValue }}<span class="placeholder">{{ placeholder }}</span></div>
|
<div class="select-value">{{ selectValue }}<span v-if="!selectValue" class="placeholder">{{ placeholder }}</span>
|
||||||
|
</div>
|
||||||
<div class="icon-arrow">
|
<div class="icon-arrow">
|
||||||
<ArrowDown class="icon-select-arrow"/>
|
<ArrowDown class="icon-select-arrow"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="select-options-wrapper">
|
<div class="select-options-wrapper">
|
||||||
<ul>
|
<ul @click="onSelect">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@ -16,7 +17,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import ArrowDown from "../icon/ArrowDown.vue";
|
import ArrowDown from "../icon/ArrowDown.vue";
|
||||||
import {ref} from "vue";
|
import {defineComponent, nextTick, ref, SetupContext} from "vue";
|
||||||
import {CHANGE_EVENT, UPDATE_MODEL_EVENT} from "../../service/constants";
|
import {CHANGE_EVENT, UPDATE_MODEL_EVENT} from "../../service/constants";
|
||||||
|
|
||||||
export interface OptionItemType {
|
export interface OptionItemType {
|
||||||
@ -26,7 +27,7 @@ export interface OptionItemType {
|
|||||||
|
|
||||||
// declare var OptionItemArray: OptionItemType[];
|
// declare var OptionItemArray: OptionItemType[];
|
||||||
|
|
||||||
export default {
|
export default defineComponent({
|
||||||
name: "PSelect",
|
name: "PSelect",
|
||||||
components: {ArrowDown},
|
components: {ArrowDown},
|
||||||
props: {
|
props: {
|
||||||
@ -34,6 +35,9 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
default: '请选择'
|
default: '请选择'
|
||||||
},
|
},
|
||||||
|
modelValue: {
|
||||||
|
type: [String, Number, Object]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
emits: [
|
emits: [
|
||||||
UPDATE_MODEL_EVENT,
|
UPDATE_MODEL_EVENT,
|
||||||
@ -41,17 +45,35 @@ export default {
|
|||||||
'focus',
|
'focus',
|
||||||
'blur',
|
'blur',
|
||||||
],
|
],
|
||||||
setup(props) {
|
setup(props, ctx: SetupContext) {
|
||||||
const selectValue = ref(props.modelValue)
|
const selectValue = ref(props.modelValue)
|
||||||
const isActive = ref(false)
|
const isActive = ref(false)
|
||||||
function onClose(){
|
|
||||||
|
function onSelect(e: MouseEvent) {
|
||||||
|
// 原生dom操作
|
||||||
|
const target = e.target as HTMLElement;
|
||||||
|
if (target.tagName.toLowerCase() != 'li') return;
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
//
|
||||||
|
const text = target.textContent
|
||||||
|
selectValue.value = text
|
||||||
|
const arr = [].slice.call (target.parentElement.children)
|
||||||
|
arr.forEach(ele => (ele as HTMLElement).classList.remove("selected"))
|
||||||
|
target.classList.add("selected")
|
||||||
|
ctx.emit(UPDATE_MODEL_EVENT,target.data)
|
||||||
|
onClose()
|
||||||
|
}
|
||||||
|
|
||||||
|
function onClose() {
|
||||||
isActive.value = false
|
isActive.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
selectValue, isActive,onClose
|
selectValue, isActive, onClose, onSelect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less">
|
<style lang="less">
|
||||||
@ -62,7 +84,8 @@ export default {
|
|||||||
.select-options-wrapper {
|
.select-options-wrapper {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
.select-box-wrapper{
|
|
||||||
|
.select-box-wrapper {
|
||||||
border-color: var(--primary-color);
|
border-color: var(--primary-color);
|
||||||
box-shadow: 0 0 3px var(--primary-color);
|
box-shadow: 0 0 3px var(--primary-color);
|
||||||
}
|
}
|
||||||
|
@ -20,17 +20,16 @@
|
|||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
商品类型
|
商品类型
|
||||||
<p-select>
|
<p-select v-model="select">
|
||||||
<p-option value="1">普通商品</p-option>
|
<p-option v-for="op in options" :key="op.value" :value="op">{{ op.label }}</p-option>
|
||||||
<p-option class="selected" value="2">精选商品</p-option>
|
|
||||||
<p-option value="3">秒杀商品</p-option>
|
|
||||||
</p-select>
|
</p-select>
|
||||||
|
{{ JSON.stringify(select) }}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import PInput from "../components/input";
|
import PInput from "../components/input";
|
||||||
import {reactive} from "vue";
|
import {reactive, ref} from "vue";
|
||||||
import PSelect from "../components/select/Select.vue";
|
import PSelect from "../components/select/Select.vue";
|
||||||
import POption from "../components/select/Option.vue";
|
import POption from "../components/select/Option.vue";
|
||||||
|
|
||||||
@ -38,6 +37,12 @@ const data = reactive({
|
|||||||
a: '1',
|
a: '1',
|
||||||
b: '2'
|
b: '2'
|
||||||
})
|
})
|
||||||
|
const options = [
|
||||||
|
{value: 1, label: '普通商品'},
|
||||||
|
{value: 2, label: '精选商品'},
|
||||||
|
{value: 3, label: '秒杀商品'},
|
||||||
|
]
|
||||||
|
const select = ref()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user