Vue.js 删除渲染函数中的 contenteditable 属性

Posted

技术标签:

【中文标题】Vue.js 删除渲染函数中的 contenteditable 属性【英文标题】:Vue.js remove contenteditable attribute in render function 【发布时间】: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

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

谢谢!

【问题讨论】:

【参考方案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 中添加上面的行。

【讨论】:

以上是关于Vue.js 删除渲染函数中的 contenteditable 属性的主要内容,如果未能解决你的问题,请参考以下文章

vue中的条件渲染

在组件Vue.js中渲染组件

记录-Vue.js模板编译过程揭秘:从模板字符串到渲染函数

VUE.JS 渲染函数

渲染组件后,Vue.js将单击事件绑定到v-html中的锚元素[重复]

Vue JS:使用基于提供的索引的 splice() 方法删除数组中动态渲染的组件,不起作用