如何使用 Vue 实现带标签的输入框?

1. 引言

标签化的输入框在许多前端开发中是非常常见的一个需求,它可以让用户更快速的输入或选择特定的选项。Vue 作为目前流行的前端框架之一,我们可以使用它的组件化思想来实现一个带标签的输入框。

2. 简单的标签化输入框

2.1 创建组件

首先,我们需要创建一个 Vue 组件。我们可以在 Vue.js 官方文档中找到组件的详细用法。下面是一个最简单的标签化输入框组件的代码:

Vue.component('tag-input', {

template: `

<div class="tag-input">

<input v-model="inputValue" @keyup.enter="addTag" />

<div v-for="tag in tags" :key="tag" class="tag">{{ tag }}</div>

</div>

`,

data() {

return {

inputValue: '',

tags: []

}

},

methods: {

addTag() {

if (this.inputValue && !this.tags.includes(this.inputValue)) {

this.tags.push(this.inputValue);

this.inputValue = '';

}

}

}

});

这里我们创建了一个名为 tag-input 的组件,它包含一个 input 元素和一个 div 元素,这个 div 元素用于展示用户添加的标签。 

2.2 实现标签添加功能

我们需要在 input 元素中实现输入完成后添加标签的功能。我们可以使用 v-model 指令来实时响应 input 元素的内容,使用 @keyup.enter 事件来响应用户按下 enter 键添加标签。在 addTag 方法中,我们判断用户输入的值是否为空或者重复,并将它添加到 tags 数组中,添加完毕后清空 input 的值。

我们的基础标签化输入框组件已经实现了,现在我们可以在页面中使用这个组件,并进行测试:

<div id="app">

<tag-input></tag-input>

</div>

new Vue({

el: '#app'

});

现在我们可以访问页面,尝试在 input 中输入标签,按下 enter 键确认,可以看到输入的标签实时的追加在输入框下方。

3. 支持标签删除功能

我们已经实现了一个最基础的标签化输入框组件,但是现在无法删除已经添加的标签,这会给用户带来不方便的使用体验。下面,我们将添加标签删除功能。

3.1 修改标签显示方式

为了支持标签删除,我们需要对已经添加的标签的展示方式进行修改。我们使用一个 span 元素来显示标签,并为每个标签添加一个删除按钮,代码如下:

Vue.component('tag-input', {

template: `

<div class="tag-input">

<input v-model="inputValue" @keyup.enter="addTag" />

<span v-for="(tag, index) in tags" :key="tag" class="tag">

{{ tag }}

<span class="remove-tag" @click="removeTag(index)">x</span>

</span>

</div>

`,

data() {

return {

inputValue: '',

tags: []

}

},

methods: {

addTag() {

if (this.inputValue && !this.tags.includes(this.inputValue)) {

this.tags.push(this.inputValue);

this.inputValue = '';

}

},

removeTag(index) {

this.tags.splice(index, 1);

}

}

});

我们为每个标签添加了一个 span 元素,里面包含标签名和移除按钮。当用户点击移除按钮时,我们可以通过 index 参数获取当前点击的标签在数组中的下标,然后使用数组的 splice 方法将它从数组中删除。

3.2 样式调整

当我们添加了标签删除功能后,标签显示的样式会发生一些变化,需要稍加调整。下面是一个简单的 CSS 样式:

.tag-input {

display: flex;

flex-wrap: wrap;

padding: 10px;

border: 1px solid #ccc;

}

.tag {

display: inline-block;

margin: 5px;

background-color: #f5f5f5;

padding: 5px;

border-radius: 3px;

font-size: 14px;

}

.remove-tag {

padding-left: 5px;

cursor: pointer;

}

通过以上 CSS 样式的调整,我们可以使标签化输入框看起来更加美观和舒适。

4. 使用带提示的标签化输入框

除了基本的标签化输入框之外,有时候我们需要提供给用户一些可选的标签,让用户可以从中选取已有的标签。这就需要实现一个带提示的标签化输入框。下面是我们实现带提示的标签化输入框的代码。

4.1 显示可选标签和选项列表

我们需要实现两个能力:一是在用户输入的时候,动态更新可选标签列表;二是在 input 框聚焦或者用户开始输入的时候,展示可选标签列表。为此,我们需要添加一个新的方法,getOptions,这个方法将返回当前可选的标签,并将其动态渲染到页面上。

Vue.component('tag-input', {

template: `

<div class="tag-input" ref="tagInput">

<input v-model="inputValue" @focus="suggest" @keyup.enter="addTag" @keydown.up="arrowUp" @keydown.down="arrowDown" @keyup.esc="unSuggest" />

<div v-for="(tag, index) in tags" :key="tag" class="tag">

{{ tag }}

<span class="remove-tag" @click="removeTag(index)">x</span>

</div>

<div v-show="suggestedOptions.length" class="options">

<li v-for="(option, index) in suggestedOptions" :key="index" @click="choose(index)" :class="{ active: index === activeIndex }">{{ option }}

</div>

</div>

`,

data() {

return {

inputValue: '',

tags: [],

options: ['HTML', 'CSS', 'JavaScript', 'Vue', 'React', 'Angular'],

suggestedOptions: [],

activeIndex: -1

}

},

methods: {

addTag() {

if (this.inputValue && !this.tags.includes(this.inputValue)) {

this.tags.push(this.inputValue);

this.inputValue = '';

}

},

removeTag(index) {

this.tags.splice(index, 1);

},

suggest() {

this.suggestedOptions = this.getOptions();

},

unSuggest() {

this.suggestedOptions = [];

},

choose(index) {

this.inputValue = this.suggestedOptions[index];

this.suggestedOptions = [];

this.addTag();

},

getOptions() {

const options = this.options;

const value = this.inputValue.toLowerCase();

return options.filter(option => option.toLowerCase().startsWith(value) && !this.tags.includes(option));

},

arrowUp() {

if (this.activeIndex > 0) {

this.activeIndex--;

}

},

arrowDown() {

if (this.activeIndex < this.suggestedOptions.length - 1) {

this.activeIndex++;

}

}

}

});

在以上代码中,我们添加了 input 元素的 focus 事件,将输入框的 ref 设为 tagInput,获取当前可选的标签,并动态更新 suggestedOptions 的值。当 suggestedOptions 不为空时,我们可以将它进行渲染,用户可以选择已有的标签或者继续输入新的标签。

在这个代码中,我们依旧使用了之前的 addTag 和 removeTag 方法来实现新标签的添加和已有标签的删除,但是现在,当用户选择已有标签时,我们需要通过 choose 方法将选中的标签添加到输入框内。如果用户输入的内容没有匹配到标签,我们不会进行提示操作,而是关闭提示框。

4.2 调整样式

我们需要调整样式来适应带提示的标签化输入框,下面是弹出提示框及其选项列表的样式:

.options {

position: absolute;

z-index: 10;

background-color: #fff;

width: 100%;

box-shadow: 0px 0px 5px #ccc;

margin-top: 2px;

}

.options ul {

margin: 0;

padding: 0;

list-style: none;

max-height: 200px;

overflow-y: auto;

}

.options li {

padding: 5px 10px;

cursor: pointer;

}

.options li.active {

background-color: #f5f5f5;

}

现在,我们已经实现了一个功能完善、样式美观的带提示标签化输入框,用户可以在输入框中快速选择或添加标签。

5. 总结

我们在本文中使用了 Vue.js 以及组件化思想,实现了一个功能完善、美观大方的带标签、带提示的输入框。Vue.js 的组件化开发思想,可以让我们高效、灵活的进行前端开发。