我想复制一个通用的项目列表重命名功能,这里有一个图层列表,如果双击一个图层,它将把该图层项目更改为输入,并且该输入也将自动选中其文本。
在我的示例中,我无法通过其focus()
ref
来 <div v-for="(item, i) in items">
<div @click="changeToInput(i)" v-if="!item.input">{{item.name}}</div>
<input ref="input" v-model="item.name" onfocus="select()" v-else>
</div>
,因为它表示未定义。仅当将元素更改为输入后,再次单击该元素时,此方法才有效。如何设置自动对焦?
changeToInput(i) {
this.items[i].input = true;
//this.$refs.input.focus()
}
requests.post(api_url, files={'image': open(img_path, 'rb')})
下面是完整的示例:https://codesandbox.io/s/reverent-khayyam-2x8mp?file=/src/App.vue:481-573
答案 0 :(得分:2)
两种解决方案:
第一个:使用v-if
+ this.$nextTick
:
v-if
将在绑定表达式为true / false时插入/销毁组件,因此在当前循环中,input
尚未进入Dom树。您必须使用nextTick
等待下一个周期才能获取Input的Dom元素。并且this.$refs.input
将是一个基于多少v-if=true
的数组,因此您必须过滤掉this.items
以找出正确的索引(这就是为什么我使用Array.slice和Array.filter)。
已更新:this.$refs.input1
的元素顺序是创建VNode的顺序。例如:单击input2-> input3-> input1,this.$refs.input1
的顺序为[2,3,1],而不是[1,2,3]。
第二个:使用v-show
+ this.$nextTick
:
这将使事情变得更容易,因为v-show
仅更新Dom元素的css样式,而不会从VNode树中添加/删除组件实例(Vnode)。因此this.$refs.input
将始终等于this.items.length
。
new Vue ({
el:'#app',
data() {
return {
items1: [
{ name: "Joe", input: false },
{ name: "Sarah", input: false },
{ name: "Jeff", input: false }
],
items2: [
{ name: "Joe", input: false },
{ name: "Sarah", input: false },
{ name: "Jeff", input: false }
],
refSort: {}
};
},
methods: {
changeToInput1(i) {
this.items1[i].input = true;
let refCount = (this.$refs.input1 && this.$refs.input1.length) || 0
refCount < this.items1.length && (this.refSort[i] = refCount)
this.$nextTick(() => {
// the purpose uses this.refSort is record the order of this.$refs.input (Its order is same as the creating order of Ref), you can uncomment below line to see the root cause
//console.log(this.$refs.input1[0] && this.$refs.input1[0].value, this.$refs.input1[1] && this.$refs.input1[1].value, this.$refs.input1[2] && this.$refs.input1[2].value)
this.$refs.input1[this.refSort[i]].focus()
})
},
changeToInput2(i) {
this.items2[i].input = true;
this.$nextTick(() => this.$refs.input2[i].focus())
}
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
<div id="app">
<h3>Uses v-if: <p>{{items1}}</p></h3>
<div v-for="(item, i) in items1">
<div @click="changeToInput1(i)" v-if="!item.input">{{item.name}}</div>
<input ref="input1" v-model="item.name" onfocus="select()" v-else>
</div>
<h3>Uses v-show: <p>{{items2}}</p></h3>
<div v-for="(item, i) in items2">
<div @click="changeToInput2(i)" v-show="!item.input">{{item.name}}</div>
<input ref="input2" v-model="item.name" onfocus="select()" v-show="item.input">
</div>
</div>