【问题标题】:Vue.js remove contenteditable attribute in render functionVue.js 删除渲染函数中的 contenteditable 属性
【发布时间】:2021-12-10 12:14:12
【问题描述】:

这似乎应该是一个简单的解决方案,但出了点问题......

我需要有条件地从元素中删除 contenteditable 属性:

<!-- first state -->
<div contenteditable="true"></div>

<!-- second state -->
<div></div>

我试过了:

data() {
    return {
      contenteditable: true,
      title: "Title",
    };
  },
  methods: {
    handleClick() {
      this.contenteditable = null;
      this.title = null;
    },
  },
  render(createElement) {
    const options = {
      attrs: {
        id: "ID",
        title: this.title,
        contenteditable: this.contenteditable,
        // Not working either
        //...(this.contenteditable && { contenteditable: true }),
      },
      domProps: {
        innerHTML: "<p>Test</p>",
      },
      on: {
        click: this.handleClick,
      },
    };

    return createElement("div", options);
  },

Sandbox

结果是:&lt;div contenteditable="false"&gt;&lt;/div&gt;,但我需要完全删除属性。例如title 属性按预期工作,如果它的值设置为 null,它不会呈现。我还尝试让 attrs 对象完全反应,例如:

data() {
  return {
    attrs: {
      title: 'Title',
      contenteditable: true,
    }
  }
},
methods: {
  handleClick() {
    Vue.delete(this.attrs, 'contenteditable')
    Vue.delete(this.attrs, 'title')
  },
},
render(createElement) {
    const options = {
      attrs: this.attrs,
      domProps: {
        innerHTML: "<p>Test</p>",
      },
      on: {
        click: this.handleClick,
      },
    };

    return createElement("div", options);
  },

Sandbox

...但没有运气。任何想法如何解决这个问题?

谢谢!

【问题讨论】:

    标签: vue.js vue-render-function


    【解决方案1】:

    Vue 2 在这里将contenteditable 属性视为special case,如果新的属性值为undefined,它不会删除该属性。这是 Vue 3 中的 fixed(或计划中的)。

    您可以绕过此行为并改为使用domProps 进行设置:

    domProps: {
      contentEditable: this.contenteditable ? 'true' : 'inherit'
    }
    

    这是一个演示:

    new Vue({
      el: '#app',
      data() {
        return {
          contenteditable: false
        }
      },
      render(h) {
        return h('div', [
          h('button', {
            on: {
              click: () => this.contenteditable = !this.contenteditable
            }
          }, `contenteditable: ${this.contenteditable}`),
          h('div', {
            domProps: {
              contentEditable: this.contenteditable ? 'true' : 'inherit'
            }
          }, 'Text')
        ])
      }
    })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
    
    <div id="app">
    </div>

    【讨论】:

    • 不,结果是一样的contenteditable=false。它适用于公共属性,但不适用于contenteditable
    • 我已经用演示更新了我的答案,检查 DOM 以验证属性是否存在。
    • 我查看了您的代码框,发现 Vue 在 更新 contenteditable 属性时具有特殊行为(这就是为什么我的建议仅在最初设置属性时有效;它不会在后续更新中删除)。
    • 感谢您的帮助,我已经解决了这个问题,this.$el.removeAttribute('contenteditable') 用于删除,this.contenteditable = true 将其重新设置。看起来不是 Vue.js 的方式,但contenteditable 确实是一个特殊的属性,所以,只需要记住它。
    • 你为什么要手动弄乱 DOM?我更新的答案正确地解决了问题,而无需诉诸 DOM hack。
    【解决方案2】:

    假设你的 div 如下

    <div id="editable"></div>
    

    然后您使用以下方法切换 contenteditable

    document.getElementById('editable').contentEditable = "true"
    

    document.getElementById('editable').setAttribute('contentEditable',"true")
    

    如果你希望这个 div 在开始时是 contentEditable,那么在 mounted 中添加上面的行。

    【讨论】:

      猜你喜欢
      • 2019-01-16
      • 2017-05-31
      • 1970-01-01
      • 1970-01-01
      • 2021-03-12
      • 2020-03-09
      • 1970-01-01
      • 1970-01-01
      • 2018-01-30
      相关资源
      最近更新 更多