前端模糊搜索关键字高亮

效果

original-original

代码

<template>
	<view class="flexStart new-box">
		<view class="company">
			<!-- 输入框样式 -->
			<view class="spaceBetween companyName" @click.stop="isCompany = true">
				<input type="text"
					:style="result.userName.length > 0 ? 'padding-right: 90rpx !important;' : 'padding-right: 0rpx !important;'"
					@input="companyInput" v-model="result.userName" placeholder="请输入文本内容" placeholder-class="placeholderClass" />
				<!-- 清除按钮,使用的是icon,直接拷代码会失效 -->
				<view v-if="result.userName != ''" @click.stop="clearCompany" class="close center">
					<text class="iconfont icon-icon-qingchu"></text>
				</view>
			</view>
			<!-- 列表循环 -->
			<scroll-view v-if="isCompany" scroll-y="true" class="companyPrick">
				<view v-for="(item,index) in filterMsg" :key="index" @click="prickCompany(item)"
					class="companyPrick-item">
					<!-- 每一行的字做拆分,匹配合格的返回 true 高亮 -->
					<span :class="dealStr(str) ? 'hightLight' : ''" v-for="(str,strIndex) in item.name"
						:key="strIndex">{{str}}</span>
				</view>
			</scroll-view>
			<!-- 三角形样式 -->
			<view v-if="isCompany" class="triangle"></view>
		</view>
	</view>
</template>

<script setup lang="ts">
	import { ref } from 'vue';
	import { onLoad } from '@dcloudio/uni-app';

	const isCompany = ref(false) // 是否显示下拉框
	const result = ref({ // 提交的数据
		"userName": "",
		"userId": 0,
	})

	const companyList = ref([ // 接口获取数据
		{
			"id": 284,
			"name": "测试智能公司",
		},
		{
			"id": 286,
			"name": "北京文娱有限公司",
		},
		{
			"id": 289,
			"name": "广州市天河快递有限公司",
		},
		{
			"id": 290,
			"name": "广东天河电子科技有限公司",
		},
		{
			"id": 291,
			"name": "广州市天河汽车维修服务有限公司",
		},
		{
			"id": 293,
			"name": "智能化工厂",
		},
		{
			"id": 294,
			"name": "广州天河物联智能科技有限公司",
		},
		{
			"id": 295,
			"name": "测试工程开发",
		},
		{
			"id": 300,
			"name": "广东立智科技",
		},
		{
			"id": 302,
			"name": "广州番禺云服务科技",
		}
	])
	const filterMsg = ref([]) // 实际展现数据

	// 对输入内容处理判断是否符合条件
	function companyInput() {
        // result.value.userName 输入的内容
		let queryStringArr = result.value.userName.split("");
		let str = "(.*?)";
		filterMsg.value = [];
		let regStr = str + queryStringArr.join(str) + str;
		let reg = RegExp(regStr, "i"); // 以mh为例生成的正则表达式为/(.*?)m(.*?)h(.*?)/i
		companyList.value.map(item => {
			if (reg.test(item.name)) {
				filterMsg.value.push(item);
			}
		});
		// 输入为空时显示全部数据
		if (result.value.userName == '') {
			filterMsg.value = companyList.value
		}
	}
	
	// 字体高亮设置
	function dealStr(str : string) {
		let status = false
		for (let i = 0; i < result.value.userName.length; i++) {
			if (result.value.userName[i] == str) {
				status = true
			}
		}
		return status
	}

	// 点击选择单位
	function prickCompany(item : any) {
		result.value.userId = item.id as number
		result.value.userName = item.name
		isCompany.value = false
		companyInput()
	}

	// 清除输入框
	function clearCompany() {
		result.value.userId = 0
		result.value.userName = ""
		filterMsg.value = companyList.value
	}

	// 获取的数据给实际处理列表赋值,在接口处处理即可
	onLoad(() => {
		filterMsg.value = companyList.value
	})
</script>

<style lang="scss">
	.new-box {
		width: 100vw;
		height: 100vh;
		flex-flow: column;
	}

	.flexStart {
		display: flex;
		justify-content: flex-start;
		align-items: center;
	}

	.spaceBetween {
		display: flex;
		justify-content: space-between;
		align-items: center;
	}

	.center {
		display: flex;
		justify-content: center;
		align-items: center;
	}


	.company {
		margin-top: 20vh;
		border-radius: 20rpx;
		// padding: 20rpx 32rpx 28rpx 32rpx;
		flex-flow: column;
		display: flex;
		justify-content: space-between;
		align-items: flex-start;
		position: relative;
		box-shadow: 0rpx 0rpx 20rpx 0rpx rgba(0, 82, 217, 0.3);

		.titleName {
			padding: 20rpx 32rpx 0 32rpx;
			font-weight: 600;
			font-size: 32rpx;
		}

		.companyName {
			width: 686rpx;
			font-family: PingFang SC, PingFang SC;
			font-weight: 600;
			font-size: 36rpx;
			position: relative;
			// color: rgba(0, 0, 0, 0.9);

			input {
				padding: 20rpx 32rpx 20rpx 32rpx;
				width: 622rpx;
				color: #3D3D3D;
			}

			.close {
				right: 0;
				padding: 20rpx;
				position: absolute;
				width: 42rpx;
				height: 42rpx;
			}

			.icon-icon-qingchu {
				font-size: 36rpx;
				color: rgba(0, 0, 0, 0.40);
			}
		}

		.companyPrick {
			box-shadow: 0rpx 0rpx 20rpx 0rpx rgba(0, 82, 217, 0.3);
			z-index: 99;
			left: 0rpx;
			position: absolute;
			top: 140rpx;
			width: 622rpx;
			min-height: 60rpx;
			max-height: 400rpx;
			background: #FFFFFF;
			border-radius: 16rpx;
			padding: 20rpx 32rpx;

			.companyPrick-item {
				padding: 20rpx 0;
				font-family: PingFang SC, PingFang SC;
				font-weight: 600;
				font-size: 32rpx;
				color: #3D3D3D;
			}
		}
	}

	.rowTime {
		display: flex;
		flex-flow: row;
		justify-content: space-between;
		align-items: center;
	}

	.hightLight {
		color: rgba(0, 82, 217, 1);
	}

	.triangle {
		z-index: 100;
		position: absolute;
		top: 120rpx;
		right: 68rpx;
		width: 0;
		height: 0;
		border-left: 10px solid transparent;
		border-right: 10px solid transparent;
		border-bottom: 10px solid white;
	}
	
	.placeholderClass{
		color: rgba(0,0,0,0.26) !important;
	}
</style>
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值