为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Helenr 2022-06-09 11:24:55
我正在尝试为双击时可以编辑的标题创建一个组件。组件将应该使用的 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);  },如何以有效的方式确定范围?非常感谢您!
查看完整描述

1 回答

?
青春有我

TA贡献1784条经验 获得超8个赞

好吧,使用 Vue,您可能希望尽可能避免以“本机”方式创建 DOM 元素,因为您可能会遇到竞争条件,其中 Vue 不知道这些元素的存在,您可能希望在某些时候做出反应时间(在你的情况下,<span>双击)。


相反,您可以做的可能是使用 this<component>和v-bind:isprop 动态地“在”这些不同的标题之间“切换”。考虑以下示例:


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>


查看完整回答
反对 回复 2022-06-09
  • 1 回答
  • 0 关注
  • 94 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信