首页 > 应用开发 > IT综合 > 教你如何实现直播源代码的搜索功能
一、需求描述
直播源代码实现一个搜索框:
1、输入关键字,按键抬起后可以实现查询功能;
2、下拉列表展示搜索结果,搜索结果中关键字要用特殊颜色突出显示,默认选中搜索结果的第一项;
3、可以按上下键切换选中项,按回车输出选中项;
4、单击组件之外的地方可以收起下拉列表;
二、分析
直播源代码用到的插件 pinyin-match:
支持拼音全拼、简拼和汉字模糊匹配。
调用match方法,匹配成功返回数组([匹配到第一个字符的下标,匹配到最后一个字符的下标]),失败返回false。
三、代码实现
<template> <div @click.stop> <div :class="{'is-focus':isFocus}"> <!-- 搜索输入框 --> <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" autofocus v-model="value" ref='searchInput' spellcheck="false" placeholder="搜索..." @click="changeInput" @keyup="clickSearch" @keydown.down.prevent="navigateOptions('next')" @keydown.up.prevent="navigateOptions('prev')"> <!-- 搜索放大镜图标 --> <div> <i v-show="value" @click="clearSearchValue"></i> <i v-show="!value" @click="clickSearch"></i> </div> </div> <!-- 搜索下拉列表 --> <div> <div ref="ul"> <ul v-for="item in result"> <li :class="{'is-selected': item.isSelected}" @click="clickResultItem(item)"> <img src="../../images/avatar.png"> <div> <span>{{item.keyword[0]}}<span>{{item.keyword[1]}}</span>{{item.keyword[2]}}</span> </div> </li> </ul> <!-- 查询结果为空时候 --> <div v-if="value && result.length == 0"> 没有结果 </div> </div> </div> </div> </template> <script> const PinyinMatch = require('pinyin-match'); export default { name: 'SearchInput', data () { return { isFocus: false,//搜索框是否获取了焦点 value: '',//输入的搜索关键字 result : [],//全部搜索结果 curIndex: 0,//选中的搜索结果的下标 selectItem: {},//选中的搜索结果 userList: [ {name:'安其拉',id:'a1'}, {name:'安琪',id:'a2'}, {name:'陈仙仙', id:'c1' }, {name:'成小龙', id:'c2' }, {name:'程野', id:'c3' }, {name:'丁小明', id:'d1' }, {name:'丁小龙', id:'d2' }, {name:'丁小野', id:'d3' }, {name:'冯小明', id:'f1' }, {name:'冯小龙', id:'f2' }, {name:'冯小野', id:'f3' }, {name:'高小明', id:'g1' }, {name:'高小龙', id:'g2' }, {name:'高小野', id:'g3' }, {name:'高小阳', id:'g4' }, {name:'郭小名', id:'g5' }, {name:'黄小明', id:'h1' }, {name:'黄小龙', id:'h2' }, {name:'黄小野', id:'h3' }, {name:'郝小阳', id:'h4' }, {name:'郝小名', id:'h5' }, {name:'李小明',id:'l1'}, {name:'李小龙',id:'l2'}, {name:'李小野',id:'l3'}, {name:'李小阳',id:'l4'}, {name:'李小一',id:'l5'}, {name:'李小二',id:'l6'}, {name:'李小三',id:'l7'}, {name:'李小四',id:'l8'}, {name:'李小五',id:'l9'}, ] } }, mounted () { let that = this; document.body.addEventListener('click', () => {//单击组件之外时收起下拉列表 that.isFocus = false; that.value = ""; }, false); }, methods: { changeInput() {//单击搜索框时获取焦点 this.isFocus = true; }, clearSearchValue () {//清空输入的查询条件 if (this.value) { this.value = "";//搜索关键字 this.result = [];//全部搜索结果 this.curIndex = 0;//选中的搜索结果的下标 this.selectItem = {};//选中的搜索结果 this.$refs.searchInput.focus();//输入查询条件清空后获取焦点 } }, clickSearch () {//查询 if (event.code == "ArrowDown" || event.code == "ArrowUp") {//上下键 return; } if (event.code == "Enter" && this.selectItem) { this.clickResultItem(this.selectItem);//有搜索结果时按下enter直接选中第一项 return; } this.result = [];//全部搜索结果 this.curIndex = 0;//选中的搜索结果的下标 this.selectItem = {};//选中的搜索结果 if (this.value.trim()) { for (let i = 0; i < this.userList.length; i++) {//根据所有人员名字匹配 let name = this.userList[i].name; let search = PinyinMatch.match(name, this.value); if (search && search.length > 0) { this.userList[i].keyword = this.getKeyWord(name, search); this.userList[i].isSelected = false; this.result.push(this.userList[i]); } } if (this.result && this.result[0]) { this.result[0].isSelected = true; this.curIndex = 0;//选中的搜索结果的下标 this.selectItem = this.result[0];//选中的搜索结果 } } else { this.$refs.searchInput.focus();//没有输入查询条件焦点不应该失去 } }, getKeyWord (name, search) {//关键字 let keyword = []; keyword[0] = name.substring(0, search[0]); if (search[0] == search[1]) { keyword[1] = name.charAt(search[0]);//匹配到的作为关键字 keyword[2] = name.substring(search[0] + 1); } else { keyword[1] = name.substring(search[0], search[1] + 1);//匹配到的作为关键字 keyword[2] = name.substring(search[1] + 1); } return keyword; }, clickResultItem (data) {//单击下拉列表中的选项 alert('您选择了' + data.name); }, navigateOptions (direction) { //搜索结果上下键选择 let resultLength = this.result.length; if (resultLength == 0 || resultLength == 1 ) { return; } let lastIndex = this.curIndex; if (direction === 'next') {//向下 this.curIndex++; if (this.curIndex === resultLength) { this.curIndex = 0; } } if (direction === 'prev') {//向上 this.curIndex--; if (this.curIndex < 0) { this.curIndex = resultLength - 1; } } if (lastIndex < resultLength) { this.result[lastIndex].isSelected = false; } if (-1 < this.curIndex < resultLength) { this.selectItem = this.result[this.curIndex]; this.selectItem.isSelected = true; // this.result[this.curIndex].isSelected = true; this.$set(this.result,this.curIndex,this.selectItem) } this.resetScrollTop(); }, resetScrollTop () { //设置滚动条的位置 let maxShowCount = this.$refs.ul.clientHeight / 50; let diff = this.curIndex - maxShowCount; diff += 4; this.$refs.ul.scrollTop = diff * (50) + 60; }, } } </script> <style src="./index.scss"></style>
index.scss
.search-wrapper { background-color: rgb(235, 148, 148); height: 580px; width:325px; overflow: hidden; border-radius: 3px; font-family: 'Microsoft YaHei'; box-sizing: border-box; padding: 10px; .search-input{ position: relative; input { width: 100%; height: 35px; box-sizing: border-box; border: 0; border-radius: 3px; margin: 0; padding: 0px 40px 0px 10px; outline: 0; font-size: 14px; color: #E5EAEE; // background-color: #209df7; background-color: #fff; } input::-webkit-input-placeholder { color: #E5EAEE; } .search-icons { position: absolute; top: 7px; right: 10px; color: #209df7; font-size: 17px; } } .is-focus { overflow: visible !important; input { color: #222 !important; // border: 1px solid #fff !important; // background-color: #fff !important; box-shadow: inset 0 1px 3px rgba(0, 0, 0, .2), 0 1px 15px hsla(0, 0%, 100%, .3) !important; } .search-icons { .el-icon-close{ color: #111; background-color: #d8d8d8; border-radius: 50%; padding: 2px; box-sizing: border-box; font-size: 15px; cursor: pointer; } .el-icon-close:hover{ color: #fff; background-color: #209df7; } } } .search-list{ height: 480px; margin-top: 8px; border: 0 none; border-radius: 3px; box-shadow: 0 0 6px rgba(0, 0, 0, .15); background-color: #fff; .search-result { height: 100%; overflow-x: hidden; overflow-y: auto; ul, li{ margin: 0px; padding: 0px; } li{ list-style-type: none; } .select-li { cursor: pointer; padding: 8px 10px; overflow: hidden; border-bottom: 1px solid #ebebeb; .user-avatar { border-radius: 50%; float: left; width: 40px; height: 40px; background-size: cover; } .user-name { width: 200px; float: left; margin-left: 15px; line-height: 40px; .keyword { color: #008cee; } } } .select-li:hover{ background-color: #e5f0fa; } .is-selected { background-color: rgba(140, 197, 255, 0.46) } } .result-null { margin-top: 100px; text-align: center; font-size: 20px; } } } ::-webkit-scrollbar { width: 6px; height: 6px; } /*滑动轨道*/ ::-webkit-scrollbar-track-piece { background-color: transparent; -webkit-border-radius: 6px; } // 下面是滑块 /*竖向滚动条*/ ::-webkit-scrollbar-thumb:vertical { height: 5px; background-color: rgb(161, 161, 161); -webkit-border-radius: 6px; } /*横向滚动条*/ ::-webkit-scrollbar-thumb:horizontal { width: 5px; background-color: rgb(143, 144, 145); -webkit-border-radius: 6px; }
以上直播源代码就实现了一个简单的搜索框。
下面对直播源代码的搜索过程进行简单的优化:
在data中添加
timer:null
将搜索过程放入
setTimeout 函数中,按键抬起半秒后再去进行搜索。
clickSearch () {//查询 if (event.code == "ArrowDown" || event.code == "ArrowUp") {//上下键 return; } if (event.code == "Enter" && this.selectItem) { this.clickResultItem(this.selectItem);//有搜索结果时按下enter直接选中第一项 return; } this.result = [];//全部搜索结果 this.curIndex = 0;//选中的搜索结果的下标 this.selectItem = {};//选中的搜索结果 if (this.value.trim()) { clearTimeout(this.timer); this.timer = setTimeout(function () { for (let i = 0; i < this.userList.length; i++) {//根据所有人员名字匹配 let name = this.userList[i].name; let search = PinyinMatch.match(name, this.value); if (search && search.length > 0) { this.userList[i].keyword = this.getKeyWord(name, search); this.userList[i].isSelected = false; this.result.push(this.userList[i]); } } if (this.result && this.result[0]) { this.result[0].isSelected = true; this.curIndex = 0;//选中的搜索结果的下标 this.selectItem = this.result[0];//选中的搜索结果 } }, 500) } else { this.$refs.searchInput.focus();//没有输入查询条件焦点不应该失去 } },
本文由云豹科技转发自五花漏博客,如有侵权请联系作者删除
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70002045/viewspace-2789504/ ,如需转载,请注明出处,否则将追究法律责任。