一、需求问题
在vue
的项目中,经常会遇到搜索输入框的需求。当我们未输入内容,搜索输入框下面不显示内容。当我们输入内容以后,搜索输入框会实时显示,下面会实时显示搜索出来的内容。这个需求也是比较常见的。
二、需求分析
针对这个需求,我们可以先想到需要用到双向数据绑定,对input
输入框应用v-model
,绑定的值可以设置为keyword
。同时,为了数据发生改变以后,能够实时的监听到,可以使用watch
。一旦数据发生改变以后,keyword
的值就可以监听到,可以执行相应的回调函数。在watch
中,可以进行判断。如果keyword
不存在,也就是用户未输入的时候,下面的list
为空。如果keyword
存在,也就是用户输入以后,我们可以定义一个结果集result
,搜索出来后的数据会放在这个里面,默认为空,然后就可以对目标数据进行forEach
遍历,通过indexOf
判断关键字keyword
是否存在目标数据,如果存在,那么就通过push
方法添加到result
中,最后再将result
的值赋值给下面展示的list
。同时,我们也可以做一些性能优化。为了防止用户未输入完,就进行请求数据,对服务器造成太大的压力,我们可以通过setTimeout
和clearTimeout
使用节流。为了搜素输入框下面的内容展示,可以设置v-show
,如果keyword
存在就展示,如果keyword
不存在就不展示。
三、需求实现
完整的代码实例如下:
<template><div><div class="search"><input v-model="keyword" class="search-input" type="text" placeholder="请输入城市名或者是拼音" /></div><div class="search-content" ref="search" v-show="keyword"><ul><li class="search-item border-bottom" v-for="item of list" :key="item.id" @click="handleCityClick(item.name)">{{ item.name }}</li><li class="search-item border-bottom" v-show="hasNoData">没有找到匹配数据</li></ul></div></div></template><script>import Bscroll from 'better-scroll'import {mapMutations } from 'vuex'export default {name: 'CityHearch',props: {cities: Object},data () {return {keyword: ' ',list: [],timer: null}},mounted () {this.scroll = new Bscroll(this.$refs.search)},computed: {hasNoData () {return !this.list.length}},methods: {handleCityClick (city) {this.changeCity(city)this.$router.push('/')},...mapMutations(['changeCity'])},watch: {keyword () {if (this.timer) {clearTimeout(this.timer)}if (!this.keyword) {this.list = []return}this.timer = setTimeout(() => {const result = []for (let i in this.cities) {this.cities[i].forEach((value) => {if (value.spell.indexOf(this.keyword) > -1 || value.name.indexOf(this.keyword) > -1) {result.push(value)}})}this.list = result}, 100)}}}</script><style lang="stylus" scoped>@import '~styles/varibles.styl'.searchheight: .72rempadding: 0 .1rembackground: $bgColor.search-inputbox-sizing: border-boxwidth: 100%height: .62rempadding: 0 .1remline-height: .62remtext-align: centerborder-radius: .06remcolor: #666.search-contentz-index: 1overflow: hiddenposition: absolutetop: 1.58remleft: 0right: 0bottom: 0background: #eee.search-itemline-height: .62rempadding-left: .2rembackground: #fffcolor: #666</style>