微信小程序的搜索高亮、自定义导航条等踩坑记录
原文地址:https://oomabc.com/articledetail?atclid=7421fe13daad46389791463f51d3395d
前言
我在写这个博客的小程序过程中,遇到了很多的问题。之前断断续续也写过不少JavaScript和css,不过都是半吊子。所以在看了一会小程序demo代码,就开工了。虽然在一天之后就基本完成了大体功能框架,但依旧在细节上碰到了不少问题。本博客会将我遇到的一些问题和自己的解决方案贴在下面,纯粹记录一下。
图片
搜索高亮
不管是电商网站还是博客,亦或者是招聘网站,通常都少不了搜索功能。而搜索通常都会有一个基础应用,那就是关键字高亮,因为输入的关键字可能包含多个词语,而当多个词语命中对应结果时,这几个词语可能不是连续出现,所以这些高亮通常是后端接口通过搜索引擎框架实现。
在HTML中,后端在返回的结果数据中,用标签(例如:<span class="keyword">需要高亮的关键字</span>)将命中的关键字包起来,然后前端通过css样式将这些关键字进行特殊标记。
图片
按照这个思路,依旧是通过后端将命中关键字用小程序的<text class="keyword"></text>标签包起来,前端通过样式对其进行高亮。很遗憾,小程序直接将这段文字连同标签一起展示了,而且网上也没有查到让标签不展示的方法,所以这个思路行不通。
在小程序中,我们可以通过wx:for来实现标签的动态生成,然后根据具体参数来确定text标签是否需要添加高亮class。
后端依旧将高亮的关键字进行特殊标记,我这里使用HHtextHHS和HHtextHHE作为高亮的开始和结束标签,然后通过js进行字符串分割,最终返回的数据结构如下:
[
{content : '重温', type : 0}, //content就是要显示的文本内容,type=0表示不高亮
{content : 'Java', type : 1}, //type=1表示要高亮
{content : '设计模式——', type : 0},
{content : '工厂', type : 1},
{content : '模式', type : 0}
]
实现带高亮标签的字符串转为数组的js方法如下:
//入参非空判断在上层已处理
splitTitle : function(s) {
//保存最终返回的结果
var rslist = [];
//根据高亮开始标签进行字符串分割
var arr1 = s.split('HHtextHHS');
//遍历分割之后的每一个字符串,进行结束标签判断
for (var i in arr1) {
var word1 = arr1[i];
//过滤空字符串
if (word1 && word1.length > 0) {
//如果有结束标签,则进行高亮字符串截取,并设置高亮标志位
var indexEnd = word1.indexOf('HHtextHHE');
if (indexEnd >= 0) {
rslist.push({
content: word1.substring(0, indexEnd),
type: 1
});
//剩余不需要高亮
//注意:这里的处理方式是基于没有标签嵌套的情况,如果有嵌套,这里需要另写逻辑
var wordEnd = word1.substring(indexEnd + 9);
if (wordEnd && wordEnd.length > 0) {
rslist.push({
content: wordEnd,
type: 0
});
}
} else {//没有结束标签,则表示当前字符串不是需要高亮的
rslist.push({
content: word1,
type: 0
});
}
}
}
return rslist;
}
对应在wxml中,循环显示这个数组对象的标签写法如下:
<!-- 这里的splitTitleList就是上面的js方法返回的数组对象 -->
<text class="articleTitle">
<text wx:for="{{splitTitleList}}">
<text class="{{item.type == 1 ? 'keywordHighLight' : ''}}">{{item.content}}</text>
</text>
</text>
高亮样式就是很简单的wxss:
.keywordHighLight{
color : red;
}
搜索框放大镜icon
图片
通常的搜索输入框都会有一个放大镜进行icon标记,既简介又功能清晰。所以,我也想在自己的小程序中也实现这个样式,之前写类似的前端代码很少,所以我打算通过background-image来引入放大镜的图标。 结果很遗憾:
template/topSearch.wxss 中的本地资源图片无法通过 WXSS 获取,可以使用网络图片,或者 base64,或者使用<img>标签。
请参考文档:https://mp.weixin.qq.com/debug/wxadoc/dev/qa.html#%E6%9C%AC%E5%9C%B0%E8%B5%84%E6%BA%90%E6%97%A0%E6%B3%95%E9%80%9A%E8%BF%87-css-%E8%8E%B7%E5%8F%96
39 | margin-left: 15px;
40 |
> 41 | background-image: url('/image/search.pn');
| ^
42 | }
43 |
44 | .searchIconImg{
微信小程序提醒我们,WXSS无法直接引入本地图片,只能使用网络图片或者以Base64格式,或者在WXML中用<img>引入。
所以,我就尝试在WXML中,直接用style的行内样式通过background-image引入图片。嘿嘿,很简单的通过view和input两个标签实现了图标显示,而且微信开发者工具中可以正常显示并调试(不过,input标签有个bug,会显示两个图标)。最终经过一番折腾,终于进入真机调试环节,结果依旧是很遗憾,在手机上无法显示这些图片,而且最终审核发布之后,手机端还是无法显示。
这下终于明白当初那些提示的含义了,接下来我就使用image试试。结果确实是可以的,不过要进行样式微调。大概的WXML和样式如下:
<view class="topSearchInputOuter">
<img src="/image/search.png" class="searchIconImg">
<input class="topSearchInput" value="{{queryWord}}" focus="true" auto-focus="true" name="topSearchInput" placeholder=" 热门关键字" bindconfirm="searchArticles">
</view>
.topSearchInput{
font-size: 13px;
border: 0px solid #EFEFEF;
width: 220px;
line-height: 33px;
height : 33px;
color : gray;
padding-left : 5px;
}
.topSearchInputOuter{
background-color: #EFEFEF;
border-radius : 15px;
padding-left : 8px;
width : 240px;
line-height : 33px;
display: flex;
}
.searchIconImg{
width : 15px;
height : 15px;
vertical-align: middle;
justify-content: center;
margin-top:9px;
}
自定义状态栏
在实现状态栏搜索功能的时候,还遇到的另一个问题就是,微信默认状态栏是不允许修改的。如果需要自定义状态栏,需要在app.json文件的window参数中,设置navigationStyle为custom。
"window": {
"backgroundTextStyle": "light",
"navigationBarBackgroundColor": "#fff",
"navigationBarTitleText": "欢迎访问OoM技术博客",
"navigationBarTextStyle": "black",
"backgroundColor": "#f1e8e8",
"navigationStyle": "custom" //这里设置状态栏(导航栏)样式为自定义
}
这样一来,顶部除了微信的胶囊按钮之外,一片清爽。
不过这样一来,我们就需要自己实现顶部状态栏+导航条的设备自适应功能了。由于我也不是专业的前端,因此网上搜寻了针对全面屏和非全面屏两种设备的自适应方案。
通过判断设备是否是全面屏(iPhone X),进行状态栏高度和导航栏高度动态调整。js代码如下:
var vm = this;
wx.getSystemInfo({ //wx提供的获得设备系统信息的方法
success: function (res) {
let totalTopHeight = 68
if (res.model.indexOf('iPhone X') !== -1) {
totalTopHeight = 88
} else if (res.model.indexOf('iPhone') !== -1) {
totalTopHeight = 64
}
var statusBar = {};
//设置状态栏相关参数
statusBar.statusBarHeight = res.statusBarHeight;
statusBar.titleBarHeight = totalTopHeight - res.statusBarHeight;
statusBar.queryWord = vm.globalData.searchDefaultPlacehoder;
//设定全局参数,其他页面通过 const app = getApp();app.globalData.statusBar 获得
vm.globalData.statusBar = statusBar;
},
fail: function() {
vm.globalData.statusBar = {
statusBarHeight : 0,
titleBarHeight : 0
};
}
});
对应的在WXML中的使用,下面给出模板化应用的例子:
<template name="topNavTmp">
<view class="topNavView" style="padding-top: 0px; height :0px">
<view class="header" style="">
<!-- 状态栏 --->
<view class="status-bar" style="height:{{barStatus.statusBarHeight}}px"></view>
<!-- 导航栏 --->
<view class="title-bar" style="height:{{barStatus.titleBarHeight}}px; line-height : {{barStatus.titleBarHeight}}px;">
<!-- 这里是顶部的返回和home按钮 -->
<view class="topNavLeft">
<view class="topNav-one"><img bindtap="clickAndBack" class="topNavImg" src="/image/back-1.png"></view>
<view class="topNav-sep"></view>
<view class="topNav-two"><img bindtap="clickAndHome" class="topNavImg" src="/image/home-1.png"></view>
</view>
<!-- 标题 -->
{{barStatus.topNavTitle}}
<view class="tablet"></view>
</view>
</view>
</view>
<!-- 将topNavView的fixed样式,用同样高度顶下去,不然后面的样式会浮上来 -->
<view style="height : {{barStatus.statusBarHeight+barStatus.titleBarHeight}}px; text-align : center;"></view>
</template>
在引用的页面使用:
<!-- 在其它页面引入模板的使用 -->
<import src="/template/topNav.wxml">
<!-- 这里使用模板,传入参数 -->
<template is="topNavTmp" data="{{barStatus}}"></template>
相关推荐
本文实例为大家分享了vue elementUI表格关键字筛选高亮的具体代码,供大家参考,具体内容如下。<el-input type="search" v-model="search" style="w