嗯。。看来教程还是有说搜索功能的嘛 嘿嘿
好了 直接上内容:
1.首先做一个搜索结果显示的样式:
<template>
// 外出需要用一个div包裹下 因为template只允许子标签只有一组
<div>
<div class="search">
<input v-model="keyword" class="search-input" type="text" placeholder="输入城市名或拼音">
</div>
//这里开始 上面的那些是之前的内容
<div
class="search-content">
<ul>
<li>
</li>
</ul>
</div>
</div>
</template>
<style lang="stylus" scoped>
// 与.search平级
.search-content
z-index: 1
overflow: hidden
position: absolute
top: 1.58rem
left: 0
right: 0
bottom: 0
background: #eee
</style>
2. 将搜索框中的数据与data中的keyword做双向绑定:
<div class="search">
<input v-model="keyword" class="search-input" type="text" placeholder="输入城市名或拼音">
</div>
data () {
return {
keyword: ''
}
}
3. 将cities(城市列表的json数据)由父组件传递到子组件中
//
City.vue
<city-search :cities="cities"></city-search>
//Search.vue
props: {
cities: Object
}
4. 利用keyword监听搜索框的输入并获取cities中的数据(根据拼音或中文检索)
props: {
cities: Object
},
data () {
return {
keyword: '',
list: [],
timer: null
}
},
watch: {
// 监听变量 keyword的变化
keyword () {
// 函数节流。省资源
if (this.timer) {
clearTimeout(this.timer)
}
this.timer = setTimeout(() => {
const result = []
// 将city.json的数据迭代出来(该json有2层 第一层是字母 第二层是字母所包含的城市信息)
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)
}
}
<template>
<div class="search">
<input v-model="keyword" class="search-input" type="text" placeholder="输入城市名或拼音">
</div>
<div
class="search-content"
>
<ul>
//迭代出城市名称
<li
v-for="item of list"
>
{{item.name}}
</li>
</template>
5. 美化样式:
<li
// 添加类
class="search-item border-bottom"
v-for="item of list"
>
{{item.name}}
</li>
<style>
.search-content
z-index: 1
overflow: hidden
position: absolute
top: 1.58rem
left: 0
right: 0
bottom: 0
background: #eee
.search-item
line-height: .62rem
padding-left: .2rem
background: #fff
color: #666
</style>
效果
6. 页面是完成好了。但是有瑕疵。比如 没办法滚动。这时候就需要借助Bscroll对象来处理了
<div class="search">
<input v-model="keyword" class="search-input" type="text" placeholder="输入城市名或拼音">
</div>
<div
class="search-content"
// 这里 绑定DOM元素
ref="search"
>
<script>
import Bscroll from 'better-scroll'
mounted () {
this.scroll = new Bscroll(this.$refs.search)
}
</script>
7. 还有一个问题。当搜索框搜索完成之后,清掉搜索框的内容。下面的页面却依然显示搜索结果。那就如下处理:
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)
}
},
8. 添加一个功能。 在没有匹配项的时候给出提示
<li class="search-item border-bottom" v-show="hasNoData">
没有找到匹配数据
</li>
computed: {
hasNoData () {
return !this.list.length
}
}
9. 还有一个问题。 如果我不需要搜索东西的时候 能不能把搜索结果隐藏起来。
<div
class="search-content"
ref="search"
// 现实与否取决于keyword是否有值
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="hasNoData">
没有找到匹配数据
</li>
</ul>
</div>
完成