uniapp u--input实现select下拉列表 input点击事件

背景:

技术框架:

uniapp框架(vue2语法)+uView组件库。

通过form表单实现数据列表的“查询”功能。注意:

1、<u--form>内部嵌套<u-form-item>,<u-form-item>内部嵌套<u--input>表单组件。

2、H5浏览器端,input输入框可以整块点击。但uniapp打包成App,不能整块点击;在平板上运行,可以整块点击。

3、input实现 select下拉列表功能

4、在App上,实现input输入框的整块点击,点击之后出现select弹框区域。

5、Form表单封装组件。接收绑定Form的数据(父传子formItems[]);监听formInline的变化,监听到变化后emit(子传父,)

 

效果展示:

 

官网链接:点击跳转官网 form

 接下来便是要解决的问题:让整块input输入框都可以点击。。。

 一、selet下拉列表的实现

实现思路:

input输入框,通过点击右侧的插槽图标,实现select弹框弹出。实际是两部分组成。。。

<u--input 
    :readonly="true" 
    v-model="inputValue" 
    :placeholder="'请选择'"
    suffixIcon="arrow-down" 
>
</u--input>

下拉列表:

<!-- 下拉列表显示 -->
<u-action-sheet 
    :show="showOption" 
    :actions="currentSelectItem.option.optionList"
    :title="currentSelectItem.option.title" 
    :description="currentSelectItem.option.description"
    @close="handleCloseOption(false)" 
    @select="handleSelect" 
    v-if="currentSelectItem.option"
>
</u-action-sheet>

官网链接:点击跳转官网 action-sheet

 

二、input框整块点击,打开select弹框

实现思路:

要想实现input框的整块点击。

实现思路是:

1、给当前input外层套一个盒子,在此盒子上绑定@click事件;

2、给input添加鼠标点击样式:style="pointer-events:none"。

none表示:鼠标事件“穿透”该元素并且指定该元素“下面”的任何东西。

给input外层套一层盒子,并绑定事件:

<template @click='handleOpenOption(item)'>
<u--input 
:readonly="true" 
style="pointer-events:none" 
v-model="inputValue"				
:placeholder="'整块点击'" 
suffixIcon="arrow-down" 
>
</u--input>
</template>

 事件:

methods: {
		handleOpenOption(item) {
			if (item.type === 'calendar') {
				this.currentSelectItem = {
					...item
				};
				this.handleCloseCalendar(true);//打开日期选择弹框
			}
			if (item.type === 'select') {
				this.currentSelectItem = {
					...item
				};
				this.handleCloseOption(true);//打开select弹框
			}
		},
}

三、封装form表单组件

背景:

理论知识:

父传子:通过props,获取到传递到子组件的formItems[];

子传父:通过watch监听表单组件绑定的数据的变化,使用emit('自定义事件名',传给父组件的数据值)

图片:

 formItems封装代码:

//formItems分装代码
<template>
	<view>
		<u--form labelPosition="left" :model="formInline" :rules="formRules" ref="uForm" :errorType="errorType">
			<u-form-item :required="item.rule.required" labelWidth="230rpx" labelAlign="right" :label="item.label"
				:prop="item.key" :borderBottom="false" @tap="handleOpenOption(item)" v-for="item, index in formItems"
				:key="index">
				<u--input v-model="formInline[item.key]" :placeholder="item.placeholder" v-if="item.type === 'input'"
					:customStyle="item.customStyle"></u--input>
				<!-- input带后置图标 -->
				<u--input v-model="formInline[item.key]" :placeholder="item.placeholder" suffixIcon="search"
					suffixIconStyle="color: #333333;font-size: 42rpx" v-if="item.type === 'input2'"
					:customStyle="item.customStyle" :clearable="true" @clear="handleClear(item.key)"></u--input>
				<!-- 以下点击设置hideKeyboard(),让移动端不弹出键盘 -->
				<template @click='handleOpenOption(item)'>
					<u--input :readonly="true" style="pointer-events:none" v-model="formInline[item.key].name"
						:placeholder="item.placeholder" suffixIcon="arrow-down" v-if="item.type === 'select'"
						:customStyle="item.customStyle"></u--input>
				</template>
				<template @click='handleOpenOption(item)'>
					<u--input :readonly="true" style="pointer-events:none" v-model="formInline[item.key]"
						:placeholder="item.placeholder" suffixIcon="clock" v-if="item.type === 'calendar'"
						:customStyle="item.customStyle" :clearable="true" @clear="handleClear(item.key)" ></u--input>
				</template>
			</u-form-item>
		</u--form>
		<!-- 下拉列表显示 -->
		<u-action-sheet :show="showOption" :actions="currentSelectItem.option.optionList"
			:title="currentSelectItem.option.title" :description="currentSelectItem.option.description"
			@close="handleCloseOption(false)" @select="handleSelect" v-if="currentSelectItem.option">
		</u-action-sheet>
		<!-- 日历显示 -->
		<u-calendar :closeOnClickOverlay="true" monthNum="12" :minDate="minDate" :maxDate="maxDate" :show="showCalendar"
			mode="range" :allowSameDay="true" @confirm="handleConfirmCalendar"
			@close="handleCloseCalendar(false)"></u-calendar>
	</view>
</template>

<script>
import {
	getLayerData
} from '@/api/index.js'

export default {
	name: "FormItem",
	data() {
		return {
			formInline: {},
			formRules: {},

			showOption: false,
			currentSelectItem: {},
			showCalendar: false,
			readonlyCalendar: true,
			minDate: '2023-01-01',
			maxDate: '2023-11-07',
		};
	},
	props: {
		formItems: Array,
		errorType: {
			type: String,
			default: 'none'
		}
	},
	computed: {},
	watch: {
		formItems: {
			immediate: true,
			handler(newval, oldval) {
				newval.forEach(item => {
					// 动态请求下拉列表
					(item.type === 'select' && item.option.optionsSrc) && this.getOptionList(item);
					this.getFormRules();
					this.getFormInlineDefault();
				});
			}
		},
		formInline: {
			immediate: true,
			deep: true,
			handler(newval, oldval) {
				this.$emit('searchData', newval);
			}
		}
	},
	methods: {
		handleConfirmCalendar(e) { //日历选项选择完毕确认
			this.formInline[this.currentSelectItem.key] = e[0] + '至' + e[e.length - 1]
			this.handleCloseCalendar(false);
			// this.readonlyCalendar = !this.readonlyCalendar;
		},
		handleCloseCalendar(state) { //日历选项关闭
			this.showCalendar = state;
		},

		handleOpenOption(item) {
			if (this.readonlyCalendar) {
				if (item.type === 'calendar') {
					this.currentSelectItem = {
						...item
					};
					this.handleCloseCalendar(true);
				}
			}
			if (item.type === 'select') {
				//当前选择框的信息,因为复用了同一个下拉选择弹出层
				this.currentSelectItem = {
					...item
				};
				this.handleCloseOption(true);
			}
		},
		handleSelect(e) { //下拉选项选择目标逻辑
			this.formInline[this.currentSelectItem.key] = e;
		},
		handleCloseOption(state) { //下拉选项关闭逻辑
			this.showOption = state;
		},
		async getOptionList(item) {
			const {
				data: res
			} = await getLayerData(item.option.optionsSrc);
			const resData = res.data;
			item.option.optionList = resData.reduce((cre, pre) => [...cre, {
				name: pre[item.option.optionContent.name],
				// 下拉选项是对各值还是一个值
				value: item.option.optionContent.value === 'objString' ? JSON.stringify(pre) : pre[
					item.option.optionContent.value]
			}], [...item.option.options]);

			this.getFormInlineDefault();
		},
		getFormInlineDefault() {
			this.formInline = this.formItems.reduce((cre, pre) => {
				let handlePre = '';
				if (pre.defaultVal) {
					if (pre.defaultVal instanceof Array) {
						// 动态请求的内容作为默认值
						if (pre.option.optionList?.length > pre.defaultVal[0]) {
							handlePre = pre.option.optionList[pre.defaultVal[0]];
						} else {
							const emptyTarget = pre.option.optionList?.find(item => item.value === '')
							handlePre = emptyTarget || '';
						}
					} else {
						handlePre = pre.defaultVal;
					}
				} else {
					// const emptyTarget = pre.option?.optionList?.find(item => item.value === '')
					// handlePre = emptyTarget || '';
					handlePre = ''
				}
				return {
					...cre,
					[pre.key]: handlePre
				}
			}, {});
		},
		getFormRules() {
			this.formRules = this.formItems.reduce((cre, pre) => {
				return pre.rule && {
					...cre,
					[pre.key]: pre.rule
				}
			}, {});
		},
		handleClear(_key) {
			this.formInline[_key] = '';
			this.readonlyCalendar = true;
			this.readonlySelect = true
		},
		clickshowOption() {
			this.showOption = !this.showOption
		},
		getCurrentData() {
			const d = new Date()
			const year = d.getFullYear()
			let month = d.getMonth() + 1
			month = month < 10 ? `0${month}` : month
			const date = d.getDate()
			return [`${year}-${month}-${date}`]
		},
		getMinDate(_yesteMonth) {
			const yesteMonth = _yesteMonth || 2
			const d = new Date()
			const year = d.getFullYear()
			let month = d.getMonth() - yesteMonth
			month = month < 10 ? `0${month}` : month
			const date = d.getDate()
			return `${year}-${month}-${date}`
		}
	},
	onLoad() {
		this.formInline = {}
	},
	created() {
		this.maxDate = this.getCurrentData()[0]
		this.minDate = this.getMinDate(6)
	}
}
</script>

<style scoped lang="scss">
/deep/.u-form {

	>.u-form-item {

		>.u-form-item__body {
			padding: 0;

			>.u-form-item__body__right {
				// background-color: #F6F7FA;
				/* border-radius: 12rpx;
					border: 1px solid #E3E7EE;
					padding: 10rpx; */
			}
		}
	}
}

// /deep/ .u-input__content__clear {
// 	position: relative;
// }

// /deep/.u-icon__icon {
// 	position: absolute;
// 	left: 0px;
// 	right: 0px;
// 	top: 0px;
// 	bottom: 0px;
// 	justify-content: center;
// }</style>

父组件使用方法:

//父传子myformItems
//子传父触发事件mysearchData
<FormItem :formItems="myformItems" @searchData="mysearchData"></FormItem>

上面用到的数据和方法:

数据formItems,示例如下:

[
    {
      type: "input2",
      // label: "船舶名称",
      key: "name",
      placeholder: "请输入船舶名称",
      rule: {
        required: false,
      },
      customStyle: {
        "margin-bottom": "20rpx",
      },
    },
    {
      type: "input2",
      // label: "MMSI",
      key: "mmsi",
      placeholder: "请输入MMSI",
      rule: {
        required: false,
      },
      customStyle: {
        "margin-bottom": "20rpx",
      },
    },
  ],

 mysearchData事件,示例如下:

methods: {
        mysearchData(_data) {
            console.log(_data);
            this.pages.name = _data.name
            this.pages.mmsi = _data.mmsi
            this.pages.pageNum = 1
            this.pages.pageSize = 7
            this.getTableList(this.pages)//查询接口
         }
}

uniapp中的`hpy-form-select`组件是一个表单下拉选择组件,用于在用户界面中提供一个可选择的下拉列表。要在该组件中添加搜索功能,通常需要使用`filter`属性来对选项进行过滤。以下是添加搜索功能的基本步骤: 1. 在数据中定义一个变量来保存搜索关键词,例如`searchKey`。 2. 绑定一个事件处理函数到`hpy-form-select`组件的`@input`事件,该事件会在用户输入时触发。 3. 在事件处理函数中,根据`searchKey`的值动态过滤`options`数据,只保留那些匹配搜索关键词的选项。 4. 将过滤后的结果传递给`hpy-form-select`组件的`options`属性,从而更新下拉列表中的选项。 示例代码如下: ```html <template> <view> <!-- 搜索框 --> <input type="text" placeholder="输入搜索关键词" v-model="searchKey" @input="filterOptions" /> <!-- 下拉选择组件 --> <hpy-form-select :options="filteredOptions"> </hpy-form-select> </view> </template> <script> export default { data() { return { searchKey: '', // 搜索关键词 options: [ { label: '选项1', value: '1' }, { label: '选项2', value: '2' }, // ...更多选项 ], filteredOptions: [] // 过滤后的选项 }; }, methods: { filterOptions() { // 简单的搜索功能实现:过滤options中的数据 const key = this.searchKey.trim().toLowerCase(); this.filteredOptions = this.options.filter(item => item.label.toLowerCase().includes(key)); } } }; </script> ``` 在上述代码中,我们在`<input>`标签中使用了`v-model`指令来双向绑定输入框的值到`searchKey`变量。每当用户输入时,`filterOptions`方法会被调用,它会根据`searchKey`的值过滤`options`,然后将结果赋值给`filteredOptions`,这个过程会实时更新`hpy-form-select`组件中显示的选项。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值