• vue 简单的 diy 搜索框 封装,全局组件化,对象配置


    1. 目录结构:

    2. main.js 全局组件

    3. KjfSearch.vue 代码:

    • <template>
          <div class="kjf_search_box" :class="kjfSearchConfig.className">
              <label class="kjf_search_search_label clearfix">
                  <input autocomplete="off" readonly="readonly" type="text" :placeholder="kjfSearchConfig.placeholder"
                         class="search_input" :ref="kjfSearchConfig.refName" v-model="kjfSearchKeyWord"
                         @blur="kjfClearPreSearchData" @focus="kjfHandleSearchEvent" @keyup="kjfHandleSearchEvent($event)" />
                  <a class="search_by_inputs" href="javascript:" @click="kjfHandleSearchEvent('notEvent')">搜索</a>
              </label>
      
              <div class="search_list" v-show="kjfPreSearchData && kjfPreSearchData.length>0">
                  <ul class="search_result">
                      <li v-for="(item, index) in kjfPreSearchData" :key="item.index"
                          :class="{active: index === kjfPreSearchItem}" @click="kjfChoosePreSearchItem(index, item.kjfShowSearchName)">
                          <span class="ellipsis" :title="item.kjfShowSearchName">
                              {{item.kjfShowSearchName}}
                          </span>
                      </li>
                  </ul>
              </div>
          </div>
      </template>
      
      <script>
          import {getElementsByCss} from '../utils';
      
          export default {
              name: 'KjfSearch',
              props: {
                  kjfSearchConfig: {
                      type: Object
                  }
              },
              data: function() {
                  return {
                      kjfSearchKeyWord: '',
                      kjfPreSearchData: [],
                      kjfPreSearchItem: -1
                  };
              },
              computed: {
              },
              watch: {
                  kjfPreSearchData: {
                      deep: true,
                      handler(newArr) {
                          if (newArr && typeof this.kjfSearchConfig.watchCallBack === 'function') {
                              return this.kjfSearchConfig.watchCallBack(newArr);
                          } else {
                              return [];
                          }
                      }
                  }
              },
              mounted() {
              },
              methods: {
                  kjfClearPreSearchData() {
                      this.$refs[this.kjfSearchConfig.refName].setAttribute('readonly', 'readonly');
                      window.setTimeout(() => {
                          this.kjfPreSearchData = [];
                          this.kjfPreSearchItem = -1;
                      }, 200);
                  },
                  kjfChoosePreSearchItem(index, searchName) {
                      this.kjfSearchKeyWord = searchName;
                      this.kjfPreSearchData = [];
                      this.kjfPreSearchItem = -1;
                  },
                  async kjfHandleSearchEvent(e) {
                      this.$refs[this.kjfSearchConfig.refName].removeAttribute('readonly');
      
                      if (e && (e.key === 'ArrowUp' || e.key === 'ArrowDown')) {
                          this.kjfPreSearchItem = e.key === 'ArrowUp' ? (this.kjfPreSearchItem - 1) : (this.kjfPreSearchItem + 1);
                          if (this.kjfPreSearchItem < 0) {
                              this.kjfPreSearchItem = -1;
                          }
                          if (this.kjfPreSearchItem >= this.kjfPreSearchData.length) {
                              this.kjfPreSearchItem = this.kjfPreSearchData.length - 1;
                          }
                          console.log('.' + this.kjfSearchConfig.className + ' .search_list .search_result');
                          const ele = getElementsByCss('.' + this.kjfSearchConfig.className + ' .search_list .search_result')[0];
                          ele && ele.scrollTo(0, this.kjfPreSearchItem * 31);
                          return;
                      } // 上、下选择下拉选项
      
                      if (e && (e.key === 'Enter') && (this.kjfPreSearchItem !== -1)) {
                          this.kjfSearchKeyWord = this.kjfPreSearchData[this.kjfPreSearchItem].kjfShowSearchName;
                          this.kjfPreSearchData = [];
                          this.kjfPreSearchItem = -1;
                          this.$refs[this.kjfSearchConfig.refName].focus();
                          return;
                      } // 回车选中下拉选项
      
                      if ((e === 'notEvent') || (e && e.key === 'Enter')) {
                          window.setTimeout(async () => {
                              this.kjfSearchConfig.enterCallBack(this.kjfSearchKeyWord);
      
                              this.kjfPreSearchData = [];
                              this.kjfPreSearchItem = -1;
                          }, 200);
                          this.$refs[this.kjfSearchConfig.refName].focus();
                          return;
                      } // 回车键按下 或者 点击搜索按钮
      
                      window.clearTimeout(this.searchTimer);
                      this.searchTimer = window.setTimeout(async () => {
                          if (this.kjfSearchKeyWord && this.kjfSearchKeyWord.trim()) {
                              if (!this.kjfSearchKeyWord) {
                                  this.kjfPreSearchData = [];
                                  return;
                              }
                              if (typeof this.kjfSearchConfig.getPreSearchData === 'function') {
                                  this.kjfPreSearchData = await this.kjfSearchConfig.getPreSearchData(this.kjfSearchKeyWord);
                              }
                          } else {
                              this.kjfPreSearchData = [];
                              this.kjfPreSearchItem = -1;
                          }
                      }, 200); // 防抖 搜索
                  }
              }
          };
      </script>
      
      <style lang="stylus" rel="stylesheet/stylus" scoped>
          @import "../../common/stylus/mixins.styl"
      
          .kjf_search_box
              width 100%
              height 100%
              input
                  height 30px
                  text-indent 2px
                  border-radius 4px
                  outline none
                  border 1px solid #DCDFE6
              .kjf_search_search_label
                  display block
                  width 100%
                  height 100%
                  >input
                      float left
                      display block
                      width 240px
                  >a
                      float right
                      display block
                      width 50px
                      height 100%
                      border-radius 4px
                      box-sizing border-box
                      padding 0 10px
                      background-color $themeColor
                      color #fff
              .search_list
                  color $fontColor
                  width 238px
                  max-height 300px
                  overflow hidden
                  .search_result
                      position absolute
                      top 32px
                      left 2px
                      z-index 100
                      width 238px
                      max-height 300px
                      overflow-x hidden
                      overflow-y auto
                      border-radius 0 0 10px 10px
                      background-color #eee
                      padding 0 0 10px 10px
                      box-sizing border-box
                      >li
                          width 180px
                          margin-top 10px
                          color $fontColor
                          white-space normal
                          word-break break-all
                          word-wrap break-word
                          &.active,
                          &:hover
                              cursor pointer
                              >span
                                  color #fff
                                  background-color $themeColor
                          >span
                              color $fontColor
      
      </style>

    4. 使用实例 主要代码: 

    • <template>
          <div id="company_pay_record">
              <ul class="company_pay_record_nav clearfix">
                  <li class="right_company_pay_record_search_li clearfix">
                      <KjfSearch :kjfSearchConfig="companyPayRecordSearchConfig"></KjfSearch>
                  </li>
              </ul>
          </div>
      </template>
      
      <script>
          import {mapState} from 'vuex';
          import {requestMyLabs} from '../../../../axios';
      
          export default {
              name: 'CompanyPayRecord',
              props: {
                  isPC: Boolean
              },
              data () {
                  return {
                      companyPayRecordSearchConfig: {
                          className: 'company_pay_record_search',
                          refName: 'companyPayRecordSearch',
                          placeholder: '请输入操作人/编号',
                          kjfShowSearchName: 'expName',
                          enterCallBack: async (searchKeyWord) => {
                              searchKeyWord = searchKeyWord && searchKeyWord.trim();
                              await this.$store.dispatch('changeLabsCurPageNo', 1);
                              await this.$store.dispatch('changeLabsKeyWord', searchKeyWord);
                              let response = ' - 223 -';
                              try {
                                  response = await this.$store.dispatch('getMyLabs', this.myLabsData); // 获取 myLabsData
                              } catch (e) {
                                  this.myConsole(e);
                                  this.myConsole('response 228: ');
                                  this.myConsole(response);
                              }
                          },
                          getPreSearchData: async (searchKeyWord) => {
                              await this.$store.dispatch('changeLabsKeyWord', searchKeyWord);
                              const response = await requestMyLabs(this.myLabsData);
                              if (response.status === 200) {
                                  return response.data.data.content;
                              }
                          },
                          watchCallBack: (newArr) => {
                              let i = 0;
                              for (; i < newArr.length; i++) {
                                  newArr[i].kjfShowSearchName = newArr[i].experiment.experimentName;
                              }
                              return newArr;
                          }
                      }
                  };
              },
              computed: {
                  ...mapState({
                      myLabsData: state => state.myLabs.myLabsData
                  })
              },
              async mounted () {
                  this.initCompanyPayRecord();
              },
              methods: {
                  async initCompanyPayRecord() {
                  }
              }
          };
      </script>
      
      <style lang="stylus" rel="stylesheet/stylus" scoped>
          @import "../../../../common/stylus/mixins.styl"
      
          #company_pay_record
              width 100%
              margin 0 auto
              .company_pay_record_nav
                  width 100%
                  padding-top 20px
                  padding-bottom 20px
                  box-sizing border-box
                  >li
                      float left
                      width 200px
                      height 30px
                      margin-right 14px
                      line-height 30px
                      &:last-child
                          margin-right 0
                  .right_company_pay_record_search_li
                      float right
                      position relative
                      width 300px
                      height 30px
      
              .my_labs_pagination
                  margin-top 15px
          #company_pay_record_info.is_mobile
              width 100%
              px('font-size', 14)    // 用于 mobile 设计图单位
      </style>

    5. 效果图:

    --------小尾巴 ________一个人欣赏-最后一朵颜色的消逝-忠诚于我的是·一颗叫做野的心.决不受人奴役.怒火中生的那一刻·终将结束...
  • 相关阅读:
    微信开发者工具
    (转)一个基于vue2的天气js应用
    (转)Vue2.0 推荐环境
    编写高质量代码:改善Java程序的151个建议(第3章:类、对象及方法___建议36~40)
    编写高质量代码:改善Java程序的151个建议(第3章:类、对象及方法___建议31~35)
    编写高质量代码:改善Java程序的151个建议(第2章:基本类型___建议26~30)
    编写高质量代码:改善Java程序的151个建议(第2章:基本类型___建议21~25)
    编写高质量代码:改善Java程序的151个建议(第1章:JAVA开发中通用的方法和准则___建议16~20)
    编写高质量代码:改善Java程序的151个建议(第1章:JAVA开发中通用的方法和准则___建议11~15)
    编写高质量代码:改善Java程序的151个建议(第1章:JAVA开发中通用的方法和准则___建议6~10)
  • 原文地址:https://www.cnblogs.com/tianxiaxuange/p/11066069.html
Copyright © 2020-2023  润新知