9. Implementation of the search function on the city selection page of the Vue project

Binding v-model two-way data binding for the input box

Insert picture description here
Go to the parent component City.vue to pass from parent to child, and pass cityies to the child component Search.vue. The child component receives data and
Insert picture description here
Insert picture description here
monitors the keyWord. Because this part is often used, in order to save performance, use function throttling, first in data The Insert picture description here
initial effect of adding timer: null is as follows, and it can be searched out, hahahaha:
Insert picture description here

Increase style, introduce better-scroll plugin to slide up and down

Then modify the style to make it more beautiful. At this time, input text or letters to search out, but when there is a lot of search content, you can’t slide down to see more. Here you need to introduce a better-scroll plug-in to get dom

Insert picture description here
Insert picture description here
Insert picture description here
search.vue

<template>
  <div>
    <div class="search">
      <input
        class="search-input"
        type="text"
        placeholder="输入城市名或拼音"
        v-model="keyWord"
      />
    </div>
    <div class="search-content" ref="search">
      <ul>
        <li
          class="search-item border-bottom"
          v-for="item in list"
          :key="item.id"
        >
          {
   
   { item.name }}
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
import BScroll from 'better-scroll'
export default {
     
     
  name: 'CitySearch',
  props: {
     
     
    cities: Object
  },
  data () {
     
     
    return {
     
     
      keyWord: '',
      list: [],
      timer: null
    }
  },
  // 监听keyword
  // 这里用到函数节流,因为这里用的频率比较高,节约性能
  watch: {
     
     
    keyWord () {
     
     
      if (this.timer) {
     
     
        clearTimeout(this.timer)
      }
      this.timer = setTimeout(() => {
     
     
        const result = []
        // 循环从父组件接收cities里面的内容
        for (let i in this.cities) {
     
     
          // 把cities里面的A、B、C等等键值对里面的值再给遍历一遍
          this.cities[i].forEach(value => {
     
     
            // 如果从spell,name中能搜索到这个关键词,就把这一项添加到result中
            if (
              value.spell.indexOf(this.keyWord) > -1 ||
              value.name.indexOf(this.keyWord) > -1
            ) {
     
     
              result.push(value)
            }
          })
        }
        // 把result结果赋值给list数组,在上面的li中循环list数组
        this.list = result
      }, 100)
    }
  },
    // 列表解决不滑动
  updated () {
     
     
    this.scroll = new BScroll(this.$refs.search)
  }
}
</script>

<style lang="scss" scoped>
@import '~styles/varibles.scss';
.search {
     
     
  background: $bgColor;
  height: 0.72rem;
  padding: 0.1rem;
  padding: 0 0.2rem;
  .search-input {
     
     
    width: 100%;
    height: 0.62rem;
    line-height: 0.62rem;
    text-align: center;
    background: #fff;
    border-radius: 0.06rem;
    color: #666;
  }
}
.search-content {
     
     
  overflow: hidden;
  position: absolute;
  top: 1.58rem;
  left: 0;
  right: 0;
  bottom: 0;
  background: #eee;
  z-index: 1;
  .search-item {
     
     
    line-height: 0.62rem;
    padding-left: 0.2rem;
    color: #666;
    background: #fff;
  }
}
</style>

Solve the situation where there is no content in the input box and the list is still there

Insert picture description here
Insert picture description here

Search results problem

Insert picture description here
Adding a li tag
Insert picture description here
Insert picture description here
to the template requires a judgment because it is used here because of the high frequency of use v-show. If there is no data in the list list, it needs to show that no matching data is found
Insert picture description here

When the input box has no value, it will not be displayed, and it will be displayed

Insert picture description here
The overall code is as follows

<template>
  <div>
    <div class="search">
      <input
        class="search-input"
        type="text"
        placeholder="输入城市名或拼音"
        v-model="keyWord"
      />
    </div>
    <!-- 有值时才显示 -->
    <div class="search-content" ref="search" v-show="keyWord">
      <ul>
        <li
          class="search-item border-bottom"
          v-for="item in list"
          :key="item.id"
        >
          {
   
   { item.name }}
        </li>
        <li class="search-item border-bottom" v-show="!this.list.length">没有找到匹配数据</li>
      </ul>
    </div>
  </div>
</template>

<script>
import BScroll from 'better-scroll'
export default {
     
     
  name: 'CitySearch',
  props: {
     
     
    cities: Object
  },
  data() {
     
     
    return {
     
     
      keyWord: '',
      list: [],
      timer: null
    }
  },
  // 监听keyword
  // 这里用到函数节流,因为这里用的频率比较高,节约性能
  watch: {
     
     
    keyWord() {
     
     
      if (this.timer) {
     
     
        clearTimeout(this.timer)
      }
      //如果input框没有输入内容,那就设置this.list为空数组
      if (!this.keyWord) {
     
     
        this.list = []
        return
      }
      this.timer = setTimeout(() => {
     
     
        const result = []
        // 循环从父组件接收cities里面的内容
        for (let i in this.cities) {
     
     
          // 把cities里面的A、B、C等等键值对里面的值再给遍历一遍
          this.cities[i].forEach(value => {
     
     
            // 如果从spell,name中能搜索到这个关键词,就把这一项添加到result中
            if (
              value.spell.indexOf(this.keyWord) > -1 ||
              value.name.indexOf(this.keyWord) > -1
            ) {
     
     
              result.push(value)
            }
          })
        }
        // 把result结果赋值给list数组,在上面的li中循环list数组
        this.list = result
      }, 100)
    }
  },
  // 列表解决不滑动
  updated() {
     
     
    this.scroll = new BScroll(this.$refs.search)
  }
}
</script>

<style lang="scss" scoped>
@import '~styles/varibles.scss';
.search {
     
     
  background: $bgColor;
  height: 0.72rem;
  padding: 0.1rem;
  padding: 0 0.2rem;
  .search-input {
     
     
    width: 100%;
    height: 0.62rem;
    line-height: 0.62rem;
    text-align: center;
    background: #fff;
    border-radius: 0.06rem;
    color: #666;
  }
}
.search-content {
     
     
  overflow: hidden;
  position: absolute;
  top: 1.58rem;
  left: 0;
  right: 0;
  bottom: 0;
  background: #eee;
  z-index: 1;
  .search-item {
     
     
    line-height: 0.62rem;
    padding-left: 0.2rem;
    color: #666;
    background: #fff;
  }
}
</style>

Optimize code, calculate attributes, try not to have too much logic in the template

Insert picture description here

<template>
  <div>
    <div class="search">
      <input
        class="search-input"
        type="text"
        placeholder="输入城市名或拼音"
        v-model="keyWord"
      />
    </div>
    <!-- 有值时才显示 -->
    <div class="search-content" ref="search" v-show="keyWord">
      <ul>
        <li
          class="search-item border-bottom"
          v-for="item in list"
          :key="item.id"
        >
          {
   
   { item.name }}
        </li>
        <li class="search-item border-bottom" v-show="hasNoData">没有找到匹配数据</li>
      </ul>
    </div>
  </div>
</template>

<script>
import BScroll from 'better-scroll'
export default {
     
     
  name: 'CitySearch',
  props: {
     
     
    cities: Object
  },
  data () {
     
     
    return {
     
     
      keyWord: '',
      list: [],
      timer: null
    }
  },
  computed: {
     
     
    hasNoData () {
     
     
      return !this.list.length
    }

  },
  // 监听keyword
  // 这里用到函数节流,因为这里用的频率比较高,节约性能
  watch: {
     
     
    keyWord () {
     
     
      if (this.timer) {
     
     
        clearTimeout(this.timer)
      }
      // 如果input框没有输入内容,那就设置this.list为空数组
      if (!this.keyWord) {
     
     
        this.list = []
        return
      }
      this.timer = setTimeout(() => {
     
     
        const result = []
        // 循环从父组件接收cities里面的内容
        for (let i in this.cities) {
     
     
          // 把cities里面的A、B、C等等键值对里面的值再给遍历一遍
          this.cities[i].forEach(value => {
     
     
            // 如果从spell,name中能搜索到这个关键词,就把这一项添加到result中
            if (
              value.spell.indexOf(this.keyWord) > -1 ||
              value.name.indexOf(this.keyWord) > -1
            ) {
     
     
              result.push(value)
            }
          })
        }
        // 把result结果赋值给list数组,在上面的li中循环list数组
        this.list = result
      }, 100)
    }
  },
  // 列表解决不滑动
  updated () {
     
     
    this.scroll = new BScroll(this.$refs.search)
  }
}
</script>

<style lang="scss" scoped>
@import '~styles/varibles.scss';
.search {
     
     
  background: $bgColor;
  height: 0.72rem;
  padding: 0.1rem;
  padding: 0 0.2rem;
  .search-input {
     
     
    width: 100%;
    height: 0.62rem;
    line-height: 0.62rem;
    text-align: center;
    background: #fff;
    border-radius: 0.06rem;
    color: #666;
  }
}
.search-content {
     
     
  overflow: hidden;
  position: absolute;
  top: 1.58rem;
  left: 0;
  right: 0;
  bottom: 0;
  background: #eee;
  z-index: 1;
  .search-item {
     
     
    line-height: 0.62rem;
    padding-left: 0.2rem;
    color: #666;
    background: #fff;
  }
}
</style>


Guess you like

Origin blog.csdn.net/weixin_45811256/article/details/109383762