VueDemo-23 搜索相关

23 搜索相关

 

23.1 首页的头部

<template>
  <div class="box">
    <header class="header">
      <div class="mynav">
        <router-link to="/kind" tag="div" class="left">
          <van-icon name="wap-nav" size="18"/>
        </router-link>
        <div class="title">
          <router-link to="/search" tag="div" class="search">
            <van-icon name="search" size="18"/>
            <p>移动硬盘500g</p>
          </router-link>
        </div>
        <div class="right">
          <van-icon v-if="loginState" name="user-o" size="18"/>
          <router-link to="/login" tag="p" v-else>登录</router-link>
        </div>
      </div>
    </header>
    ...
  </div>
</template>
​
<script>
​
import { mapState } from 'vuex'
export default {
  computed: {
    ...mapState({
      loginState: state => state.user.loginState
    })
  },
  .....
}
</script>
​
<style lang="stylus" scoped>
....
.mynav
  background-color #f66
  display flex
  height 0.44rem
  color #fff
  .left
    width 50px
    display flex
    justify-content center
    align-items center
  .title
    flex 1
    display flex
    justify-content center
    align-items center
​
    .search
      width 100%
      height 0.32rem
      background-color #fff
      border-radius 16px
      display flex
      line-height 0.32rem
      color #999
      .van-icon
        width 26px
        margin 7px 4px 7px 20px
      p
        flex 1
  .right
    width 50px
    display flex
    justify-content center
    align-items center
</style>
​

23.2 定义搜索页面以及注册路由

<template>
  <div class="box">
    <div class="header">
      <van-search
        v-model="keyword"
        show-action
        placeholder="请输入搜索关键词"
        @search="onSearch"
      >
  <template #action>
    <div @click="onSearch">搜索</div>
  </template>
</van-search>
    </div>
    <div class="content">
      <h3>最近搜索</h3>
​
      <h3>热门搜索</h3>
​
    </div>
  </div>
</template>
<script>
import Vue from 'vue'
import { Search } from 'vant'
​
Vue.use(Search)
export default {
  data () {
    return {
      keyword: ''
    }
  },
  methods: {
    onSearch () {}
  }
}
</script>
<style lang="stylus" scoped>
.van-search
  padding 5px 12px
</style>
​
 {
    path: '/search',
    name: 'search',
    component: () => import('../views/search/index.vue')
  },
  {
    path: '**',
    component: () => import('../views/home/index.vue')
  }

23.3 搜索结果页面

// src/views/search/result.vue

<template>
  <div class="box">
    <div class="header">
      <van-search
        v-model="keyword"
        show-action
        placeholder="请输入搜索关键词"
        @search="onSearch"
      >
      <template #left>
        <van-icon name="arrow-left" size="18"/>
      </template>
      <template #action>
        <div @click="onSearch">搜索</div>
      </template>
    </van-search>
    </div>
    <div class="content">
​
    </div>
  </div>
</template>
<script>
import Vue from 'vue'
import { Search, Icon } from 'vant'
​
Vue.use(Search)
Vue.use(Icon)
export default {
  data () {
    return {
      keyword: ''
    }
  },
  methods: {
    onSearch () {}
  }
}
</script>
<style lang="stylus" scoped>
.van-search
  padding 5px 12px
.van-search__content
  margin-left 12px
</style>
​
{
    path: '/searchresult', // /searchresult?keyword=111
    name: 'searchresult',
    component: () => import('../views/search/result.vue')
  },
  {
    path: '**',
    component: () => import('../views/home/index.vue')
  }

请求渲染数据

/ api/search.js

import request from '@/utils/request'
​
export function search (params) {
  return request.get('/pro/search', { params })
}
​
<!--search/result.vue-->
<template>
  <div class="box">
    <div class="header">
      <van-search
        v-model="keyword"
        show-action
        placeholder="请输入搜索关键词"
        @search="onSearch"
      >
      <template #left>
        <van-icon name="arrow-left" size="18"/>
      </template>
      <template #action>
        <div @click="onSearch">搜索</div>
      </template>
    </van-search>
    </div>
    <div class="content">
      <van-dropdown-menu>
        <van-dropdown-item v-model="priceVal" :options="priceOption" />
        <van-dropdown-item v-model="salesVal" :options="salesOption" />
        <van-dropdown-item title="筛选" ref="item">
          <van-cell center title="包邮">
            <template #right-icon>
              <van-switch v-model="switch1" size="24" active-color="#ee0a24" />
            </template>
          </van-cell>
          <van-cell center title="团购">
            <template #right-icon>
              <van-switch v-model="switch2" size="24" active-color="#ee0a24" />
            </template>
          </van-cell>
          <div style="padding: 5px 16px;">
            <van-button type="danger" block round @click="onConfirm">
              确认
            </van-button>
          </div>
        </van-dropdown-item>
      </van-dropdown-menu>
      <van-card
        v-for="item of list"
        :key="item.proid"
        :price="item.originprice"
        :desc="item.desc"
        :title="item.proname"
        :thumb="item.img1"
      />
    </div>
  </div>
</template>
<script>
import Vue from 'vue'
import { Search, Icon, Toast, Card, DropdownMenu, DropdownItem, Cell, Switch, Button } from 'vant'
import { search } from '@/api/search'
Vue.use(Search)
Vue.use(Icon)
Vue.use(Toast)
Vue.use(Card)
Vue.use(DropdownMenu)
Vue.use(DropdownItem)
Vue.use(Cell)
Vue.use(Switch)
Vue.use(Button)
export default {
  data () {
    return {
      list: [],
      keyword: '',
      priceVal: 0,
      salesVal: 0,
      switch1: false,
      switch2: false,
      priceOption: [
        { text: '默认排序', value: 0 },
        { text: '价格升序', value: 1 },
        { text: '价格降序', value: 2 }
      ],
      salesOption: [
        { text: '销量排序', value: 0 },
        { text: '销量升序', value: 1 },
        { text: '销量降序', value: 2 }
      ]
    }
  },
  mounted () {
    search({
      keyword: this.$route.query.keyword
    }).then(res => {
      if (res.data.code === '10002') {
        Toast('暂未找到相关商品')
      } else {
        this.list = res.data.data
      }
    })
  },
  methods: {
    onConfirm () {
      this.$refs.item.toggle()
    },
    onSearch () {}
  }
}
</script>
<style lang="stylus" scoped>
.van-search
  padding 5px 12px
.van-search__content
  margin-left 12px
</style>
​

排序以及筛选关联. ---- 深拷贝 备份数据

<template>
  <div class="box">
    <div class="header">
      <van-search
        v-model="keyword"
        show-action
        placeholder="请输入搜索关键词"
        @search="onSearch"
      >
      <template #left>
        <van-icon name="arrow-left" size="18"/>
      </template>
      <template #action>
        <div @click="onSearch">搜索</div>
      </template>
    </van-search>
    </div>
    <div class="content">
      <van-sticky :offset-top="44">
        <van-dropdown-menu>
          <van-dropdown-item v-model="priceVal" @change="priceChange" :options="priceOption" />
          <van-dropdown-item v-model="salesVal" @change="salesChange" :options="salesOption" />
          <van-dropdown-item title="筛选" ref="item">
            <h3>价格区间</h3>
            <van-cell center>
              <template #right-icon>
                <van-field v-model="min" placeholder="最低价" />
                -
                <van-field v-model="max" placeholder="最高价" />
              </template>
            </van-cell>
            <div style="padding: 5px 16px;">
              <van-button type="danger" block round @click="onConfirm">
                确认
              </van-button>
            </div>
          </van-dropdown-item>
        </van-dropdown-menu>
      </van-sticky>
      <van-card
        v-for="item of list"
        :key="item.proid"
        :num="item.sales"
        :price="item.originprice"
        :desc="item.desc"
        :title="item.proname"
        :thumb="item.img1"
      />
    </div>
  </div>
</template>
<script>
import Vue from 'vue'
import { Search, Icon, Toast, Sticky, Field, Card, DropdownMenu, DropdownItem, Cell, Switch, Button } from 'vant'
import { search } from '@/api/search'
Vue.use(Search)
Vue.use(Icon)
Vue.use(Field)
Vue.use(Toast)
Vue.use(Card)
Vue.use(DropdownMenu)
Vue.use(DropdownItem)
Vue.use(Cell)
  Vue.use(Sticky)
Vue.use(Switch)
Vue.use(Button)
export default {
  data () {
    return {
      list: [],
      readyList: [],
      min: '',
      max: '',
      keyword: '',
      priceVal: 0,
      salesVal: 0,
      switch1: false,
      switch2: false,
      priceOption: [
        { text: '默认排序', value: 0 },
        { text: '价格升序', value: 1 },
        { text: '价格降序', value: 2 }
      ],
      salesOption: [
        { text: '销量排序', value: 0 },
        { text: '销量升序', value: 1 },
        { text: '销量降序', value: 2 }
      ]
    }
  },
  mounted () {
    this.keyword = this.$route.query.keyword
    search({
      keyword: this.$route.query.keyword
    }).then(res => {
      if (res.data.code === '10002') {
        Toast('暂未找到相关商品')
      } else {
        this.list = res.data.data
        // 深拷贝
        this.readyList = JSON.parse(JSON.stringify(res.data.data))
      }
    })
  },
  methods: {
    priceChange (value) {
      console.log(value)
      if (value === 0) {
        // 深拷贝
        this.list = JSON.parse(JSON.stringify(this.readyList))
      } else if (value === 1) {
        this.list.sort((a, b) => {
          return a.originprice - b.originprice
        })
      } else if (value === 2) {
        this.list.sort((a, b) => {
          return b.originprice - a.originprice
        })
      } else {
      }
    },
    salesChange (value) {
      console.log(value)
      if (value === 0) {
        // 深拷贝
        this.list = JSON.parse(JSON.stringify(this.readyList))
      } else if (value === 1) {
        this.list.sort((a, b) => {
          return a.sales - b.sales
        })
      } else if (value === 2) {
        this.list.sort((a, b) => {
          return b.sales - a.sales
        })
      } else {
      }
    },
    onConfirm () {
      // 只写最低价
      // 深拷贝
      this.list = JSON.parse(JSON.stringify(this.readyList))
      const arr = this.list.filter(item => {
        // 既有最小值也有最大值
        if (this.min !== '' && this.max !== '') {
          return item.originprice > this.min && item.originprice < this.max
        } else if (this.min === '' && this.max !== '') { // 没有最小值有最大值
          return item.originprice > 0 && item.originprice < this.max
        } else { // 只有最小值
          return item.originprice > this.min
        }
      })
      this.list = arr
      // this.min = ''
      // this.max = ''
      this.$refs.item.toggle()
    },
    onSearch () {}
  }
}
</script>
<style lang="stylus" scoped>
.van-search
  padding 5px 12px
.van-search__content
  margin-left 12px
</style>
​

23.4 搜索继续搜索

Views/search/result.vue

.....
export default {
....
  watch: {
    $route (newVal) {
      this.keyword = newVal.query.keyword
      search({
        keyword: newVal.query.keyword
      }).then(res => {
        if (res.data.code === '10002') {
          Toast('暂未找到相关商品')
        } else {
          this.list = res.data.data
          // 深拷贝
          this.readyList = JSON.parse(JSON.stringify(res.data.data))
        }
      })
    }
  }
}
</script>
​
​

23.4 搜索页面跳转

如果输入框为空,不可以跳转

23.5 记录搜索信息

vie w s/search/result.vue

mounted () {
    this.keyword = this.$route.query.keyword
    search({
      keyword: this.$route.query.keyword
    }).then(res => {
      if (res.data.code === '10002') {
        Toast('暂未找到相关商品')
      } else {
        this.list = res.data.data
        // 深拷贝
        this.readyList = JSON.parse(JSON.stringify(res.data.data))
        // ************************
        const arr = JSON.parse(localStorage.getItem('search')) || []
        const index = arr.indexOf(this.keyword)
        if (index > -1) {
          arr.splice(index, 1)
        }
        arr.unshift(this.keyword)
        console.log(arr)
        localStorage.setItem('search', JSON.stringify(arr))
      }
    })
  },
  
  watch: {
    $route (newVal) {
      this.keyword = newVal.query.keyword
      search({
        keyword: newVal.query.keyword
      }).then(res => {
        if (res.data.code === '10002') {
          Toast('暂未找到相关商品')
        } else {
          this.list = res.data.data
          // 深拷贝
          this.readyList = JSON.parse(JSON.stringify(res.data.data))
          // ************************
          const arr = JSON.parse(localStorage.getItem('search')) || []
          const index = arr.indexOf(this.keyword)
          if (index > -1) {
            arr.splice(index, 1)
          }
          arr.unshift(this.keyword)
          console.log(arr)
          localStorage.setItem('search', JSON.stringify(arr))
        }
      })
    }
  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值