一、函数组建
<script>
export default {
props: {
value: {
type: Array,
},
},
data() {
return {
newTag: '',
}
},
methods: {
addTag() {
if (this.newTag.trim().length === 0 || this.value.includes(this.newTag.trim())) {
return
}
this.$emit('input', [...this.value, this.newTag.trim()])
this.newTag = ''
},
removeTag(tag) {
this.$emit('input', this.value.filter(t => t !== tag))
},
},
render() {
return this.$scopedSlots.default({
tags: this.value,
addTag: this.addTag,
removeTag: this.removeTag,
inputEvents: {
input: e => {
this.newTag = e.target.value
},
keydown: e => {
if (e.keyCode === 13) {
e.preventDefault()
this.addTag()
}
},
},
inputAttrs: {
value: this.newTag,
},
})
},
}
</script>
二、消费组建
<template>
<div id="app layout">
<tagsInput v-model="tags">
<div class="input-tags-wrap" slot-scope="{inputAttrs,inputEvents,tags,removeTag}">
<span class="tag" v-for="tag in tags" :key="tag">
<span>{{tag}}</span>
<button class="tag-input-remove" @click="removeTag(tag)">x</button>
</span>
<input type="text" class="tag-input" v-bind="inputAttrs" v-on="inputEvents" placeholder="Add tag..." >
</div>
</tagsInput>
<tags-input v-model="tags" style="margin-top:50px;margin-bottom:50px;">
<div class="input-tags-wrap" slot-scope="{inputAttrs,inputEvents,tags,removeTag,addTag}">
<div class="tags-wrap-header">
<input type="text" v-bind="inputAttrs" v-on="inputEvents" placeholder="Add tag..." ><button class="tag-input-add" @click="addTag">添加</button>
</div>
<div>
<dl>
<dd v-for="tag in tags " :key="tag">{{tag}}
<button class="tag-input-remove" @click="removeTag(tag)">x</button>
</dd>
</dl>
</div>
</div>
</tags-input>
<button @click="submit">提交</button>
</div>
</template>
<script>
import tagsInput from './components/tagsInput.vue'
export default {
name: 'app',
data(){
return {
tags:['Helllo World','Lange']
}
},
components: {
tagsInput
},
methods:{
submit(){
console.log(this.tags)
}
}
}
</script>
<style>
.layout{
width: 100%;
display: flex;
justify-content: center;
height: 100vh;
}
.input-tags-wrap{
width: 400px;
display: flex;
flex-wrap: wrap;
border:1px solid #eee;
background-color: #fff;
padding: 5px;
}
.input-tags-wrap .tag-input{
border:none;
outline: transparent;
margin-left: 5px;
}
.input-tags-wrap .tag{
background: rgb(219, 148, 15);
color: #fff;
padding: 5px;
border-radius: 5px;
margin: 5px;
}
.tag-input-remove{
outline: transparent;
font-size: 16px;
color: #fff;
border: none;
border-radius: 50%;
margin-left: 5px;
cursor:pointer;
background-color: rgb(7, 230, 118);
}
.tags-wrap-header{
display: flex;
height: 40px;
line-height: 40px;
}
.tags-wrap-header input{
width: 200px;
display: inline-flex;
height: 32px;
line-height: 32px;
box-sizing: border-box;
}
.tags-wrap-header button{
display: inline-flex;
height: 32px;
outline: none;
padding: 0 12px;
background: green;
color: #fff;
border-color: transparent;
line-height: 32px;
cursor: pointer;
}
</style>
三、实现的效果
同一套逻辑,不同的展示方式。高效的复用组件