小程序实时监听搜索数据并将关键字高亮显示

在这里插入图片描述

<template>
  <view>
    <view class="box">
     <view class="search">
     	<image src="https://ebk-picture.oss-cn-hangzhou.aliyuncs.com/mini-wx/images/homeIndex/search.png" mode=""></image>
     	<view class="inputCon">
     		<input type="search"
     		 placeholder="搜索地铁站" 
     			v-model="searchValue"
     			 confirm-type="search"
     			@confirm="search()">
     	</view>
     </view>
	 <view class="list-box" v-if="showList">
	   <view class="item active" v-for="(item, index) in stationList" :key="index" @click="onSelectStation(item)" v-html="item.subway_name">
	   </view>
	 </view>
     <view v-if="isContent">
     	<view style="margin-top: 20rpx;" class="pickers">
     			<picker
     			  :value="multiIndex"
     			  @change="onChange"
     			  @columnchange="onColumnChange"
     			  mode="multiSelector"
     			  :range="multiArray"
     			  range-key="label"
     			>
     			<text>定位</text>
     				<view style="max-width:max-content;
     				height: 46rpx;
     				border-radius: 12rpx 12rpx 12rpx 12rpx;
     				border: 2rpx solid rgba(0,139,124,0.1);
     				padding: 10rpx;">
     						<image src="https://ebk-picture.oss-cn-hangzhou.aliyuncs.com/ebk-wap/img-202304231132081261-Group%2034001.png" mode=""></image>
     						<text style="font-size: 28rpx;
     						font-weight: 400;
     						color: #008B7C;
     						line-height: 33rpx;">{{station}}</text>
     							
     					  </view>
     			  <!-- <view class="picker-value">{{ line }} - {{ station }}</view> -->
     			</picker>
     	</view>
     	<text class="search_txt">历史记录:</text>
     	<view class="search_history">
     	  <view v-for="(item, index) in searchHistory" :key="index" @tap="onSearchHistoryTap(item)" class="search_item" @click="toIndex()">
     	    <text>{{ item }}</text>
     	  </view>
     	</view>
     </view>
      
    </view>
   
  </view>
</template>

<script>
export default {
data() {
  return {
    sub: "",
    multiArray: [],
    multiIndex: [0, 0],
    line: "", 
    station: "",
    lines: [], 
    stations: [] ,
    City:[],
    searchValue:'',
    searchHistory:[],
    stationList: [], // 下拉列表数据
    showList: false ,// 判断下拉列表是否显示
	timer: null ,// 定时器开关
	isContent:true,//出现下拉列表时隐藏页面内容
	zhanshi:""
  };
},
 watch: {
    searchValue: function(val) {
      if (this.timer) clearTimeout(this.timer); // 清除上个定时器
      this.timer = setTimeout(() => {
        if (val) {
          this.search(); // 发起搜索请求
          this.showList = true; // 显示下拉菜单
		  this.isContent = false
        } else {
			this.stationList = []//清空上一次的下拉展示记录
          this.showList = false; // 隐藏下拉菜单
		  this.isContent = true
        }
      }, 300); // 设置定时器,延迟 300 毫秒后开始搜索
    }
  },
 // 在组件挂载后获取 localcityNm 缓存值,并请求地铁线路列表
 mounted() {
   this.sub = uni.getStorageSync("localcityNm");
   this.getSubwayLinesList();
 },
 
 // 在页面加载时获取历史搜索记录和定位标志,将定位标志设为 false
 onLoad(){
   this.searchHistory = uni.getStorageSync("searchHistory")
   console.log(this.searchHistory+'11')
   const isDinwei = uni.getStorageSync('isDinwei')
   uni.setStorageSync('isDinwei',false)
 },
 
 methods: {
   // 跳转到首页
   toIndex(){
     uni.navigateBack(1)
   },
   // 点击历史搜索记录项触发的事件
   onSearchHistoryTap(item) {
	   console.log(item,'我是点击的某一项')
     // 将点击的历史搜索记录项值赋给搜索框
     this.searchValue = item;
     // 执行搜索方法进行搜索,并将定位标志设置为 true
     this.onSelectStation();
	 uni.setStorageSync('localcityNm', this.searchValue); 
     const isDinwei = uni.getStorageSync('isDinwei')
     uni.setStorageSync('isDinwei',true)
   },
// 选择了某个地铁站时,更新当前页面显示的地铁站名称和存储的相关信息
onSelectStation(station) {
  this.station = station.subway_name; // 更新当前显示的地铁站名称
  uni.setStorageSync('localcityNm', station.subway_name); // 存储所选地铁站名称
  const currentStationObj = JSON.parse(JSON.stringify(station));
  const { subway_latitude, subway_longitude } = currentStationObj;
  const newCityData = { lat: subway_latitude, lng: subway_longitude };
  uni.setStorageSync('City', newCityData); // 存储所选地铁站的经纬度信息

  const history = uni.getStorageSync('searchHistory') || [];
   const newStationName = station.subway_name.replace(/<[^>]*>/g, ''); // 去除所有 HTML 标签
  if (!history.includes(newStationName)) {//判断搜索历史记录中是否有值,无值执行以下代码
	  this.searchHistory = history;
	  	this.searchHistory.unshift(newStationName);//在历史记录数组中首位添加搜索内容
	  	  if (this.searchHistory.length > 10) { // 保留10个值
	  		this.searchHistory.pop()//当大于十个值时删掉数组末尾的值
	  	  }
	uni.setStorageSync('searchHistory', this.searchHistory); // 存储搜索历史记录
    const isDinwei = uni.getStorageSync('isDinwei');
    uni.setStorageSync('isDinwei', true); // 设置已定位标志为true,避免再次进行定位操作
    // history.push(newStationName);
	uni.setStorageSync('localcityNm', newStationName);
	this.searchValue = ''
	this.toIndex(); // 跳转到首页
    this.searchHistory = history;
		 uni.setStorageSync('searchHistory', this.searchHistory); // 存储搜索历史记录
  }else{
	  //有搜索记录,删除之前的旧记录,将新搜索值重新push到数组首位
	  console.log('11111111111111111111111')
	  this.searchHistory = history;
	  let i = this.searchHistory.indexOf(newStationName);
	  this.searchHistory.splice(i, 1);
	  this.searchHistory.unshift(newStationName);
	  if (this.searchHistory.length > 10) { // 保留10个值
	  	this.searchHistory.pop()
	  }
	   uni.setStorageSync('searchHistory', this.searchHistory); // 存储搜索历史记录
	  // 请勿重复搜索
	  this.toIndex(); // 跳转到首页
	 const isDinwei = uni.getStorageSync('isDinwei');
	 uni.setStorageSync('isDinwei', true); // 设置已定位标志为true,避免再次进行定位操作
	 uni.setStorageSync('localcityNm', newStationName);
	  uni.setStorageSync('isDinwei', true); // 设置已定位标志为true,避免再次进行定位操作
	  this.searchValue = ''
	  this.isContent = true
	  this.showList = false; // 关闭下拉列表
  }
},
async search() {
  try {
    const res = await this.$request.post("subway/getSubwayStation", {
      city_id: uni.getStorageSync("localcityId"),
      subway_name: this.searchValue.trim()
    });
    const data = res.data;
	// console.log(data,'数据格式')
    const station = data[0];
    if (station) {
		this.showList = true;
		 this.isContent = false
		
		//一定要是大于等于,不然匹配规则就有问题,匹配到单个不会显示
      if (data.length >= 1) {
        // 如果匹配到多个地铁站,则将所有信息保存到stationList中,并显示下拉列表
        this.stationList = data;
		      this.stationList = data.map(item => {
		               const reg = new RegExp(this.searchValue, 'g'); // 使用正则表达式进行全局匹配
		               const newName = item.subway_name.replace(reg, `<span style="color:#008B7C">${this.searchValue}</span>`); // 将匹配到的部分用<span>标签包裹,并修改文字颜色
		               return { ...item, subway_name: newName };
		             });
					 console.log(this.stationList,'我是处理好的数据')
       
      }
	  else {
        // 如果只匹配到一个地铁站,则直接定位到该地铁站
        this.station = station.subway_name;
        uni.setStorageSync('localcityNm', station.subway_name);
        const currentStationObj = JSON.parse(JSON.stringify(station));
        const { subway_latitude, subway_longitude } = currentStationObj;
        const newCityData = { lat: subway_latitude, lng: subway_longitude };
        uni.setStorageSync('City', newCityData);
        const history = uni.getStorageSync('searchHistory') || [];
		 const newStationName = station.subway_name.replace(/<[^>]*>/g, '');
	
   //      if (!history.includes(newStationName)) {
   //        const isDinwei = uni.getStorageSync('isDinwei')
   //        uni.setStorageSync('isDinwei',true)
		 //  this.toIndex()
   //        history.push(newStationName);
		 
		 //  uni.setStorageSync('localcityNm', newStationName);
   //        this.searchHistory=history;
		 
   //        uni.setStorageSync('searchHistory', this.searchHistory);
   //      }
      }
    } else {
		this.showList = false;
		 this.isContent = true
      uni.showToast({
        title: '未找到该地铁站点',
        icon: 'none'
      });
    }
  } catch (error) {
    console.log(error);
  }
},
 
   // 请求地铁线路列表
   async getSubwayLinesList() {
     try {
       const res = await this.$request.post("subway/getSubwayLinesList", {
         city_id: uni.getStorageSync("localcityId")
       });
       const data = res.data;
       const lines = data;
       // 格式化地铁线路名称列表数据,并存储到当前组件实例的 lines 属性中
       this.lines = lines.map(item => ({
         label: item.lines,
         value: item.id
       }));
       this.line = lines[0].lines; // 初始化当前选中的地铁线路名
       this.getSubwayStations(lines[0].id); // 获取第一个地铁线路的站点列表
     } catch (error) {
       console.log(error);
     }
   },
  // 请求指定地铁线路的站点列表
  async getSubwayStations(lineId) {
    try {
      // 调用后端API获取数据
      const res = await this.$request.post("subway/getSubwayStationList", {
        lines_id: lineId
      });
      const data = res.data;
      // 将数据存储到stations变量中
      const stations = data;
      // 将每个站点的名称和id转换为label和value,存储到this.stations数组中
      this.stations = stations.map(item => ({
        label: item.subway_name,
        value: item.id
      })); // 存储地铁站点名称列表到 data 中
      // 将data中的所有数据存储到City变量中
      const City = data
      this.City = City
      // 如果用户没有选择站点,则默认选择距离用户最近的站点
      if (!this.station) {
        // 如果用户还没有选择站点,则将其设为本地存储中的城市名localcityNm
  	  this.station = uni.getStorageSync('localcityNm')
      }
      // 设置选中的站点为当前地铁线路的第一个站点
      this.multiIndex = [this.multiIndex[0], 0];
      // 更新多列选择器的数据源
      this.multiArray = [this.lines, this.stations];
    } catch (error) {
      console.log(error);
    }
  },
  
  // 线路选择器值改变事件
  onChange(e) {
    const that = this;
    // 获取picker选择器中的索引值
    const multiIndex = e.detail.value;
    // 获取当前选中的地铁线路的名称
    const lineName = that.lines[multiIndex[0]].label;
    // 获取当前选中的地铁站点的名称
    const stationName = that.stations[multiIndex[1]].label;
    // 将当前选中的地铁站点的名称存储到本地存储中,用于下次默认选择
    uni.setStorageSync('localcityNm', stationName);
    // 根据当前选中的地铁站点名称获取该站点的经纬度信息,并存储到localStorage中
    const currentStation = that.City.find(item => item.subway_name === stationName);
    if (currentStation) {
      const currentStationObj = JSON.parse(JSON.stringify(currentStation));
      const { subway_latitude, subway_longitude } = currentStationObj;
      const newObj ={lat:subway_latitude, lng:subway_longitude}
      uni.setStorageSync('City', newObj);
    }
    // 更新选中的地铁线路、站点名称
    that.line = lineName;
    that.station = stationName;
    // 重新获取并更新站点列表数据
    that.getSubwayStations(
      that.lines.find(item => item.label === lineName).value
    );
    // 更新多列选择器的数据源和选中的索引值
    that.multiArray = [that.lines, that.stations];
    that.multiIndex = multiIndex;
    // 跳转到首页
    this.toIndex()
    // 设置isDinwei为true,表示已经定位
    const isDinwei = uni.getStorageSync('isDinwei')
    uni.setStorageSync('isDinwei',true)
  },
  
  // 列变化事件
  onColumnChange(e) {
    let that = this
    // 获取列和行的索引值
    const columnIndex = e.detail.column;
    const rowIndex = e.detail.value;
  
    // 如果列变化的是地铁线路列,则重新获取站点列表并更新右侧 picker 列表的数据源
    if (columnIndex === 0) {
      const lineId = that.lines[rowIndex].value;
      that.getSubwayStations(lineId);
    }
  }

}
};
</script>


<style lang="less" scoped>
	.box{
		padding-left:24rpx ;
		padding-right: 20rpx;
		.search_history{
			width: 100%;
			display: flex;
			flex-wrap: wrap;
			.search_item{
				width: max-content;
				height: 56rpx;
				border-radius: 12rpx 12rpx 12rpx 12rpx;
				opacity: 1;
				border: 2rpx solid rgba(0,0,0,0.1);
				margin-right:20rpx ;
				padding-left: 8rpx;
				padding-right: 8rpx;
				margin-bottom: 20rpx;
				text{
					font-size: 28rpx;
					font-weight: 400;
					line-height: 56rpx;
					text-align: center;
					color: #666666;
				}
			}
		}
		.picker {
			  font-size: 16px;
			  color: #000;
			  line-height: 40px;
			  text-align: center;
			  border: 1px solid #ccc;
			  border-radius: 4px;
			  padding: 0 10px;
			  margin-top: 20px;
			}
		.pickers{
			text{
				font-size: 24rpx;
				font-weight: 400;
				color: #666666;
				line-height: 68rpx;
			}
			image{
				width: 24rpx;
								height: 28rpx;
								vertical-align: middle;margin-right: 6rpx;
			}
		}
		.search_txt{
			font-size: 24rpx;
			font-weight: 400;
			color: #666666;
			line-height: 98rpx;
		}
		.search {
					/* // flex: 1; */
					height: 64rpx;
					position: relative;
					background-color: #FFFFFF;
					// bottom: -0rpx;
					border-radius: 300rpx;
					image {
						position: absolute;
						width: 22rpx;
						height: 18rpx;
						top: 22rpx;
						left: 22rpx;
						z-index: 999;
					}
		
					input {
						width: 90%;
						height: 62rpx;
						position: absolute;
						left: 0;
						top: 0;
						margin: 0 auto;
						// border: none;
						background-color: #FFFFFF;
						border: 1rpx solid rgba(0,0,0,0.2);
						border-radius: 300rpx;
						padding: 0;
						margin: 0;
						padding-left: 60rpx;
						color: #666666;
						font-size: 24rpx;
					}
				}
				.dinwei{
					font-size: 24rpx;
					font-weight: 400;
					color: #666666;
					line-height: 28rpx;
				}
	}
	.list-box{
		padding: 22rpx;
		.item{
			width: 100%;
			padding-bottom: 20rpx;
			padding-top: 20rpx;
			border-bottom: 1rpx solid rgba(0,0,0,0.02);
			color: #666666 ;
			font-size: 30rpx;
		}
		.item:hover .active{
			color: #000;
		}
	}
</style>
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
小程序可以通过监听数据变化的方式实时更新界面。具体的实现方式可以通过以下步骤来完成: 1. 在小程序中,可以使用 `setData` 方法来修改数据。当数据发生变化时,可以调用 `setData` 方法更新数据的值。 2. 在需要监听数据变化的地方,可以使用 `watch` 方法来监听数据的变化。首先,需要使用 `this.data` 来获取当前数据的值,然后使用 `this.setData` 方法来更新数据。 例如,假设我们要监听某个数据 `count` 的变化,可以按照以下步骤来实现: 1. 在小程序的 Page 或 Component 中定义 `data` 对象,并初始化 `count` 的初始值: ```javascript Page({ data: { count: 0 }, // ... }) ``` 2. 在需要监听数据变化的地方,使用 `watch` 方法来监听 `count` 的变化。在 `onLoad` 或其他合适的生命周期函数中调用 `watch` 方法: ```javascript Page({ data: { count: 0 }, watch: { count(newValue, oldValue) { // 数据变化时的逻辑处理 console.log('count 变化了', newValue, oldValue); } }, onLoad() { this.watch(); }, // ... }) ``` 在上述代码中,我们定义了一个 `watch` 对象,其中的 `count` 方法会在 `count` 的值发生变化时被调用。在 `count` 方法中,可以对数据的变化进行逻辑处理,比如更新界面或执行其他操作。 需要注意的是,上述代码中的 `watch` 方法是自定义的,需要在合适的地方调用。你也可以使用一些第三方库来实现类似的功能,比如 `miniprogram-computed` 或 `wxapp-computed`。这些库提供了更便捷的方式来监听数据的变化。 希望以上信息对你有帮助!如有更多问题,请继续提问。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

码上流星&洒下星辰

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

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

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

打赏作者

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

抵扣说明:

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

余额充值