我正在尝试在我的应用程序中重现类似于Microsoft Excel / Google表格的UX,当您键入公式时,您有一个自动完成下拉列表,您可以使用不同的公式和变量。
为此,在验证了自动完成后,我希望能够控制光标的位置。
例如,如果我输入= sum(variable1,variable2),则在变量2的自动完成时,光标应该在最后一个括号之前,而不是在最后。
我理解如何用javascript设置光标的位置,问题是因为我同时修改输入的值并设置光标位置,后者不起作用。
我用更简单的上下文来复制问题: https://jsfiddle.net/joparisot/j8ourfa1/31/
我的HTML:
<div id="app">
<autocomplete v-model="selection"></autocomplete>
</div>
<template id="autocomplete">
<div>
<h2>gernerogrnio</h2>
<input id="my-input"
class="form-control"
type="text"
:value="value"
@keydown.enter="updateValue($event.target.value)">
<p>{{ value }}</p>
</div>
</template>
我的剧本:
Vue.component('autocomplete', {
template: '#autocomplete',
props: {
value: {
type: String,
required: true
}
},
methods: {
updateValue (value) {
var new_value = ''
if (value.length < 4) {
new_value = 'Inferior'
} else {
new_value = 'Superior'
}
this.$emit('input', new_value)
var myInput = document.getElementById('my-input');
this.setCaretPosition(myInput, 5)
},
setCaretPosition(ctrl, pos) {
ctrl.focus();
ctrl.setSelectionRange(pos, pos);
}
}
});
new Vue({
el: '#app',
data: {
selection: 'test'
}
});
我不打扰自动完成,但根据您键入的内容,当您按Enter键时,输入将填充新值。您可以看到,如果您对第11到16行进行注释并将new_value设置为value,则设置光标位置将起作用。
我似乎无法同时做这两件事。有什么想法吗?
答案 0 :(得分:1)
感谢Roy J的评论,我找到了解决方案。
在updateValue函数中添加以下内容:
this.$nextTick(() => {
this.setCaretPosition(myInput, 5)
});
答案 1 :(得分:0)
我从这个问题中学到了setSelectionRange
,并用它来处理信用卡号输入:
模板:
<input
ref="input"
v-model="value"
@input="handleChange"
>
实例方法:
data() {
return {
lastValue: '',
}
},
methods: {
setCursorPosition(el, pos) {
el.focus();
el.setSelectionRange(pos, pos);
},
handleChange() {
// handle backspace event
if (this.value.length < this.lastValue.length) {
this.lastValue = this.value;
this.$emit('input-changed', this.value);
return;
}
// handle value-edit event
if (this.$refs.input.selectionStart < this.value.length) {
const startPos = this.$refs.input.selectionStart;
this.value = this.value.replace(/\W/gi, '').replace(/(.{4})/g, '$1 ').trim();
this.$nextTick(() => this.setCursorPosition(this.$refs.input, startPos));
this.lastValue = this.value;
this.$emit('input-changed', this.value);
return;
}
// handle everything else
this.value = this.value.replace(/\W/gi, '').replace(/(.{4})/g, '$1 ').trim();
this.lastValue = this.value;
this.$emit('input-changed', this.value);
},
},
上述代码的目标是在信用卡输入中添加空格,因此1234123412341234
会自动重新格式化为1234 1234 1234 1234
。冒险进入该区域的人会注意到在编辑输入值时会出现问题。
您可以在上面的示例中看到三个条件。最后一个是默认值,它使用两步组合简单地重新格式化当前值:删除所有空格,然后每第4个字符添加一个空格。
如果注释掉两个if
块,则可以看到问题的出现。
第一个if
块处理退格事件。如您所见,每次输入更改时,该值都会捕获为this.lastValue
。当您按退格键时,第一个条件的目标是不运行正则表达式。我认为,这是更好的UX。如果您注释掉这种情况,您可以看到。
第二个if
块处理编辑事件。测试它的一个好方法是输入一个有效的抄送,但忽略第三个字符,以便所有内容都一个掉。然后添加角色。一切都应该很好。同样,如果退格多个字符。第二个条件的目标是正确管理光标位置(如果希望使用术语,则可以插入符号的位置)。
您可以安全地删除第一个条件以及对lastValue
的所有引用,该代码仍然可以使用。可以说这是更简单但更糟糕的用户体验。
答案 2 :(得分:0)
我找到了解决此问题的简便方法,该方法已在IE和Chrome中进行了100%测试
每次按键都调用此功能
function setCaret(eleId)
{
var mousePosition = $(elemId)[0].selectionStart;
var elem = document.getElementById(elemId);
elem.setSelectionRange(mousePosition + 1, mousePosition + 1);
}
将文本框ID传递给此功能,该功能将找到鼠标位置并在每次按键时放置插入符号