去哪儿-12-city-search-logic

目标: 城市列表页搜索区域的功能实现

功能:在搜索城市名字或者拼音的时候,能够把搜索的结果显示出来。

搜索列表的布局与逻辑实现

<template>
    <div>
        <div class="search">
            <input class="search-input" type="text" placeholder="请输入城市或字母">
        </div>
        <div class="search-content">
            <ul>
                <li>123</li>
            </ul>
        </div>
    </div>
</template>

样式美化:

.search-content
    overflow hidden
    position absolute
    top 1.58rem
    left 0
    right 0
    bottom 0
    z-index 1
    background green

要想在这个区域中显示搜索结果,就需要将用户的搜索词与和数据做一个双向绑定。data中设置一个keyword,默认为空字符串,使用vue中的v-model让input框的内容与这个keyword值做一个双向绑定。

<div class="search">
    <input v-model="keyword" class="search-input" type="text" placeholder="请输入城市或字母">
</div>

此外,City.vue需要向Search.vue传递cities数据:<city-search :cities="cities"></city-search>,Search.vue接收cities数据:

props: {
    cities: Object
}

Search.vue中在data里面定义一个list空数组,并设置一个watch侦听器来侦听keyword的值,同样的,为了提高性能,我们采用节流的方式:在data中初始化一个值为null的timer,即:

watch: {
    keyword () {
        if (this.timer) {
            clearTimeout(this.timer)
        }
        this.timer = setInterval(() => {
            
        }, 100);
    }
}

具体的逻辑实现:

this.timer = setInterval(() => {
    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);

代码分析:
在cities中,每一项数据是这样的:

"A": [{
        "id": 56,
        "spell": "aba",
        "name": "阿坝"
    }

循环遍历cities中的数据,判断用户搜索的中文关键词或者拼音是否在这个数据库当中,如果存在的话就把它们放在一个数组里面,最终将这个结果给到this.list用于渲染到页面上的搜索列表当中:

<div class="search-content">
    <ul>
        <li class="search-item border-bottom" v-for="item of list" :key="item.id">
            {{item.name}}
        </li>
    </ul>
</div>

至此,页面上的搜索功能就能实现了,接下来再做进一步的样式优化:

.search-item
    line-height .62rem
    padding-left .2rem
    background #fff
    color #666

此时会发现,当我们搜索一个城市的名字,比如果是“阿”开头的,就会显示出很多“阿”开头的城市名字,但是此时的页面无法滚动,超出页面的部分无法查看,我们借助better-scroll插件来实现页面的局部滚动功能(使用这个插件之前不要忘记引入)。

首先,在class="search-content"的div上添加一个ref属性,然后借助生命周期钩子:

mounted () {
    this.scroll = new Bscroll(this.$refs.search)
}

就可以实现搜索列表的局部滚动了。

但是此时会发现,当我在输入框中删除“阿”后,搜索列表还是显示在那里,所以需要进行一个小的优化。在侦听这个keyword的值的时候,判断当这个keyword不存在时候,就将这个list设置为一个空数组然后return就可以了。

当用户输入的数据在数据库中不存在的时候,搜索列表中没有内容,这时可以给用户一个"没有找到匹配数据"的提示:

<li class="search-item border-bottom">没有找到匹配数据</li>

但是会发现,这个提示语句在一开始搜索的时候以及搜索过程中都会显示,我们想要的效果是,当搜索列表中有数据的时候不显示提示信息,当匹配不到用户搜索的数据的时候才会显示出来。可以使用v-show来实现:

<li class="search-item border-bottom" v-show="!list.length">没有找到匹配数据</li>

上述的效果实现了,但是这个列表区域把之前写过的城市列表全部遮挡住了。这个搜索列表区域的显示语法可以通过一个变量来控制:

<div 
    class="search-content" 
    ref="search"
    v-show="keyword"
>
    <ul>
        <li 
            class="search-item border-bottom" 
            v-for="item of list" 
            :key="item.id"
        >
            {{item.name}}
        </li>
        <li class="search-item border-bottom" v-show="!list.length">没有找到匹配数据</li>
    </ul>
</div>

这就表示,当keyword有值的时候就会显示,没有值的时候就会隐藏。

代码小优化

<li class="search-item border-bottom" v-show="!list.length">没有找到匹配数据</li>

在上面的代码中,v-show指令中有一个取反的运算符!, 我们应该避免在模板当中出现逻辑性的描述。所以,可以定义一个计算属性:

hasNoData () {
    return !this.list.length
}

所以模板中就变成了:

<li class="search-item border-bottom" v-show="hasNoData">没有找到匹配数据</li>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值