可编辑的HTML内容:限制编辑操作并复制更新的文本

时间:2019-06-13 22:59:27

标签: javascript vuejs2 contenteditable dom-events keyevent

我有一个contenteditable p元素。我想将可能的编辑操作限制为插入和删除逗号。我也想将更新的内容复制到另一个div。这两个目标似乎很难结合在一起:

  • 如果按下了除退格键或逗号以外的任何其他键,似乎我必须监听keydown事件以防止使用event.preventDefault()更改文本。当我收听keyup时,event.preventDefault()执行得太迟了,无论按下哪个键,内容都会更新。

  • 但是我可能需要等待keyup更新段落的内容,以便我可以复制文本。如果我使用keydown,则会得到原始文本。

我正在使用Vue。在HTML代码中,@keydown='evaluate($event)'只是附加了一个侦听器,并允许使用来访问事件变量。

编辑:这是我的原始代码,另请参见下面的代码段(无Vue)。

HTML

<p @keydown='evaluate($event)' id='text' contenteditable>
    Some text
</p>

JS

evaluate: function(storeResponse = true, event) {

    // Stop if any key except comma or backspace was pressed. Only works well with keydown.
    if (! [',', 'Backspace'].includes (event.key)) {
        event.preventDefault();
        return;
    }

    // Otherwise, copy the updated content. Only works well with keyup.
    let textContent = document.getElementById('text').textContent;

    // Paste updated content to another p
    document.getElementById('original-text').innerText = textContent;
}

document.getElementById('text').addEventListener('keydown', evaluate);

function evaluate() {
  // Stop if any key except comma or backspace was pressed.
  // Only works well with keydown.
  if (![',', 'Backspace'].includes(event.key)) {
    event.preventDefault();
    return;
  }

  // Otherwise, copy the updated content. Only works well with keyup.
  let textContent = document.getElementById('text').textContent;

  // I need to paste the updated content to another div, but just log it for this snippet
  console.log(textContent);
}
<p @keydown='evaluate' id='text' contenteditable>
  Some text
</p>

是否有一种优雅的方法来限制可能的编辑操作,并获取更新的文本?

2 个答案:

答案 0 :(得分:0)

这是在单个事件中执行此操作的一种方法:

new Vue({
  el: '#app',

  data: () => ({
    content: ''
  }),

  methods: {
    evaluate(event) {
      // Stop if any key except comma or backspace was pressed. Only works well with keydown.
      if (![',', 'Backspace'].includes(event.key)) {
        event.preventDefault();
        return;
      }

      // Otherwise, copy the updated content.
      const el = event.target;

      // Paste updated content to another p
      this.content = el.textContent;
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <p @keydown='evaluate' contenteditable>
    Start typing...
  </p>

  <br />
 
  <p v-text="content">
    Updated text goes here.
  </p>
</div>

快速提示:

传递不带任何参数的方法名称并括住括号将自动将关联的Event数据对象传递给幕后方法,如果执行了键盘事件,则KeyboardEvent数据对象将传递给方法。

因此,以下几行实际上是等效的:

<p @keydown='evaluate($event)'></p>

<!-- Or -->

<p @keydown='evaluate'></p>

答案 1 :(得分:0)

这是根据Yom S.的答案编写的摘要。

new Vue({
  el: '#app',

  data: () => ({
    content: ''
  }),

  methods: {
    /**
     * Checks whether the keypress should be processed.
     */
    checkKey: function() {
        // Users may only navigate or enter/delete commas
        let permittedKeys = [
            ',',
            'Backspace',
            'ArrowLeft',
            'ArrowRight',
            'ArrowDown',
            'ArrowUp'
        ];

        if (! permittedKeys.includes (event.key)) {
          event.preventDefault();
        }
    },

    evaluate(event) {
      // Stop if any key except comma or backspace was pressed. Only works well with keydown.
      if (![',', 'Backspace'].includes(event.key)) {
        event.preventDefault();
        return;
      }

      // Otherwise, copy the updated content.
      const el = event.target;

      // Paste updated content to another p
      this.content = el.textContent;
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <p @keydown='checkKey' @keyup='evaluate' contenteditable>
    Start typing...
  </p>

  <br />
 
  <p v-text="content">
    Updated text goes here.
  </p>
</div>

运行该代码段时,您会看到仍然可以删除除逗号以外的其他字符。 AFAIK,不可能从关键事件中获取已删除的字符,因此唯一的机会似乎是撤消此类删除。为此,我从编辑后的文本和以前的版本中都删除了所有逗号。如果这些字符串不同,则将先前版本复制到contenteditable元素。