Vue.JS 值与具有焦点的输入相关联
Posted
技术标签:
【中文标题】Vue.JS 值与具有焦点的输入相关联【英文标题】:Vue.JS value tied on input having the focus 【发布时间】:2017-05-26 20:36:47 【问题描述】:有没有办法在输入获得/失去焦点时更改模型中的值?
这里的用例是一个搜索输入,在您键入时显示结果,这些应该只在焦点位于搜索框上时显示。
这是我目前所拥有的:
<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 解决方案。
【问题讨论】:
见forum-archive.vuejs.org/topic/1005/… 【参考方案1】:在更复杂的场景中处理此类问题的另一种方法可能是允许表单跟踪当前处于活动状态的字段,然后使用观察器。
我将展示一个快速示例:
<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
时才会触发观察程序,但我们不希望这样。我们正在关注user
上的foo
和bar
键。
在幕后,deep: true
正在为this.user
上的所有键添加观察者。如果不启用deep
,Vue 合理地不会产生被动维护每个键的成本。
一个简单的观察者应该是这样的:
watch:
user()
console.log('this.user changed');
,
,
注意:如果你发现我有handler(user)
,你可能有handler(oldValue, newValue)
,但你注意到两者都显示相同的值,这是因为它们都是对同一个user
对象的引用。在这里阅读更多:https://github.com/vuejs/vue/issues/2164
编辑:为了避免深度观看,已经有一段时间了,但我认为您实际上可以像这样观看一个关键:
watch:
'user.foo'()
console.log('user foo changed');
,
,
但如果这不起作用,你也绝对可以制作一个计算道具然后观察:
computed:
userFoo()
return this.user.foo;
,
,
watch:
userFoo()
console.log('user foo changed');
,
,
我添加了这两个额外的示例,以便我们可以快速注意到深度观察会消耗更多资源,因为它会更频繁地触发。在合理的情况下,我个人避免深度观看,而是更精确地观看。
但是,在这个带有user
对象的示例中,如果所有键都对应于输入,那么深度观察是合理的。也就是说可能是。
【讨论】:
【参考方案2】:您可以通过确定特殊的 CSS class
来使用平面,例如这是一个简单的 sn-p:
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>
祝你好运
【讨论】:
【参考方案3】:显然,这就像在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>
【讨论】:
你也可以编写方法并调用它们,而不是在模板中放入太多逻辑。但是这种方式完全可以。 我在 vue 的 docs 和 api 上都没有看到焦点和模糊,它是否列出了我错过的某个地方? @KelvinZhao 它们是原生 js 事件,这就是为什么它们没有在 Vue 文档中列出。 焦点可能经常变化,你可能想使用“v-show”而不是“v-if”vuejs.org/v2/guide/conditional.html#v-show【参考方案4】:您可能还想在用户将鼠标悬停在输入上时激活搜索 - @mouseover=...
这种功能的另一种方法是过滤器输入始终处于活动状态,即使鼠标位于结果列表中也是如此。键入任何字母都会修改过滤器输入而不改变焦点。许多实现实际上只有在输入字母或数字后才显示过滤器输入框。
查看@event.capture。
【讨论】:
以上是关于Vue.JS 值与具有焦点的输入相关联的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Vue JS 组合多个 Vue JS 实例(与多个 html div 关联)?
SQL 表中如何让某条记录的某个属性值与另一个表中的某条记录的某个属性值相关联