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

标签 javascript vue.js dom

我正在尝试为标题创建一个组件,双击标题即可对其进行编辑。 该组件将应该使用的 h 标签和标题作为 props,并且应该生成一个普通的 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>

安装的钩子(Hook)我不知道如何确定范围:

  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,您可能希望尽可能避免以“ native ”方式创建 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>

关于javascript - 如何有条件地在作用域 Vue 组件中追加元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60953539/

相关文章:

html - 什么是影根

javascript - 如何使用 JavaScript 改变多个元素的 CSS

javascript - eval 在这里如何工作或表现如何?

javascript - Meteor:从 JavaScript 内部调用/触发事件?

javascript - 具有异步属性的脚本元素仍然阻止浏览器呈现?

javascript - 在最后一张幻灯片处停止幻灯片

html - 尝试使用 v-on :blur for making disappear a context menu. ..但它不起作用

javascript - 计算属性 setter 导致 vuejs/javascript 在日期选择器焦点上使浏览器崩溃

vue.js - 如何在不添加路由到vue中的历史记录的情况下重定向到登录?

javascript - jQuery RightClick 处理程序插件