Vue.JS值与具有焦点的输入相关联

问题描述 投票:28回答:4

当输入获得/失去焦点时,有没有办法在模型中更改值?

此处的用例是一个搜索输入,在您键入时显示结果,这些只应在焦点位于搜索框时显示。

这是我到目前为止所拥有的:

<input type="search" v-model="query">
<div class="results-as-you-type" v-if="magic_flag"> ... </div>

然后,

new Vue({
  el: '#search_wrapper',
  data: {
    query: '',
    magic_flag: false
  }
});

这里的想法是,当搜索框有焦点时,magic_flag应该转向true。我可以手动执行此操作(例如,使用jQuery),但我想要一个纯粹的Vue.JS解决方案。

vue.js onfocus
4个回答
61
投票

显然,这就像在event handlers上做一些代码一样简单。

<input 
  type="search" 
  v-model="query"
  @focus="magic_flag = true"
  @blur="magic_flag = false"
/>
<div class="results-as-you-type" v-if="magic_flag"> ... </div>

0
投票

当用户将鼠标悬停在输入上时,您可能还想激活搜索 - @mouseover = ...

这种功能的另一种方法是过滤器输入始终处于活动状态,即使鼠标位于结果列表中也是如此。键入任何字母都会修改滤镜输入而不会更改焦点。许多实现实际上仅在键入字母或数字后显示过滤器输入框。

查看@ event.capture。


0
投票

在更复杂的场景中处理类似这样的事情的另一种方法可能是允许表单跟踪当前活动的字段,然后使用观察者。

我将展示一个快速示例:

<input
    v-model="user.foo"
    type="text"
    name="foo"
    @focus="currentlyActiveField = 'foo'"
>

<input
    ref="bar"
    v-model="user.bar"
    type="text"
    name="bar"
    @focus="currentlyActiveField = 'bar'"
>

...

data() {
    return {
        currentlyActiveField: '',
        user: {
            foo: '',
            bar: '',
        },
    };
},

watch: {
    user: {
        deep: true,
        handler(user) {
            if ((this.currentlyActiveField === 'foo') && (user.foo.length === 4)) {
                // the field is focused and some condition is met
                this.$refs.bar.focus();
            }
        },
    },
},

在我的示例中,如果当前活动字段为foo且值为4个字符长,则下一个字段bar将自动聚焦。在处理信用卡号,信用卡到期和信用卡安全代码输入等表单时,此类逻辑非常有用。用户体验可以通过这种方式得到改进。

我希望这可以激发你的创造力。监视器非常方便,因为它们允许您监听数据模型的更改,并在触发观察器时根据您的自定义需求执行操作。

在我的示例中,您可以看到每个输入都已命名,并且组件知道当前正在关注哪个输入,因为它正在跟踪currentlyActiveField

我所展示的观察者有点复杂,因为它是一个“深度”观察者,这意味着它能够观察物体和阵列。如果没有deep: true,只有在重新分配user时才会触发观察者,但我们不希望如此。我们在foo上观看baruser的关键。

在幕后,deep: true正在为this.user上的所有按键添加观察者。否则Vue不会产生这样做的代价。

一个简单的观察者会是这样的:

watch: {
    user() {
        console.log('user changed');
    },
},

注意:如果你发现我有handler(user) {,你可以有handler(oldValue, newValue) {,但你注意到两者都显示相同的值,这是因为两者都是对同一个user对象的引用。在这里阅读更多:https://github.com/vuejs/vue/issues/2164


0
投票

您可以通过确定一个特殊的CSS class来使用平面,例如这是一个简单的片段:

var vm = new Vue({
	el: '#app',
	data: {
		content: 'click to change content',
		flat_input_active: false
	},
	methods: {
		onFocus: function(event) {
	    	    event.target.select();
	    	    this.flat_input_active = true;
		},
		onBlur: function(event) {
	    	    this.flat_input_active = false;
		}
	},
	computed: {
		clazz: function() {
			var clzz = 'control-form';
			if (this.flat_input_active == false) {
				clzz += ' only-text';
			}
			return clzz;
		}
	}
});
#app {
  background: #EEE;
}
input.only-text { /* special css class */
  border: none;
  background: none;
}
<!-- libraries -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/vue"></script>

<!-- html template -->
<div id='app'>
	<h1>
	<input v-model='content' :class='clazz'
		@focus="onFocus($event)"
		@blur="onBlur"/>
	</h1>
<div>

祝好运

© www.soinside.com 2019 - 2024. All rights reserved.