zoukankan      html  css  js  c++  java
  • vue-music 关于Search(搜索页面)-- 搜索历史

    搜索历史展示每一次搜索过,并选中的关键字,保存数据到数组。搜索历史数据是需要在多个组件中共享的,所以保存在vuex 中 searchHistory 数组中,保存触发在搜索列表点击选中之后派发事件到search.vue 中,search.vue 监听事件并提交actions改变共享数组,改变vuex 中共享数据之前需要存到本地缓存 Localstorage 中,在本地存储 中判断如果当期历史搜索数据在数据中已经有则提前插入到第一位,没有则添加到数组中存储

    在common 中 创建cache.js 里面写所有相关存储的逻辑代码。使用goog-storage 库 方便调用localstorage 相关api

    保存本地搜索历史首先获取访问本地存储中的key 如果已经有值则赋值,没有则赋值为空数组,插入新数据前先与当前历史数据列表比较有没有相同数据,有则且在第一个位置原样返回该数据,有且大于第一个位置则删除该数据,然后再插入,并且插入大于最大限制条数的时候,删除数组的最后一个元素。最后调用storage.set(key,val) 存到本地缓存中。并且 在action 中提交到vuex数据中

    cache.js

    import storage from 'good-storage'
    
    const SEARCH_KEY = '__search__'
    const SEARCH_MAX_LEN = 15
    
    // 检索函数,判断新增的是否存在
    function insertArray(arr, val, compare, maxLen) {
      const index = arr.findIndex(compare)
      if (index === 0) {
        return
      }
      if (index > 0) {
        arr.splice(index, 1)
      }
      arr.unshift(val)
      if (maxLen && arr.length > maxLen) {
        arr.pop()
      }
    }
    
    export function saveSearch(query) {
      let searches = storage.get(SEARCH_KEY, [])
      insertArray(searches, query, (item) => {
        return item === query
      }, SEARCH_MAX_LEN)
      storage.set(SEARCH_KEY, searches)
      return searches
    }
      export function loadSearch() {    return storage.get(SEARCH_KEY, [])  }

    actions.js

    export const saveSearchHistory = function({commit},query){
      commit(types.SET_SEARCH_HISTORY,saveSearch(query));
    } 

    state.js

    import {loadSearch} from 'common/js/cache.js';
    
    const state = {
        singer:{},
        playing:false,
        fullScreen:false,
        playList:[],
        sequenceList:[],
        mode:playMode.sequence,
        currentIndex:-1,
        disc:{},
        topList:{},
        searchHistory:loadSearch()    //默认值从本地存储中获取
    }
    export default state

    将获取来的vuex数据遍历到历史数据列表组件上search-list 组件

    <template>
      <div class="search-list" v-show="searches.length">
        <ul>
          <li :key="item" class="search-item" @click="selectItem(item)" v-for="item in searches">
            <span class="text">{{item}}</span>
            <span class="icon" @click.stop="deleteOne(item)">
              <i class="icon-delete"></i>
            </span>
          </li>
        </ul>
      </div>
    </template>
    
    <script type="text/ecmascript-6">
      export default {
        props: {
          searches: {
            type: Array,
            default: []
          }
        },
        methods: {
          selectItem(item) {
            this.$emit('select', item)
          },
          deleteOne(item) {
            this.$emit('delete', item)
          }
        }
      }
    </script>

    组件上派发一个选中本条历史数据和删除本条历史数据的方法,选中本条可以引用addQuery 方法将本条数据再次填在input 搜索框中。删除本条调用action 方法

    function deleteFromArray(arr, compare) {
      const index = arr.findIndex(compare)
      if (index > -1) {
        arr.splice(index, 1)
      }
    }
    
    // 删除后的数组存到本地
    export function deleteSearch(query) {
      let searches = storage.get(SEARCH_KEY, [])
      deleteFromArray(searches, (item) => {
        return item === query
      })
      storage.set(SEARCH_KEY, searches)
      return searches
    }
    
    ------------------ actions.js -----
    
    export const deleteSearchHistory = function({commit},query){
      commit(types.SET_SEARCH_HISTORY,deleteSearch(query));
    }

    点击清除所有历史数据方法和删除本条的逻辑一样,需要提交actions 清除本地缓存数据,并返回一个空数组赋值给vuex 数据,然后组件通过mapActions 调用该方法清空历史数据

    // 清除数据
    export function clearSearch() {
      storage.remove(SEARCH_KEY)
      return []
    }
    
    // 提交空数组
    export const clearSearchHistory = function({commit}){
      commit(types.SET_SEARCH_HISTORY,clearSearch());
    }

    search.vue 引入mapActions ,代理调用clearSearchHistory 方法

    import {mapActions,mapGetters} from 'vuex'
    
    ...mapActions([
      'saveSearchHistory',
      'deleteSearchHistory',
      'clearSearchHistory'
    ])
    
    // 绑定派发事件   
    deleteAll(){
      this.clearSearchHistory();
    },
    
    //!注意这里可以直接将代理的方法直接绑定到监听事件中,可省略再次写方法名
    
    // 之前是
    <span class="clear" @click="deleteAll">
    
    // 可改为
    <span class="clear" @click="clearSearchHistory">

    优化体验,点击清空所以数据的时候弹窗确认删除才删除

    建立confirm 组件,向外派发点击确认按钮时的事件,这里就直接把确认的派发事件写成 clearSearchHistory 。取消的话影藏自身就行

    // confirm 组件<template>
      <transition name="confirm-fade">
        <div class="confirm" v-show="showFlag" @click.stop>
          <div class="confirm-wrapper">
            <div class="confirm-content">
              <p class="text">{{text}}</p>
              <div class="operate">
                <div @click="cancel" class="operate-btn left">{{cancelBtnText}}</div>
                <div @click="confirm" class="operate-btn">{{confirmBtnText}}</div>
              </div>
            </div>
          </div>
        </div>
      </transition>
    </template>
    
    <script type="text/ecmascript-6">
      export default {
        props: {
          text: {
            type: String,
            default: ''
          },
          confirmBtnText: {
            type: String,
            default: '确定'
          },
          cancelBtnText: {
            type: String,
            default: '取消'
          }
        },
        data() {
          return {
            showFlag: false    // 内部变量控制其显示影藏
          }
        },
        methods: {
          show() {
            this.showFlag = true
          },
          hide() {
            this.showFlag = false
          },
          cancel() {
            this.hide()
            this.$emit('cancel')
          },
          confirm() {
            this.hide()
            this.$emit('confirm')
          }
        }
      }
    </script>
  • 相关阅读:
    js基础之BOM
    js基础之DOM
    js基础之数组
    js基础之arguments、css
    四个使用this的典型应用
    网页优化URI(http URI scheme与data URI scheme)
    FF与IE对JavaScript和CSS的区别
    javascrip自定义对象的方式
    常用的JavaScript验证正则表达式1
    4.26日软件开发日记:今天我干了什么?
  • 原文地址:https://www.cnblogs.com/catbrother/p/9180406.html
Copyright © 2011-2022 走看看