uniapp实现搜索功能详细步骤【前端开发】


首先放一下效果图:
在这里插入图片描述


I.场景的引入及前提条件

搜索的场景有很多很多,这里以搜索好友并添加作为演示的场景。

需求: 实现往搜索框中输入好友的姓名,能够实时在页面上反馈出搜索的结果,并选择是否添加为好友。

前提条件后端相关的搜索api,能接收POST/GET请求并返回json格式的数据。


II.搜索效果的制作

本文面向uniapp初学者或急需要做项目的小白,因而步骤较为详细,如果需要只需源码请直接link到第三部分。

1️⃣搭建界面基础

这部分对于掌握H5的小伙伴来说是小菜一碟了,直接开干即可:搭出一个搜索框和一个搜索按钮即可。

这部分的代码参考如下:

<template>
	<view>
		<view class="header">
			添加好友
		</view>
		<view class="searchInput">
			<input type="text" placeholder="请输入对方的昵称" v-model="friendName" @input="inputChanged"/>
		</view>
		<view class="searchbtn" @click="search">
			搜索            <span class="icon-search"></span>
		</view>
		<view :class = "currentclass">
			<view :class="currentIconClass"><image :class = "currentImgClass" :src="imgSrc" mode="widthFix"></image></view>
			<view :class="currentNickClass">
				<text>{{searchName}}</text>
			</view>
			<span @click="add" :class="currentFontIconClass"></span>
		</view>
	</view>
</template>

注意,在这一步,不用太care我的代码里面的绑定事件或类名,只需要简单了解一下布局的思路即可。(后面会讲解这些绑定事件和类名的使用)


2️⃣向后端发送请求获取数据

基础外观搭好之后,下一步是考虑向后端发起请求获取我们需要的数据。

这里可以再拆解成两个小步骤:

🌀第一步,给之前搭建的按钮添加点击事件,该事件即为搜索事件。

🌀第二步,在搜索事件的函数体内完成请求的发送

第一个小步骤没有要解释的,直接进行绑定即可(@tap或者@click均可),并给事件定义一个名称,例如search。

第二个小步骤是实现search事件

首先是在script部分定义search函数:

search(){
}

接下来,首先获取到发起搜索请求的这个用户的用户信息,例如用户名:

search(){
	this.userName = uni.getStorageSync("username_log"),
}

这一步的userName可定义在data()中。

分析为什么要进行上面的这一步,因为既然我们的目的是搜索好友,那为什么要获取发起搜索的这个用户的信息呢?

这是因为后续我们要通过这个信息来确定该用户搜索的好友是否已经是他的好友了(之前已经被添加了),从而完善我们的加好友功能。

下一步,拿到了发起搜索的这个用户的用户名之后,我们可以向后端发起请求了:

search(){
	this.userName = uni.getStorageSync("username_log"),
	uni.request({				
	            url:'https://www.xxxx',
				method:'GET',	
				data:{username : this.userName, friendname : this.friendName},
				header: {
					  'content-type': 'application/x-www-form-urlencoded'
					 },

上面这段请求基于uniapp发送请求的api,其中:

✅url即为后端给你提供的加好友的接口

✅method可选 “GET/POST”,这个也根据后端来调整

重点解释一下data,data是发给后端用于处理的数据,其中 :前:后分别代表了后端定义的数据名称和前端的数据变量名。

在上面的代码中,username代表了后端定义的一个变量名,表示它希望前端给它这个数据;this.userName表示前端定义的一个变量,它存着要给后端的数据。那么毫无疑问,这个this.userName就是之前说的发起搜索的用户的用户名。

第二个参数friendname同样是后端定义的一个变量名,而this.friendName是前端捕获的用户输入在搜索框中的数据,这个数据表示了用户想要搜索的好友的名称。

最后header部分可以直接复制我的无需修改(只要是互传JSON数据)


3️⃣回调函数

(注意上面的代码并不完整,不要直接复制上面的代码,会报错。需要直接拿到完整源码的请在文章第三部分自取)

这部分紧紧承接上面第二步的最后,当完成了对后端的请求,接下来就是写后端返回的信息对应的回调函数:

因为回调函数仍然在search()函数体内,因此我们仍然回到search()函数中。

对于回调函数的书写,考虑到严谨性,可以分成四种情况:

1.用户不存在

这种情况下,在回调之后,我们将会处理成在用户界面生成“该用户不存在”字样。

success: (res) => {
		if(this.friendName == "") return;
		this.searchName = res.data.username;
		if(this.searchName == null){
				this.searchName = "此用户不存在!"
				this.imgSrc = ""		
			}

在代码中,与后端协商后决定,当搜索对象不存在时,返回的username值是一个null,因而这里做一个简单的判断即可。

2.搜索的对象是搜索者本身

这种情况下,在回调之后,会将搜索者自己的用户信息渲染出来,但与普通的搜索结果不同的是,此时用户信息栏不显示“加好友”按钮(避免出现自己加自己的奇怪情况)。

else if(this.searchName == uni.getStorageSync("username_log")){
		this.currentFontIconClass = "icon-user"
		this.currentNickClass = "nickname_searched",
		this.currentIconClass = "icon_searched",
		this.currentImgClass = "image_searched",
		this.currentclass = "friend",
		this.imgSrc = "https:xxxx" + this.searchName
			}

这部分的代码也很有特点:因为搜索对象是搜索者本身这件事可以用简单的与之前我们存在缓存里的发起搜索请求的用户名进行对比实现,因而这里首先做了这样一个判断。

之后的操作就涉及到了动态类名,所以这块在这里不做详细介绍,在第四步会进行讲解。

最后一句是加载用户的头像,这一块是由于阿帕奇服务器会将用户上传的头像转成一个固定格式的url,因此可以用这行代码拼接出头像的url,从而把头像渲染。这一行是原项目的需要,对于本例的主要功能(搜索效果)来说,可以无视。

3.搜索的对象已经是搜索者的好友

这种情况下,在回调之后,会将这个好友的用户信息渲染出来,但与普通的搜索结果不同的是,此时用户信息栏的“加好友”按钮会变成“已添加”状态(避免出现重复添加的奇怪情况)

else if(res.data.message == "1"){
		this.currentFontIconClass = "icon-user-check"
		this.currentNickClass = "nickname_searched",
		this.currentIconClass = "icon_searched",
		this.currentImgClass = "image_searched",
		this.currentclass = "friend",
		this.imgSrc = "https:xxxx" + this.searchName
			}

这部分的代码,首先跟后端协商好,返回的 message 变量的值为1时,代表搜索的对象已经是发起搜索的用户的好友。因而一句简单的判断,即可选中这种情况。

之后仍然是动态类名,仍然不做详细介绍。

4.搜索的对象是正常的结果(除了以上三种情况的结果)

这种情况最为普通,回调后将搜索对象的用户信息渲染即可,用户信息栏会出现正常的“加好友”按钮。

else{
		this.currentFontIconClass = "icon-user-plus1"
		this.currentNickClass = "nickname_searched",
		this.currentIconClass = "icon_searched",
		this.currentImgClass = "image_searched",
		this.currentclass = "friend",
		this.imgSrc = "https:xxxx" + this.searchName
			}

以上四种情况的渲染实现方法在下一个步骤:动态类名 中进行介绍。


4️⃣动态类名

首先简单介绍动态类名:动态类名是相对于静态类名而言的。在前端开发中,一个组件可以拥有class,也即类名。当类名以一个 “xx” 的格式被赋值时,它就是一个静态类名。(可以理解为字符串)

当使用 v-bind: variable 时,代表我们使用了一个动态的表达式来表示类名,这个 “variable” 的值就是我们这个组件的类名。其中 v-bind:可以简写为“:”。

接下来举几个在本例中用到的动态类名的场景:

1.关于用户信息组件:

没有搜索任务时,用户信息组件的类名为默认的不显示类名,但当有搜索结果时,类名要变化为相应的结果的类名:

	.friend_unSearched{
		text-align: center;
		width: 100%;
		height: 110rpx;
	}
	.friend{
		margin-top: 45rpx;
		position: relative;
		background-color: #FFFFFF;
		width: 100%;
		height: 100rpx;
	}

2.关于添加好友按钮、用户头像等小组件:

	.icon_searched{
		height: 100rpx;
		width: 100rpx;
	}
	.icon_unsearched{
		width: 0rpx;
		height: 0rpx;
	}
	.image_unsearched{
		width: 0rpx;
		height: 0rpx;
	}
	.image_searched{
		margin-top: 3rpx;
		line-height: 94rpx;
		margin-left: 35rpx;
		width: 94rpx;
		height: 100rpx;
		border-radius: 50%;
	}
	.icon_searched,.nickname_searched{
		float: left;
	}
	.nickname_searched{
		margin-left: 55rpx;
		line-height: 100rpx;
	}
	.nickname_unsearched{
		line-height: 100rpx;
		margin: 0 auto;
		text-align: center;
	}
	.fonticon_unsearched{
		height: 0rpx;
		width: 0rpx;
	}
	.icon-user-plus1,.icon-user,.icon-user-check{
		line-height: 110rpx;
		position: absolute;
		right: 35rpx;
		font-size: 40rpx;
	}

上面的部分是用到了动态类名的css代码片段,可以和最初文章的第一部分展示的html代码进行对比,得到更加深刻的理解。


5️⃣效果优化

最后做一个简单的小的搜索功能优化:

要实现的效果:搜索结果在搜索框最后一个文字被擦除的瞬间完全消失。

首先,在html部分给input组件添加一个@input事件,这个事件会在input输入框的内容发生改变时被触发,同时会把此时的输入框内容作为事件的参数返回。

而后在JavaScript部分实现这个@input事件:

inputChanged(e){
		if(e.target.value == ""){
				this.searchName = "",
				this.imgSrc = "",
				this.currentFontIconClass = "fonticon_unsearched"
				this.currentclass = "friend_unSearched",
				this.currentIconClass = "icon_unsearched",
				this.currentImgClass = "image_unsearched",
				this.currentNickClass = "nickname_unsearched"
				}
			}

其中inputChange()是给@input事件起的名字,这个名字可以任意起。需要注意的一点是,这里的 消失 仍然是用到了 动态类名 的方法。

最后的最后补充一下,演示gif图上的用户信息栏最右侧的小人是用字体图标实现的,这部分可能单独做一个博客展示。


III.源码

<template>
	<view>
		<view class="header">
			添加好友
		</view>
		<view class="searchInput">
			<input type="text" placeholder="请输入对方的昵称" v-model="friendName" @input="inputChanged"/>
		</view>
		<view class="searchbtn" @click="search">
			搜索            <span class="icon-search"></span>
		</view>
		<view :class = "currentclass">
			<view :class="currentIconClass"><image :class = "currentImgClass" :src="imgSrc" mode="widthFix"></image></view>
			<view :class="currentNickClass">
				<text>{{searchName}}</text>
			</view>
			<span @click="add" :class="currentFontIconClass"></span>
		</view>
	</view>
</template>

<script>
	export default{
		data(){
			return{
				userName:'',
				friendName:'',
				imgSrc:'',
				searchName:'',
				color:'#f27498',
				currentclass:'friend_unSearched',
				currentImgClass:'image_unsearched',
				currentIconClass:'icon_unsearched',
				currentNickClass:'nickname_unsearched',
				currentFontIconClass:"fonticon_unsearched"
			}
		},
		methods:{
			search(){
				this.userName = uni.getStorageSync("username_log"),
				uni.request({
					url:'https:xxxx',
					method:'GET',	
					data:{username : this.userName, friendname : this.friendName},
					header: {
					  'content-type': 'application/x-www-form-urlencoded' //表明后端接收的是(表单)字符串类型,例如'id=1231454&sex=男' 
					 },
					 success: (res) => {
						if(this.friendName == "") return;
						this.searchName = res.data.username;
						if(this.searchName == null){
							this.searchName = "此用户不存在!"
							this.imgSrc = ""		
						}
						else if(this.searchName == uni.getStorageSync("username_log")){
							this.currentFontIconClass = "icon-user"
							this.currentNickClass = "nickname_searched",
							this.currentIconClass = "icon_searched",
							this.currentImgClass = "image_searched",
							this.currentclass = "friend",
							this.imgSrc = "https:xxxx" + this.searchName
						}
						else if(res.data.message == "1"){
							this.currentFontIconClass = "icon-user-check"
							this.currentNickClass = "nickname_searched",
							this.currentIconClass = "icon_searched",
							this.currentImgClass = "image_searched",
							this.currentclass = "friend",
							this.imgSrc = "https:xxxx" + this.searchName
						}
						else{
							this.currentFontIconClass = "icon-user-plus1"
							this.currentNickClass = "nickname_searched",
							this.currentIconClass = "icon_searched",
							this.currentImgClass = "image_searched",
							this.currentclass = "friend",
							this.imgSrc = "https:xxxx" + this.searchName	
						}
			
					 }
				})
				console.log(this.friendName)
			},
			inputChanged(e){
				if(e.target.value == ""){
					this.searchName = "",
					this.imgSrc = "",
					this.currentFontIconClass = "fonticon_unsearched"
					this.currentclass = "friend_unSearched",
					this.currentIconClass = "icon_unsearched",
					this.currentImgClass = "image_unsearched",
					this.currentNickClass = "nickname_unsearched"
				}
			},
			add(){
				this.userName = uni.getStorageSync("username_log");
				if(this.currentFontIconClass == "icon-user-plus1"){
					uni.request({
						url:'https:xxxx',
						method:'GET',	
						data:{username : this.userName, friendname: this.friendName},
						header: {
						  'content-type': 'application/x-www-form-urlencoded' 
						 },
						 success: () => {
						 	uni.showToast({
						 		title: "添加成功"
						 	}),
							this.currentFontIconClass = "icon-user-check"
						 }
					})
				}
				else if(this.currentFontIconClass == "icon-user"){
					uni.showToast({
						title: "不能添加自己哦!",
						icon: "none"
					})
				}
				else if(this.currentFontIconClass == "icon-user-check")
					uni.showToast({
						title: "已有该好友!",
						icon: "none"
				})
			}
		}
	}
</script>

<style>
	page{
		display: flex;
		flex-direction: column;
		background-color: #ededed;
	}
	.header{
		position: relative;
		margin-top: 25rpx;
		font-weight: 600;
		font-size: 40rpx;
		text-align: center;
		margin-bottom: 35rpx;
	}
	.searchInput{
		width: 100%;
	}
	input{
		text-align: center;
		margin: 0 auto;
		border-radius: 10rpx;
		border: 2rpx solid #000000;
		width: 95%;
		height: 70rpx;
	}
	.searchbtn{
		border-radius: 10rpx;
		background-color: #f27498;
		font-size: 33rpx;
		line-height: 65rpx;
		text-align: center;
		margin: 0 auto;
		margin-top: 40rpx;
		width: 35%;
		height: 65rpx;
		color: #FFFFFF;
	}
	.icon-search{
		margin-left: 5rpx;
	}
	.friend_unSearched{
		text-align: center;
		width: 100%;
		height: 110rpx;
	}
	.friend{
		margin-top: 45rpx;
		position: relative;
		background-color: #FFFFFF;
		width: 100%;
		height: 100rpx;
	}
	.icon_searched{
		height: 100rpx;
		width: 100rpx;
	}
	.icon_unsearched{
		width: 0rpx;
		height: 0rpx;
	}
	.image_unsearched{
		width: 0rpx;
		height: 0rpx;
	}
	.image_searched{
		margin-top: 3rpx;
		line-height: 94rpx;
		margin-left: 35rpx;
		width: 94rpx;
		height: 100rpx;
		border-radius: 50%;
	}
	.icon_searched,.nickname_searched{
		float: left;
	}
	.nickname_searched{
		margin-left: 55rpx;
		line-height: 100rpx;
	}
	.nickname_unsearched{
		line-height: 100rpx;
		margin: 0 auto;
		text-align: center;
	}
	.fonticon_unsearched{
		height: 0rpx;
		width: 0rpx;
	}
	.icon-user-plus1,.icon-user,.icon-user-check{
		line-height: 110rpx;
		position: absolute;
		right: 35rpx;
		font-size: 40rpx;
	}
</style>
  • 25
    点赞
  • 142
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
要在uniapp实现搜索功能,可以按照以下步骤进行操作: 1. 在搜索框的输入框中添加一个@input事件,用于监听输入框内容的变化。在这个事件中,可以通过e.target.value获取到输入框的值。 2. 在@input事件中,可以根据输入框的值进行相应的处理。例如,如果输入框的值为空,则可以清空搜索结果,并将相关的样式设置为未搜索状态。 3. 当用户点击搜索按钮或按下回车键时,可以触发一个方法(例如sou()),在这个方法中可以进行搜索操作。 4. 在搜索方法中,可以使用uni.navigateTo()方法跳转到搜索结果页,并将搜索关键字作为参数传递给搜索结果页。 5. 在搜索结果页中,可以通过uniCloud.database().collection().get()方法获取到相应的搜索结果数据,并进行渲染。 6. 根据搜索结果的情况,可以设置相应的样式和显示内容。例如,如果搜索结果是用户自己的信息,则可以隐藏加好友按钮。 通过以上步骤,就可以实现uniapp中的搜索功能。请注意,以上步骤中的代码片段是根据提供的引用内容进行的推测,具体的实现方式可能会有所不同。 #### 引用[.reference_title] - *1* [uni-app实现搜索功能](https://blog.csdn.net/qq_60077855/article/details/125579597)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [uniapp实现搜索功能详细步骤前端开发】](https://blog.csdn.net/qq_52736131/article/details/122292730)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

跳探戈的小龙虾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值