jjy-store-select-mobile
jjy-store-select-mobile
uni-app(Vue3)移动端门店选择下拉组件:触发器 + 全屏遮罩 + 弹出面板(搜索 + 列表 + 当前项高亮)。纯 UI,无 Pinia / 网络 / UI 库依赖,仅依赖 vue。
特性
- 触发器 + 遮罩 + 面板一体化,一行标签接入
- 本地搜索(编码 / 名称包含匹配,忽略大小写)
- 当前门店高亮(颜色可配)
- 跨端:飞书/微信小程序、H5、App(仅用 view/input/scroll-view 等基础能力与 rpx)
- 触发器文字色继承宿主,深浅色导航栏均适配
- options 防御性清洗,可直接传 Pinia 响应式数组
安装
npm install jjy-store-select-mobile
消费方工程需自备
sass(组件使用lang="scss")。
使用
方式一:局部引入(推荐)
<template>
<jjy-store-select-mobile
:model-value="currentStoreCode"
:options="storeList"
panel-top="248rpx"
@change="onStoreChange"
>
<template #trigger-icon>
<text class="my-icon">🏪</text>
</template>
</jjy-store-select-mobile>
</template>
<script setup>
import { ref } from 'vue'
// ⚠️ 必须直连 .vue 子路径,不要从包入口 'jjy-store-select-mobile' 引入:
// 经 index.js 间接 re-export 时,uni-app 小程序编译器不会把组件注册进
// usingComponents(构建"成功"但运行时渲染空白),H5 端则两者皆可。
import JjyStoreSelectMobile from 'jjy-store-select-mobile/components/jjy-store-select-mobile/jjy-store-select-mobile.vue'
const currentStoreCode = ref('')
const storeList = ref([
{ value: '1001', text: '1001-烟台幸福门店' },
{ value: '1002', text: '1002-青岛市南门店' },
])
const onStoreChange = (item) => {
// item: { value: '1002', text: '1002-青岛市南门店' }
console.log('选中', item.value, item.text)
}
</script>
方式二:easycom 全局注册
pages.json:
{
"easycom": {
"custom": {
"^jjy-store-select-mobile$": "jjy-store-select-mobile/components/jjy-store-select-mobile/jjy-store-select-mobile.vue"
}
}
}
配置后模板直接使用 <jjy-store-select-mobile />,无需 import。
层级注意事项(重要)
面板/遮罩是组件内的 position: fixed 元素(z-index 99999 / 100000),但 z-index 只在最近的层叠上下文内生效。若组件的任一祖先(如导航栏的行容器)设置了 z-index、transform、filter 等形成层叠上下文的属性,面板会被困在其中,被宿主 DOM 靠后的内容遮挡——典型症状:面板只露出导航栏以下部分,上半段(含面板搜索框)被导航压住。
接入时请确保组件到页面根节点之间没有这类祖先;若无法避免,去掉祖先的 z-index 即可(position: relative + z-index: auto 不构成层叠上下文,可安全使用)。
持久化选中值
组件不存储数据。如需"v-model + 自己保存":
<jjy-store-select-mobile v-model="currentStoreCode" :options="storeList" @change="save" />
若写入需走特定 action(如 Pinia 的 setCurrentStore 持久化),请用 :model-value + @change 手动写入,避免 v-model 绕过。
Props
| 属性 | 类型 / 默认值 | 说明 |
|---|---|---|
| modelValue | String / '' |
当前门店编码;触发器显示匹配项 text |
| options | Array<{value, text}> / [] |
门店集合 |
| placeholder | String / '请选择门店' |
未选中时触发器文案 |
| searchPlaceholder | String / '搜索门店编码 / 名称' |
搜索框占位 |
| searchable | Boolean / true |
是否显示搜索框 |
| listHeight | String / '480rpx' |
列表滚动区高度 |
| panelTop | String / '248rpx' |
面板距视口顶部偏移(按导航栏高度调) |
| highlightColor | String / '#e85241' |
当前门店高亮色 |
Events
| 事件 | 参数 | 说明 |
|---|---|---|
| update:modelValue | value: String |
v-model 更新 |
| change | item: {value, text} |
选中完整对象 |
| visible-change | visible: Boolean |
面板开合 |
Slots
| 名称 | 说明 |
|---|---|
| trigger-icon | 触发器左侧图标(包内不含 iconfont,由消费方提供) |
暴露方法(ref 调用)
| 方法 | 说明 |
|---|---|
| close() | 关闭面板并重置搜索词;建议在页面 onHide 调用,保持"页面隐藏收起面板"体验 |
本地开发
npm install
npm test # vitest 跑 utils 单测
npm pack --dry-run
License
MIT
Related Packages
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 0.1.1 | ^3.2.0 | MIT | |
| 0.1.0 | ^3.2.0 | MIT |