【问题标题】:Vue.js Keys events Up, Down, Enter to control selectionVue.js 按键事件 Up、Down、Enter 来控制选择
【发布时间】:2020-06-22 17:32:47
【问题描述】:

我在一个带有列表输出的数组中进行了搜索。在列表中需要选择一个产品。鼠标单击事件添加所选项目。然后它被添加到另一个数组中,然后我们已经在使用它了。

一切都完美!

但我需要添加使用键盘键 Up、Down 和 Enter 进行选择的功能。

我可以使用事件“v-on:keyup.up”“v-on:keyup.down”“v-on:keyup.enter”,但是在方法里面做什么呢?

需要:使用向下和向上键,选择所需的项目,该项目使用“活动”类突出显示。 当按下 Enter 时,元素 id 值被传递给方法。 怎么做?

模板:

    <input class="form-control col-sm-4" type="text" v-model="searchGoods" placeholder="Search">
    <div v-if="searchGoods">
        <ul class="col-sm-4 list-group" v-if="goodsList.length">
            <li v-for="item in searchQuery" class="list-group-item list-group-item-action" @click="addGoods(item.id)">{{item.name}}</li>
        </ul>
    </div>

JS:

        data () {
        return {
          goodsList: [
            { id: '1', name: 'Cheese 1' },
            { id: '3', name: 'Cheese 2' },
            { id: '4', name: 'Cheese 3' },
            { id: '5', name: 'Meat' },
            { id: '7', name: 'Tomato' },
            { id: '11', name: 'Sauce' },
          ],
          searchGoods: ''
        }
    },
    computed: {
        searchQuery: function(){
            if (this.searchGoods){
                return this.goodsList.filter((item)=>{
                    return this.searchGoods.toLowerCase().split(' ').every(v => item.name.toLowerCase().includes(v))
                })}
            else{
                return this.goodsList;
            }
        },
    },
    methods: {
        addGoods(id){
            let goods=this.goodsList.find(item => item.id == id);
            this.products.push({
                id: id,
                goods_name: goods.name
            });
            this.searchGoods='';
        },
    }

尝试输入“Chee”,我们在 HTML 上看到的内容:

    <div>
    <input type="text" placeholder="Search" class="form-control col-sm-4"> 
        <div>
            <ul class="col-sm-4 list-group">
                <li class="list-group-item list-group-item-action">Cheese 1</li>
                <li class="list-group-item list-group-item-action">Cheese 2</li>
                <li class="list-group-item list-group-item-action">Cheese 3</li>
            </ul>
        </div>
    </div>

【问题讨论】:

    标签: vue.js


    【解决方案1】:

    您必须跟踪列表中的活动项目以及过滤的项目

    示例

    new Vue({
      data() {
        return {
          products: [],
          goodsList: [{
              id: '1',
              name: 'Cheese'
            },
            {
              id: '2',
              name: 'Meat'
            },
            {
              id: '3',
              name: 'Fruits'
            },
            {
              id: '4',
              name: 'Vegetables '
            },
            {
              id: '5',
              name: 'Sweets'
            },
            {
              id: '6',
              name: 'Furniture'
            },
            {
              id: '7',
              name: 'Fish'
            },
            {
              id: '8',
              name: 'Lamb'
            },
            {
              id: '9',
              name: 'Utensils'
            }
          ],
          filtered: [],
          active: {
            id: -1,
            index: 0
          },
          searchGoods: ''
        }
      },
      watch: {
        searchGoods: function() {
          if (!this.searchGoods) {
            this.filtered = [];
            return;
          }
    
          const normalized = this.searchGoods.toLowerCase();  
          this.filtered = this.goodsList.filter(({name}) => name.toLowerCase().includes(normalized))
          
          if(!this.filtered.length) {
            return;
          }
          
          const id = this.filtered[this.active.index].id;
          this.$set(this.active, 'id', id);
        }
      },
      created() {
        window.addEventListener('keydown', this.onKey)
      },
      beforeDestroy() {
        window.removeEventListener('keydown', this.onKey)
      },
      methods: {
        onKey(event) {
          const key = event.key;
          
          const map = {
            Enter: () => {
              this.addGoods(this.active.id);
            },
            ArrowDown: () => {
              const { active, filtered } = this;
              const index = (active.index + 1) % this.filtered.length;
              const id = filtered[index].id;
              
              this.active = {
                index,
                id
              };
            },
            ArrowUp: () => {
              const { active, filtered } = this;
              let index = active.index - 1;
              index = index < 0 ? filtered.length - 1 : index;
              const id = filtered[index].id;
              
              this.active = {
                index,
                id
              };
            }
          }
          
          const func = map[key];
          if(func) {
            func();
          }
        },
        addGoods(id) {
          let goods = this.goodsList.find(item => item.id == id);
          this.products.push({
            id: id,
            goods_name: goods.name
          });
          this.searchGoods = '';
          this.filtered = [];
        },
      },
      el: '#container',
    });
    .active {
      border: 1px solid black;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    <div id="container">
      <div>
        <input class="form-control col-sm-4" type="text" v-model="searchGoods" placeholder="Search">
        <div v-if="filtered.length">
          <ul class="col-sm-4 list-group" v-if="goodsList.length">
            <li :class="{'active': active.id === item.id}" v-for="item in filtered" class="list-group-item list-group-item-action" @click="addGoods(item.id)">{{item.name}}</li>
          </ul>
        </div>
        <div>Products: {{JSON.stringify(products)}}</div>
      </div>
    </div>

    【讨论】:

      【解决方案2】:

      所以你已经知道你可以做到v-on:keyup.enter="(YourFunction())

      从那里,有几种方法可以做到。 一种方法是计算告诉您哪个选项处于活动状态,以便您可以从那里获取 id。

      另一种选择是在选择某些内容时设置的数据中设置“currentlySelected”,然后使用 addGoods() 代替 addGoods(id) 并在该方法中获取 this.currentlySelected 并避免需要传入 id完全没有。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-02-04
        • 2016-07-20
        • 1970-01-01
        • 1970-01-01
        • 2016-05-16
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多