我正在尝试为双击时可以编辑的标题创建一个组件。组件将应该使用的h标记和标题作为道具,并应该生成一个普通的h标记,双击后该标记将变成一个输入字段。如果页面上只有一个标题,这已经起作用了,但是一旦一个页面上使用了多个组件,就会因为组件的作用域不正确而中断。但我不知道怎么做。这是代码:
<template>
<div class="edit-on-click">
<input
:class="sizeClass"
type="text"
v-if="edit"
v-model="editedTitle"
@blur="finishEdit"
@keyup.enter="finishEdit"
v-focus="true"
/>
<span v-show="!edit" @dblclick.prevent="edit = true"></span>
</div>
</template>
安装的钩子我不知道如何瞄准:
mounted() {
let node = document.createElement(this.size); // Takes h-tag (h1, h2 etc.)
let titleText = document.createTextNode(this.finalTitle); // Takes title
node.appendChild(titleText);
node.classList.add("editable-title");
// This breaks the code once there are multiple components in the document
document.getElementsByTagName("span")[0].appendChild(node);
},
我如何才能有效地确定范围?提前非常感谢!
好吧,使用Vue,您可能希望尽可能避免以"原生"方式创建DOM元素,因为您可能会遇到竞争条件,Vue不知道这些元素的存在,而您可能希望这些元素在某个时间点(在您的情况下,<span>
双击(是被动的。
相反,您可以使用这个<component>
和v-bind:is
道具动态地在这些不同的标题之间"切换"。考虑以下示例:
Vue.component('EditableHeading', {
template: '#editable-heading',
props: {
size: {
type: String,
default: 'h1'
},
value: {
type: String,
required: true
}
},
data() {
return {
editing: false
}
},
methods: {
confirm(e) {
this.$emit('input', e.target.value);
this.close();
},
start() {
this.editing = true;
this.$nextTick(() => {
this.$el.querySelector('input[type="text"]').select();
});
},
close() {
this.editing = false;
}
}
})
new Vue({
el: '#app',
data: () => ({
titleList: [],
text: 'New Title',
size: 'h3'
}),
methods: {
addNewTitle() {
this.titleList.push({
text: this.text,
size: this.size
});
}
}
})
.edit-on-click {
user-select: none;
}
.heading-size {
margin-top: 1rem;
width: 24px;
}
p.info {
background-color: beige;
border: 1px solid orange;
color: brown;
padding: 4px 5px;
margin-top: 2rem;
}
<script src="https://vuejs.org/js/vue.min.js"></script>
<div id="app">
<editable-heading
v-for="(title, index) of titleList" :key="index"
v-model="title.text"
:size="title.size">
</editable-heading>
<div>
<label>
Heading size:
<input v-model="size" class="heading-size" />
</label>
</div>
<div>
<label>
Title:
<input v-model="text" />
</label>
</div>
<div>
<button @click="addNewTitle()">Add new title</button>
</div>
<p class="info">
[double-click]: Edit <br />
[enter]: Confirm <br />
[esc/mouseleave]: Cancel
</p>
</div>
<script id="editable-heading" type="text/x-template">
<div class="edit-on-click">
<input
type="text"
v-if="editing"
:value="value"
@blur="close"
@keydown.enter="confirm"
@keydown.esc="close" />
<component :is="size" v-else @dblclick="start">{{value}}</component>
</div>
</script>