** 技术栈 : ** vue + vuex
架构选型,因为有首页和搜索页面用到同一搜索框样式,所以考虑将搜索框单独封装为一个组件,搜索页面(搜索框组件,搜索结果,搜索历史)
-
遇到的问题
scene: a. 搜索占位符字体样式调整 ,
b. focus光标在
ios
和Android
中大小显示样式不统一key : 搜索框光标的大小和位置在
IOS
和Android
中的显示并不一样,最好是设padding值,让高度全部填充,实现居中,占位符的样式需要兼容多个浏览器.search-box { border:none; box-sizing: border-box; font-size: 14/@r; color: #353535; width: 100%; height: 36/@r; padding: 8/@r 0 ; line-height: 20/@r; &::-webkit-input-placeholder{/*Webkit browsers*/ height: 20/@r; line-height: 20/@r; color: @gray-search; font-size:14/@r; } &:-moz-placeholder{/*Mozilla Firefox 4 to 8*/ } &::moz-placeholder{/*Mozilla Firefox 19+*/ } &::-o-placeholder{ } &:-ms-input-placeholder{/*Internet Explorer 10+*/ } }
-
遇到的问题
scene: 产品需求,如何自动获取焦点(进入页面获取焦点),xx宝页面搜索深深打动了产品,强烈要求实现
key : 这里分两种情况,
- 如果是在同一个项目中 , 可以实现点击搜索框跳转到搜索页,自动获取焦点并打开键盘。具体的方法是,将
search
组件单独分装,首页使用其样式,点击后跳转到搜索页,当搜索页mounted
时再次触发搜索页中的search
组件中的focus
方法。类似在首页用户点击search
框,跳转到新的页面,感觉没有再触发serch
组件,实际点击既是触发当前的serch
框事件。从而不需要点击两次搜索。 - 如果不在同一个项目,是其他页面通过
url
点击跳转到搜索页,则无法触发键盘事件,类似autoplay
,autoFocus
无法生效,只能调取原生方法获取键盘打开事件,或者使用第三方封装的键盘,但会导致其他问题 ,详见场景 6 , 谨慎使用 。
// search 组件中的方法 <input class="search-box" v-model.trim ="query" type="search" :placeholder="placeholder" @compositionstart="handleComposition" @compositionupdate="handleComposition" @compositionend="handleComposition" @blur="handleBlur" @focus="handleFocus" @input="handleInput(query)" @change="handleChange" autocomplete="off" required ref= "searchContainer"> // methods 中的方法 getInput(){ return this.$refs.searchContainer }, focus(){ if(this.getInput()){ this.getInput().focus(); } }, handleFocus(e) { this.$emit('focus',e) },
// 搜索页面 <Search ref="searchBox" @initPageNoFun="initPageSize" ></Search> // 搜索历史 mounted() { this.$refs.searchBox.focus() },
// 首页点击入口 <div class="search-container" @click="jump('#/searchBox')"> <Search></Search> </div>
- 如果是在同一个项目中 , 可以实现点击搜索框跳转到搜索页,自动获取焦点并打开键盘。具体的方法是,将
-
遇到的问题
scene: 当进入页面弹出键盘,输入搜索内容,如何实现键盘显示search(搜索)字样,而不是换行
key : 说来不难,可以尝试,改变input框的属性 ,当type为search时键盘就会显示搜索,且有对应的自带清除按钮样式 , 当type = text时键盘显示换行,且无清除按钮
<input class="search-box" v-model.trim ="query" type="search" :placeholder="placeholder" @focus="handleFocus" required ref= "searchContainer">
-
遇到的问题
scene: 产品觉得自带按钮样式太丑,如何去除系统自带的清除按钮样式
key : 此类答案网上还是蛮多,自己重定义一个清除按钮,添加对应的样式和交互逻辑就行
/* 当input 为 type=search 时的样式兼容问题 */ input::-ms-clear { width : 0; height: 0; } input[type="search"]{ -webkit-appearance:none; } input[type=search] { -webkit-appearance: textfield; -webkit-box-sizing: content-box; font-family: inherit; font-size: 100%; } input::-webkit-search-decoration, input::-webkit-search-cancel-button { display: none; }
-
遇到的问题
scene: 产品需要无感交互,即在搜索框中使用汉字输入法输入,当选中提示文字,自动搜索
key : 这种无感交互应用还是比较广泛,里面涉及到三个事件
compositionstart
compositionupdate
compositionend
在其中我们用的是compositionend
,即是选中提示选择的文字时,其他的触发时机都是干扰项需要将其排除,但也引入了另一个问题,IOS
和Android
的事件触发机制并不一样,会发现在 Android 中compositionend
事件无法触发,但IOS
好好的,所以这里Android
要实现无感交互,需要依赖input
事件,且为了防止多次触发,需要设置截流,符合条件再触发<input class="search-box" v-model.trim ="query" type="search" :placeholder="placeholder" @compositionstart="handleComposition" @compositionupdate="handleComposition" @compositionend="handleComposition" @blur="handleBlur" @focus="handleFocus" @input="handleInput(query)" @change="handleChange" autocomplete="off" required ref= "searchContainer"> // methods 中 handleComposition(e){ if(e.type === 'compositionstart'){ this.isOnComposition = true } if(e.type === 'compositionend'){ this.isOnComposition = false this.handleChange(e.target.value) this.handleInput(e.target.value) } }, handleInput(queryInfo){ let that = this /** is andriod can't triger composition event */ if(navigator.userAgent.match(/Android/i)){ that.isOnComposition = false } if(this.isOnComposition) return ; if(queryInfo){ that.search(queryInfo) }else { that.clearSearch() } },
-
遇到的问题
scene: 类似
IOS
中安装第三方输入法键盘 , 无感交互失效。key : 排查发现第三方键盘无法触发
composition
事件 ,这里有两个思路:- 使用change事件实现无感交互,尝试了一下,可以实现,但会导致接口请求类似多次查询,及二次发送请求问题。多次查询可以用方法排除,但首次进入无法触发,且无法使用v-model绑定,实时传值需要进行判断是否更新,感觉将特殊情况下的问题变得复杂化了。如有大神有实现方案欢迎共享
- 沟通后调整了需求,保证接口,在安装第三方键盘时实现点击搜索功能,搜寻了一大圈,之后参考了几种的input封装的组件,选择用form表单去触发实现搜索功能,这里的action必须存在,可以置空,搜索功能实现。具体如下:
scene: 点击后页面有时会出错,搜索结果被置空,像是页面出bug的感觉,但只有首次会出现,当有值时不会出现
key :
- 用隐藏的input,结果事件无法触发,果断排除,
- 而后有方法说监听键盘的事件获取其
keyCode
,感觉太过麻烦, - 后调试发现是触发表单默认事件,在submit上加阻止默认行为后,解决
此类有两种选择,只能去沟通需求
<form action="" ref="search-form" @submit.prevent="search(query)"> <input class="search-box" v-model.trim ="query" type="search" :placeholder="placeholder" @compositionstart="handleComposition" @compositionupdate="handleComposition" @compositionend="handleComposition" @blur="handleBlur" @focus="handleFocus" @input="handleInput(query)" @change="handleChange" autocomplete="off" required ref= "searchContainer"> <!-- <input type="text" style="display:none;"/> --> </form>
-
遇到的问题
scene: 上拉加载更多
key: 加载更多的方法很多,因为使用了vuex,发送请求后会将请求到的数据合并,所以用了这种简易的上拉刷新方法,利用vue的scroll事件实现
<div class="company-data" v-if="searchFinish===1" @scroll="scroll"> <div>
// scroll方法
scroll(e){
let that = this
//当滚动到底部为1时触发
if(e.srcElement.scrollTop+e.srcElement.offsetHeight>e.srcElement.scrollHeight-1) {
let queryInfo = null
if(this.$children && this.$children[0] && this.$children[0].query){
queryInfo = this.$children[0].query
setTimeout(function(){
that.search(queryInfo)
},100)
}
}
}
小结:而后遇到的问题,类似搜索历史去重后取前四个,请求截流防抖,都是些常见的问题,这里也不一一列举,总结下来,搜索还是有不少注意点,希望以上总结,可以给各位网友一点思路。