使用渲染功能时,Vue组件未显示子文本节点

Tom*_*ler 5 javascript vue.js vue-component vuejs2

我正在尝试使用Vue 2进行可编辑的组件.它应该contenteditable在任何标记中使用该属性,替换正常输入.我想给它一个占位符功能,以便在用户没有提供时显示一个值,但我似乎无法让它工作.

我正在观察组件的当前值,并设置data.isEmptytrue没有用户内容时.然后该组件应显示占位符值,但目前它不显示任何内容.

如果我console.logrender方法的结果,它将显示占位符子节点被正确实例化,但由于某种原因它只是不会显示在最终的HTML上.

这是一个JSFiddle:https://jsfiddle.net/dy27fa8t/

并为喜欢它的人提供了一个嵌入式代码:

Vue.component('editable-content', {
  props: {
    initial: {
      type: String
    },
    placeholder: {
      type: String,
      required: false
    }
  },
  data() {
    return {
      value: this.initial,
      isEmpty: this.initial === ''
    }
  },
  render: function(createElement) {
    const self = this
    return createElement(
      'div', {
        attrs: {
          contenteditable: true
        },
        on: {
          input: function(event) {
            self.value = event.target.innerHTML
            self.$emit('edited', event.target.value)
          }
        }
      },
      this.isEmpty ? this.placeholder : this.value
    )
  },
  watch: {
    value(to, from) {
      this.isEmpty = to === ''
    }
  }
})

new Vue({
  el: '#app',
  components: [
    'editable-content'
  ]
})
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.0/vue.min.js"></script>

<div id="app">
  <editable-content initial="Initial value" placeholder="Placeholder" />
</div>
Run Code Online (Sandbox Code Playgroud)

Tom*_*ler 2

最后我选择了使用:empty伪类的混合 JS 和 CSS 解决方案。仅限 Vue 的解决方法似乎太笨重了,所以这感觉像是一个健康的妥协。我什至觉得没有必要再跟踪了value

值得注意的是,对于单文件组件,我可以使用作用域 CSS,因此效果更好,因为 CSS 对于组件核心功能至关重要。

Vue.component('editable-content', {
  props: {
    initial: {
      type: String
    },
    placeholder: {
      type: String,
      required: false
    }
  },
  data() {
    return {
      value: this.initial
    }
  },
  render: function(createElement) {
    const self = this
    return createElement(
      'div', {
        attrs: {
          contenteditable: true,
          'data-placeholder': this.placeholder
        },
        on: {
          input: function(event) {
            self.$emit('edited', event.target.value)
          }
        }
      },
      this.value
    )
  }
})

new Vue({
  el: '#app',
  components: [
    'editable-content'
  ]
})
Run Code Online (Sandbox Code Playgroud)
[data-placeholder]:empty::after {
  content: attr(data-placeholder);
}
Run Code Online (Sandbox Code Playgroud)
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.0/vue.min.js"></script>

<div id="app">
  <editable-content initial="Initial value" placeholder="Placeholder" />
</div>
Run Code Online (Sandbox Code Playgroud)