【笔记】实战mpvue2.0多端小程序框架——搜索模块(上)


搜索开发 | 「小慕读书」官网


一、搜索视觉稿

http://www.youbaobao.xyz/mpvue-design/preview/#artboard1

二、搜索页面组件结构图

search

三、标签组件

可交互的标签组件 tag

组件名称属性参数用途默认值
Tagpropstext标签文本(空)
methodsonClick标签点击事件(空)

1.新建src\components\base\Tag.vue

<template>
  <div class="tag-wrapper" @click="onClick">
    <div class="tag">{{text}}</div>
  </div>
</template>

<script>
export default {
  props: {
    text: {
      type: String,
      default: ''
    }
  },
  methods: {
    onClick() {
      this.$emit('onClick')
    }
  }
}
</script>

<style lang="scss" scoped>
  .tag-wrapper {
    display: flex;
    justify-content: center;
    background: #F7F7F9;
    border-radius: 16px;
    padding: 6px 17px;
    .tag {
      width: 100%;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
      font-size: 14px;
      color: #272E37;
    }
  }
</style>

2.新建src\pages\search\main.js

import Vue from 'vue'
import App from './search'

const app = new Vue(App)
app.$mount()

3.新建src\pages\search\search.vue

<template>
  <div>
  </div>
</template>

<script>
export default {
  components: {
  },
  data() {
    return {
    }
  },
  methods: {
  }
}
</script>

<style lang="scss" scoped>
</style>

修改src\components\home\SearchBar.vue的如下部分(添加点击事件):

<div class="search-bar-wrapper" @click="onSearchBarClick">

src\pages\index\index.vueonSearchBarClick事件添加路由跳转:

onSearchBarClick() {
  this.$router.push('/pages/search/main')
},

4.新建src\pages\search\main.json

{
  "navigationBarTitleText": "搜索"
}

四、标签分组组件

标签分组组件,包含一个标题和按钮,以及标签分组 tag_group

组件名称属性参数用途默认值
TagGrouppropsheaderText标题文本(空)
btnText按钮文本(空)
value标签数据[]
methodsonTagClick标签点击事件(空)
onBtnClick按钮点击事件(空)

1.新建src\components\base\TagGroup.vue

<template>
  <div class="tag-group-wrapper">
    <div class="tag-group-header">
      <div class="header-text">{{headerText}}</div>
      <div class="header-btn" @click="onBtnClick">{{btnText}}</div>
    </div>
    <div class="tag-goup">
      <div class="tag-group-inner" v-for="(text, index) in value" :key="index">
        <Tag :text="text" @onClick="onTagClick(text, index)"/>
      </div>
    </div>
  </div>
</template>

<script>
import Tag from './Tag'
export default {
  components: {Tag},
  props: {
    headerText: String,
    btnText: String,
    value: Array
  },
  methods: {
    onTagClick(text, index) {
      this.$emit('onTagClick', text, index)
    },
    onBtnClick() {
      this.$emit('onBtnClick')
    }
  }
}
</script>

<style lang="scss" scoped>
  .tag-group-wrapper {
    .tag-group-header {
      display: flex;
      justify-content: space-between;
      padding: 0 16px;
      font-size: 14px;
      line-height: 20px;
      .header-text {
        color: #333333;
      }
      .header-btn {
        color: #3696EF;
      }
    }
    .tag-goup {
      display: flex;
      flex-flow: row wrap;
      padding: 4px 10px 0 10px;
      .tag-group-inner {
        padding: 12px 6px 0 6px;
      }
    }
  }
</style>

2.在src\pages\search\search.vue中引入TagGroup

<template>
  <div>
    <TagGroup
      :value="tags"
      header-text="热门搜索"
      btn-text="换一批"
      @onTagClick="onTagClick"
      @onBtnClick="onBtnClick"
    />
  </div>
</template>

<script>
import TagGroup from '../../components/base/TagGroup'
export default {
  components: {
    TagGroup
  },
  data() {
    return {
      tags: [
        'aaaaaa',
        'bbbbb',
        'c',
        'ddddddddddddddddd',
        'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeee',
        'ffffffffff'

      ]
    }
  },
  methods: {
    onTagClick(text, index) {
      console.log('tag...', text, index)
    },
    onBtnClick() {
      console.log('btn...')
    }
  }
}
</script>

3.效果

在这里插入图片描述

五、搜索分类组件

搜索列表中的分类组件 component_search_item

组件名称属性参数用途默认值
SearchItempropstitle标题文本(空)
subTitle副标题文本(空)
icon图标类型(空)
methodsonClick分类点击事件(空)

1.新建src\components\search\SearchItem.vue

<template>
  <div class="search-item-wrapper" @click="onClick">
    <div class="search-item-icon">
      <div class="icon-wrapper">
        <van-icon :name="icon" color="#777777" :style="{ width:'20px', height:'20px' }" />
      </div>
    </div>
    <div class="search-item-info">
      <div class="search-item-title">{{title}}</div>
      <div class="search-item-sub-title">{{subTitle}}</div>
    </div>
  </div>
</template>

<script>
export default {
  props: {
    title: String,
    subTitle: String,
    icon: String
  },
  methods: {
    onClick() {
      this.$emit('onClick')
    }
  }
}
</script>

<style lang="scss" scoped>
  .search-item-wrapper {
    display: flex;
    align-items: center;
    padding: 15px;
    height: 36.5px;
    .search-item-icon {
      .icon-wrapper {
        display: flex;
        justify-content: center;
        align-items: center;
        width: 32px;
        height: 32px;
        border-radius: 50%;
        background: #F7F7F9;
      }
    }
    .search-item-info {
      margin-left: 10px;
      .search-item-title {
        color: #333333;
        font-size: 14px;
        line-height: 20px;
      }
      .search-item-sub-title {
        color: #777777;
        font-size: 12px;
        line-height: 16.5px;
      }
    }
  }
</style>

2.在src\pages\search\search.vue中引入

<SearchItem icon="apps-o" title="计算机科学" sub-title="类别"/>

六、搜索列表组件

搜索结果列表组件

component_search_table

组件名称属性参数用途默认值
SearchTablepropsdata列表数据[]
methodsonClick图书点击事件(空)

1.新建src\components\search\SearchTable.vue

<template>
  <div class="search-table-wrapper">
    <div class="search-table-inner">
      <div class="search-table-book" v-for="(book, index) in data" :key="index" @click="onClick(book)">
        <div class="book-img-wrapper">
          <div class="book-img">
            <ImageView :src="book.cover"/>
          </div>
        </div>
        <div class="book-info-wrapper">
          <div class="book-title">{{book.title}}</div>
          <div class="book-author">{{book.author}}</div>
          <div class="book-category">{{book.categoryText}}</div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import ImageView from '../base/ImageView'
export default {
  components: {ImageView},
  props: {
    data: Array
  },
  methods: {
    onClick(book) {
      this.$emit('onClick', book)
    }
  }
}
</script>

<style lang="scss" scoped>
  .search-table-wrapper {
    padding: 0 16px;
    .search-table-inner {
      .search-table-book {
        margin: 14.5px 0;
        display: flex;
        align-items: center;
        .book-img-wrapper {
          .book-img {
            width: 47px;
            height: 68.5px;
          }
        }
        .book-info-wrapper {
          width: 80%;
          margin-left: 15.5px;
          .book-title {
            color: #333333;
            font-size: 16px;
            line-height: 22.5px;
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
            font-weight: 500;
          }
          .book-author {
            color: #999999;
            font-size: 13px;
            line-height: 18px;
            margin-top: 5px;
          }
          .book-category {
            color: #777777;
            font-size: 13px;
            line-height: 18px;
          }
        }
      }
    }
  }
</style>

2.在src\pages\search\search.vue中引入

<SearchTable :data="list"/>
...
data() {
    return {
    	...
      list: [
        {
          'id': 225,
          'fileName': '2016_Book_MicrofinanceEUStructuralFundsA',
          'cover': 'https://www.youbaobao.xyz/book/res/img/Economics/2016_Book_MicrofinanceEUStructuralFundsA.jpeg',
          'title': 'Microfinance, EU Structural Funds and Capacity Building for Managing Authorities',
          'author': 'Giovanni Nicola Pes',
          'publisher': 'Palgrave Macmillan',
          'bookId': '2016_Book_MicrofinanceEUStructuralFundsA',
          'category': 3,
          'categoryText': 'Economics',
          'language': 'en',
          'rootFile': 'OEBPS/9781137536013.opf'
        },
        {
          'id': 88,
          'fileName': '2018_Book_BetweenMobilityAndMigration',
          'cover': 'https://www.youbaobao.xyz/book/res/img/SocialSciences/978-3-319-77991-1_CoverFigure.jpg',
          'title': 'Between Mobility and Migration',
          'author': 'Peter Scholten',
          'publisher': 'Springer International Publishing',
          'bookId': '2018_Book_BetweenMobilityAndMigration',
          'category': 2,
          'categoryText': 'SocialSciences',
          'language': 'en',
          'rootFile': 'OEBPS/package.opf'
        },
        {
          'id': 225,
          'fileName': '2016_Book_MicrofinanceEUStructuralFundsA',
          'cover': 'https://www.youbaobao.xyz/book/res/img/Economics/2016_Book_MicrofinanceEUStructuralFundsA.jpeg',
          'title': 'Microfinance, EU Structural Funds and Capacity Building for Managing Authorities',
          'author': 'Giovanni Nicola Pes',
          'publisher': 'Palgrave Macmillan',
          'bookId': '2016_Book_MicrofinanceEUStructuralFundsA',
          'category': 3,
          'categoryText': 'Economics',
          'language': 'en',
          'rootFile': 'OEBPS/9781137536013.opf'
        },
        {
          'id': 88,
          'fileName': '2018_Book_BetweenMobilityAndMigration',
          'cover': 'https://www.youbaobao.xyz/book/res/img/SocialSciences/978-3-319-77991-1_CoverFigure.jpg',
          'title': 'Between Mobility and Migration',
          'author': 'Peter Scholten',
          'publisher': 'Springer International Publishing',
          'bookId': '2018_Book_BetweenMobilityAndMigration',
          'category': 2,
          'categoryText': 'SocialSciences',
          'language': 'en',
          'rootFile': 'OEBPS/package.opf'
        },
        {
          'id': 225,
          'fileName': '2016_Book_MicrofinanceEUStructuralFundsA',
          'cover': 'https://www.youbaobao.xyz/book/res/img/Economics/2016_Book_MicrofinanceEUStructuralFundsA.jpeg',
          'title': 'Microfinance, EU Structural Funds and Capacity Building for Managing Authorities',
          'author': 'Giovanni Nicola Pes',
          'publisher': 'Palgrave Macmillan',
          'bookId': '2016_Book_MicrofinanceEUStructuralFundsA',
          'category': 3,
          'categoryText': 'Economics',
          'language': 'en',
          'rootFile': 'OEBPS/9781137536013.opf'
        },
        {
          'id': 88,
          'fileName': '2018_Book_BetweenMobilityAndMigration',
          'cover': 'https://www.youbaobao.xyz/book/res/img/SocialSciences/978-3-319-77991-1_CoverFigure.jpg',
          'title': 'Between Mobility and Migration',
          'author': 'Peter Scholten',
          'publisher': 'Springer International Publishing',
          'bookId': '2018_Book_BetweenMobilityAndMigration',
          'category': 2,
          'categoryText': 'SocialSciences',
          'language': 'en',
          'rootFile': 'OEBPS/package.opf'
        }
      ]
    }
  },

3.效果

在这里插入图片描述

七、综合搜索列表组件

包含分类和列表的综合搜索列表
component_search_list

组件名称属性参数用途默认值
SearchListpropsdata列表数据{}
methodsshowList展示分类点击后的列表(空)

1. 新建src\components\search\SearchList.vue

<template>
  <div class="search-list-wrapper">
    <SearchTable :data="data"/>
    <SearchItem icon="apps-o" title="计算机科学" sub-title="类别"/>
    <SearchItem icon="apps-o" title="计算机科学" sub-title="类别"/>
    <SearchItem icon="apps-o" title="计算机科学" sub-title="类别"/>
  </div>
</template>

<script>
import SearchItem from './SearchItem'
import SearchTable from './SearchTable'
export default {
  components: {SearchTable, SearchItem},
  props: {
    data: Object
  },
  methods: {
    showList() {
    },
  }
}
</script>

<style lang="scss" scoped>
</style>

2.修改src\pages\search\search.vue

  • data中新增:
item: [
  { icon: 'apps-o', title: 'Compute Science', subTitle: 'Category' },
  { icon: 'contact', title: 'Compute Science', subTitle: 'Author' },
  { icon: 'newspaper-o', title: 'Compute Science', subTitle: 'Publisher' }
],
  • 通过computed将data整合为一个参数对象
computed: {
  data() {
    return {
      item: this.item,
      list: this.list
    }
  }
},
  • 去掉SearchTable和SearchItem,替换为SearchList
<SearchList :data="data"/>

3.修改src\components\search\SearchList.vue

在src\components\search\SearchList.vue中使用计算属性动态拿到传过来的数据:

computed: {
  categroy() {
    return this.data.item[0]
  },
  author() {
    return this.data.item[1]
  },
  publisher() {
    return this.data.item[2]
  }
},
  • 在页面部分绑定数据:
<SearchItem
  :icon="categroy.icon"
  :title="categroy.title"
  :sub-title="categroy.subTitle"
  @onClick="showList(categroy.title, 'categroy')"
/>
<SearchItem
  :icon="author.icon"
  :title="author.title"
  :sub-title="author.subTitle"
  @onClick="showList(author.title, 'author')"
/>
<SearchItem
  :icon="publisher.icon"
  :title="publisher.title"
  :sub-title="publisher.subTitle"
  @onClick="showList(publisher.title, 'publisher')"
/>
<SearchTable :data="data.list" @onClick="onBookClick"/>
  • 文件完整内容如下:
<template>
  <div class="search-list-wrapper">
    <SearchItem
      :icon="categroy.icon"
      :title="categroy.title"
      :sub-title="categroy.subTitle"
      @onClick="showList(categroy.title, 'categroy')"
    />
    <SearchItem
      :icon="author.icon"
      :title="author.title"
      :sub-title="author.subTitle"
      @onClick="showList(author.title, 'author')"
    />
    <SearchItem
      :icon="publisher.icon"
      :title="publisher.title"
      :sub-title="publisher.subTitle"
      @onClick="showList(publisher.title, 'publisher')"
    />
    <SearchTable :data="data.list" @onClick="onBookClick"/>
  </div>
</template>

<script>
import SearchItem from './SearchItem'
import SearchTable from './SearchTable'
export default {
  components: {SearchTable, SearchItem},
  props: {
    data: Object
  },
  computed: {
    categroy() {
      return this.data.item[0]
    },
    author() {
      return this.data.item[1]
    },
    publisher() {
      return this.data.item[2]
    }
  },
  methods: {
    showList(text, key) {
      console.log(text, key)
    },
    onBookClick(book) {
      console.log(book)
    }
  }
}
</script>

<style lang="scss" scoped>
</style>

4.效果

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序边界

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值