如何有条件地在作用域 Vue 组件中附加元素?

我正在尝试为双击时可以编辑的标题创建一个组件。组件将应该使用的 h-tag 和 title 作为 props,并且应该生成一个普通的 h-tag,一旦双击它就会变成一个输入字段。如果页面上只有一个标题,这已经有效,但是一旦在一页上使用了多个组件,它就会中断,因为组件的范围不正确。但我不知道怎么做。这是代码:


<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);

  },

如何以有效的方式确定范围?非常感谢您!


Helenr
浏览 95回答 1
1回答

青春有我

好吧,使用 Vue,您可能希望尽可能避免以“本机”方式创建 DOM 元素,因为您可能会遇到竞争条件,其中 Vue 不知道这些元素的存在,您可能希望在某些时候做出反应时间(在你的情况下,<span>双击)。相反,您可以做的可能是使用 this<component>和v-bind:isprop 动态地“在”这些不同的标题之间“切换”。考虑以下示例:Vue.component('EditableHeading', {&nbsp; template: '#editable-heading',&nbsp; props: {&nbsp; &nbsp; size: {&nbsp; &nbsp; &nbsp; type: String,&nbsp; &nbsp; &nbsp; default: 'h1'&nbsp; &nbsp; },&nbsp; &nbsp; value: {&nbsp; &nbsp; &nbsp; type: String,&nbsp; &nbsp; &nbsp; required: true&nbsp; &nbsp; }&nbsp; },&nbsp; data() {&nbsp; &nbsp; return {&nbsp; &nbsp; &nbsp; editing: false&nbsp; &nbsp; }&nbsp; },&nbsp; methods: {&nbsp; &nbsp; confirm(e) {&nbsp; &nbsp; &nbsp; this.$emit('input', e.target.value);&nbsp; &nbsp; &nbsp; this.close();&nbsp; &nbsp; },&nbsp; &nbsp; start() {&nbsp; &nbsp; &nbsp; this.editing = true;&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; this.$nextTick(() => {&nbsp; &nbsp; &nbsp; &nbsp; this.$el.querySelector('input[type="text"]').select();&nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; },&nbsp; &nbsp; close() {&nbsp; &nbsp; &nbsp; this.editing = false;&nbsp; &nbsp; }&nbsp; }})new Vue({&nbsp; el: '#app',&nbsp; data: () => ({&nbsp; &nbsp; titleList: [],&nbsp; &nbsp; text: 'New Title',&nbsp; &nbsp; size: 'h3'&nbsp; }),&nbsp; methods: {&nbsp; &nbsp; addNewTitle() {&nbsp; &nbsp; &nbsp; this.titleList.push({&nbsp; &nbsp; &nbsp; &nbsp; text: this.text,&nbsp; &nbsp; &nbsp; &nbsp; size: this.size&nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; }&nbsp; }}).edit-on-click {&nbsp; user-select: none;}.heading-size {&nbsp; margin-top: 1rem;&nbsp; width: 24px;}p.info {&nbsp; background-color: beige;&nbsp; border: 1px solid orange;&nbsp; color: brown;&nbsp; padding: 4px 5px;&nbsp; margin-top: 2rem;}<script src="https://vuejs.org/js/vue.min.js"></script><div id="app">&nbsp; <editable-heading&nbsp;&nbsp; &nbsp; v-for="(title, index) of titleList" :key="index"&nbsp;&nbsp; &nbsp; v-model="title.text"&nbsp;&nbsp; &nbsp; :size="title.size">&nbsp; </editable-heading>&nbsp; <div>&nbsp; &nbsp; <label>&nbsp; &nbsp; &nbsp; Heading size:&nbsp;&nbsp; &nbsp; &nbsp; <input v-model="size" class="heading-size" />&nbsp; &nbsp; </label>&nbsp; </div>&nbsp; <div>&nbsp; &nbsp; <label>&nbsp; &nbsp; &nbsp; Title:&nbsp;&nbsp; &nbsp; &nbsp; <input v-model="text" />&nbsp; &nbsp; </label>&nbsp; </div>&nbsp; <div>&nbsp; &nbsp; <button @click="addNewTitle()">Add new title</button>&nbsp; </div>&nbsp; <p class="info">&nbsp; &nbsp; [double-click]: Edit <br />&nbsp; &nbsp; [enter]: Confirm <br />&nbsp; &nbsp; [esc/mouseleave]: Cancel&nbsp; </p></div><script id="editable-heading" type="text/x-template">&nbsp; <div class="edit-on-click">&nbsp; &nbsp; <input&nbsp;&nbsp; &nbsp; &nbsp; type="text"&nbsp;&nbsp; &nbsp; &nbsp; v-if="editing"&nbsp;&nbsp; &nbsp; &nbsp; :value="value"&nbsp;&nbsp; &nbsp; &nbsp; @blur="close"&nbsp;&nbsp; &nbsp; &nbsp; @keydown.enter="confirm"&nbsp;&nbsp; &nbsp; &nbsp; @keydown.esc="close" />&nbsp; &nbsp; <component :is="size" v-else @dblclick="start">{{value}}</component>&nbsp; </div></script>
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript