Vue JS关注输入的下一个输入

时间:2016-10-02 19:27:50

标签: javascript focus vue.js

我有2个输入,当用户按Enter键时,希望切换焦点从第一个到第二个。 我尝试将jQuery与Vue混合,因为我无法找到任何关注Vue文档中某些内容的函数:

<input v-on:keyup.enter="$(':focus').next('input').focus()"
    ...>
<input  ...>

但是在输入时我在控制台中看到错误:

build.js:11079 [Vue warn]: Property or method "$" is not defined on the instance but referenced during render. Make sure to declare reactive data properties in the data option. (found in anonymous component - use the "name" option for better debugging messages.)warn @ build.js:11079has @ build.js:9011keyup @ build.js:15333(anonymous function) @ build.js:10111
build.js:15333 Uncaught TypeError: $ is not a function

8 个答案:

答案 0 :(得分:12)

您可以尝试这样的事情:

<input v-on:keyup.enter="$event.target.nextElementSibling.focus()" type="text">

<强> JSfiddle Example

答案 1 :(得分:5)

来自@zurzui的跟进在我看来是使用$refs API(https://vuejs.org/v2/api/#vm-refs)的更清洁的替代方案。

使用$refs API,可以让您以更简单的方式定位元素,而无需遍历DOM。

  

示例:https://jsfiddle.net/xjdujke7/1/

答案 2 :(得分:2)

经过一些测试,它正在运作

new Vue({
    el:'#app',
    methods: {
      nextPlease: function (event) {
        document.getElementById('input2').focus();
      }
    }
});
<script src="https://vuejs.org/js/vue.js"></script>
<div id='app'>
    <input type="text" v-on:keyup.enter="nextPlease">
    <input id="input2" type="text">
</div>

答案 3 :(得分:1)

directives: {
    focusNextOnEnter: {
        inserted: function (el,binding,vnode) {
            let length = vnode.elm.length;
            vnode.elm[0].focus();
            let index = 0;
            el.addEventListener("keyup",(ev) => {
                if (ev.keyCode === 13 && index<length-1) {
                  index++;
                  vnode.elm[index].focus();
                }
            });
            for (let i = 0;i<length-1;i++) {
                vnode.elm[i].onfocus = (function(i) {
                  return function () {
                    index = i;
                  }
                })(i);
            }
        }
    }
}

//使用它

<el-form v-focusNextOnEnter>
...
</el-form>

答案 4 :(得分:1)

虽然我喜欢指令的答案,因为它可以与其他元素(样式包装器等)内部的输入一起使用,但我发现来来去去的元素有点不灵活,特别是如果它们根据其他字段来来去去。它还做得更多。

相反,我将以下两个不同的指令放在一起。按照以下说明在HTML中使用它们:

<form v-forcusNextOnEnter v-focusFirstOnLoad>
...
</form>

使用以下命令在您的Vue对象(或mixin)中定义它们:

directives: {
        focusFirstOnLoad: {
            inserted(el, binding, vnode) {
                vnode.elm[0].focus();
            },
        },
        focusNextOnEnter: {
            inserted(el, binding, vnode) {
                el.addEventListener('keyup', (ev) => {
                    let index = [...vnode.elm.elements].indexOf(ev.target);

                    if (ev.keyCode === 13 && index < vnode.elm.length - 1) {
                        vnode.elm[index + 1].focus();
                    }
                });
            },
        },
    },

按下回车键时,它将在输入列表中查找当前输入的索引,验证其是否可以放大,并集中显示下一个元素。

键差异:长度和索引是在单击时计算的,使其更适合字段添加/删除;无需其他事件即可更改缓存的变量。

不利的是,这运行起来会稍慢一些/强度更高,但是考虑到它基于UI交互...

答案 5 :(得分:0)

<template>
    <div>
        <div class="row">
            <div class="col-md-6">
                <input type="text" class="form-control" id="1" ref="1">
            </div>
            <div class="col-md-6">
                <input type="text" class="form-control" id="2" ref="2">
            </div>
        </div>
    </div>
</template>
<script>
export default {
    data() {
        return {
            noOfFocusableControls: 2
        };
    },
    mounted() {
        document.addEventListener("keypress", this.switchFocus);
    },
    methods: {
        switchFocus(e) {
            var key = e.which || e.keyCode;
            if (key === 13) {
                var id = parseInt(e.target.id);
                if (id == this.noOfFocusableControls) {
                    id = 0;
                }
                id = id + 1;
                var focus = this.setFocus(id);
            }
        },
        setFocus(id) {
            var foused = false;
            for (var ref in this.$refs) {
                if (ref == id) {
                    this.$refs[ref].focus();
                    foused = true;
                    break;
                }
            }
            return foused;
        }
    }
};
</script>

答案 6 :(得分:0)

Vue.js 的指令是满足此要求的良好做法。

定义一个全局指令:

Vue.directive('focusNextOnEnter', {
  inserted: function (el, binding, vnode) {
    el.addEventListener('keyup', (ev) => {
      if (ev.keyCode === 13) {
        if (binding.value) {
          vnode.context.$refs[binding.value].focus()
          return
        }
        if (!el.form) {
          return
        }
        const inputElements = Array.from(el.form.querySelectorAll('input:not([disabled]):not([readonly])'))
        const currentIndex = inputElements.indexOf(el)
        inputElements[currentIndex < inputElements.length - 1 ? currentIndex + 1 : 0].focus()
      }
    })
  }
})

注意:我们应该排除禁用和只读输入。

用法:

<form>
<input type="text" v-focus-next-on-enter></input>
<!-- readonly or disabled inputs would be skipped -->
<input type="text" v-focus-next-on-enter readonly></input>
<input type="text" v-focus-next-on-enter disabled></input>
<!-- skip the next and focus on the specified input -->
<input type="text" v-focus-next-on-enter='`theLastInput`'></input>
<input type="text" v-focus-next-on-enter></input>
<input type="text" v-focus-next-on-enter ref="theLastInput"></input>
</form>

答案 7 :(得分:-1)