我已经在 VUE 字段交互的JSFiddle中准备了一个功能代码示例。
https://jsfiddle.net/JLLMNCHR/2a9ex5zu/6/
我有一个正常运行的自定义自动完成组件,一个正常的输入字段和一个要加载的'Load'按钮在自动完成字段的常规输入中输入的值。 此“加载”按钮不起作用。
HTML:
<div id="app">
<p>Selected: {{test1}}</p>
<br>
<div>
<label>Test1:</label>
<keep-alive>
<autocomplete v-model="test1" v-bind:key="1" :items="theItems">
</autocomplete>
</keep-alive>
</div>
<br>
<label>Display this in 'test1':</label>
<input type="text" v-model=anotherField>
<button type="button" v-on:click="loadField()">Load</button>
<br>
<br>
<button type="button" v-on:click="displayVals()">Display vals</button>
</div>
<script type="text/x-template" id="autocomplete">
<div class="autocomplete">
<input type="text" @input="onChange" v-model="search"
@keyup.down="onArrowDown" @keyup.up="onArrowUp" @keyup.enter="onEnter" />
<ul id="autocomplete-results" v-show="isOpen" class="autocomplete-results">
<li class="loading" v-if="isLoading">
Loading results...
</li>
<li v-else v-for="(result, i) in results" :key="i" @click="setResult(result)"
class="autocomplete-result" :class="{'is-active':i === arrowCounter}">
{{ result }}
</li>
</ul>
</div>
</script>
VUE.JS:
const Autocomplete = {
name: "autocomplete",
template: "#autocomplete",
props: {
items: {
type: Array,
required: false,
default: () => []
},
isAsync: {
type: Boolean,
required: false,
default: false
}
},
data() {
return {
isOpen: false,
results: [],
search: "",
isLoading: false,
arrowCounter: 0
};
},
methods: {
onChange() {
// Let's warn the parent that a change was made
this.$emit("input", this.search);
// Is the data given by an outside ajax request?
if (this.isAsync) {
this.isLoading = true;
} else {
// Let's search our flat array
this.filterResults();
this.isOpen = true;
}
},
filterResults() {
// first uncapitalize all the things
this.results = this.items.filter(item => {
return item.toLowerCase().indexOf(this.search.toLowerCase()) > -1;
});
},
setResult(result) {
this.search = result;
this.$emit("input", this.search);
this.isOpen = false;
},
onArrowDown(evt) {
if (this.arrowCounter < this.results.length) {
this.arrowCounter = this.arrowCounter + 1;
}
},
onArrowUp() {
if (this.arrowCounter > 0) {
this.arrowCounter = this.arrowCounter - 1;
}
},
onEnter() {
this.search = this.results[this.arrowCounter];
this.isOpen = false;
this.arrowCounter = -1;
},
handleClickOutside(evt) {
if (!this.$el.contains(evt.target)) {
this.isOpen = false;
this.arrowCounter = -1;
}
}
},
watch: {
items: function(val, oldValue) {
// actually compare them
if (val.length !== oldValue.length) {
this.results = val;
this.isLoading = false;
}
}
},
mounted() {
document.addEventListener("click", this.handleClickOutside);
},
destroyed() {
document.removeEventListener("click", this.handleClickOutside);
}
};
new Vue({
el: "#app",
name: "app",
components: {
autocomplete: Autocomplete
},
methods: {
displayVals() {
alert("test1=" + this.test1);
},
loadField() {
this.test1=this.anotherField;
}
},
data: {
test1: '',
anotherField: '',
theItems: [ 'Apple', 'Banana', 'Orange', 'Mango', 'Pear', 'Peach', 'Grape', 'Tangerine', 'Pineapple']
}
});
任何帮助将不胜感激。
答案 0 :(得分:0)
请参见固定的新fiddle。
在自定义组件上使用v-model时,您需要添加一个名为value
的属性并监视它的更改,以便它可以更新本地属性this.search
。