【问题标题】:How can DOM manipulation like wrapping text in a paragraph element be achieved using only Vue.js?如何仅使用 Vue.js 来实现 DOM 操作,例如在段落元素中包装文本?
【发布时间】:2020-04-27 16:01:16
【问题描述】:

我有一个 Vue 组件,它有一个 contenteditable div 允许用户输入消息。当用户第一次尝试创建消息时,我使用 jQuery 将文本包装在 <p> 标记中。我无法理解如何单独使用 Vue.js 来实现...

Vue.js 组件

<template>
   <div id="Message" contenteditable="true" @focus="formatMessage" @keydown="formatMessage" @keyup="formatMessage" @keypress="formatMessage">

   </div>
</template>

<script>
  import $ from 'jquery'

  formatMessage: function(event) {
    if ($("#Message > p").length === 0) {            // if no <p> element when user interacts with div
      $("#Message").contents().eq(0).wrap("<p />");  // then wrap a <p> tag around the first child content
  }

}

是否可以仅使用 Vue.js 来执行此操作,这样我就不必加载 jQuery 库来进行简单的 DOM 操作(这可能会导致 Vue 的虚拟 DOM 与 jQuery 的更改不同步)?

formatMessage()之前:

<div id="Message" contenteditable="true">
I started typing here  
</div>

formatMessage()之后:

<div id="Message" contenteditable="true">
 <p>I started typing here</p>
</div>

尝试使用 Vue 的虚拟 DOM 是否可能/更好?我可以以某种方式使用createElement 创建一个新的p 标签,然后用用户输入的内容更新其内容吗?也许这不是 Virtual DOM 的工作方式,我不确定。

【问题讨论】:

  • 发布一些相同的标记,也像调用formatMessage之前的HTML标记以及之后的样子?另外,它是否会将每个文本都包含在 #Message 中?
  • @palaѕн 我只是在代码前后添加了一些。这有帮助吗?它会立即发生,因此只要您 keydown 文本被包裹在 &lt;p&gt;
  • @palash 虽然它与 jQuery 完美配合。一旦&lt;p&gt;在keydown后渲染,所有字符都输入到&lt;p&gt;标签中

标签: javascript jquery vue.js


【解决方案1】:

如果你想实现类似的东西,你可以使用v-if 并稍微复制代码

<template>
   <div v-if="shouldWrap === false" contenteditable="true" @focus="formatMessage" @keydown="formatMessage" @keyup="formatMessage" @keypress="formatMessage">

   </div>
   <p v-else>
      <div contenteditable="true" @focus="formatMessage" @keydown="formatMessage" @keyup="formatMessage" @keypress="formatMessage">
     </div>
   </p>
</template>
<script>
export default {
 data () {
   return {
    shouldWrap: false
   }
 },
 methods: {
   formatMessage() {
    this.shouldWrap = true
   }
 }
}
</script>

但可能尝试匹配 p 的样式也应该可以。

【讨论】:

  • 但是您将整个 &lt;div&gt; 包装在 &lt;p&gt; 元素中。它只有 &lt;div&gt; 的内容需要包装在 &lt;p&gt;
  • 在Vue中使用createElement方法可以做到吗?
  • 应该的。所有 javascript 相关的 DOM 方法都在 vue 中可用。
【解决方案2】:

不要在 VUE 中使用类似 JQuery 的 DOM 操作,VUE 是数据驱动框架,你需要在组件中存储一些数据来触发布局,例如

<template>
   <div contenteditable="true" @focus="formatMessage" @keydown="formatMessage" @keyup="formatMessage" @keypress="formatMessage">
     <!-- wrap 'p' tag, if 'shouldWrap'-->
     <p v-if="shouldWrap">{{content}}</p>
     <!-- without wrap-->
     <template v-else>{{content}}</template>
   </div>

</template>
<script>
export default {
 data () {
   return {
    shouldWrap: false,
    content:'' // text, you want to display inside div
   }
 },
 methods: {
   formatMessage() {
    this.shouldWrap = true
   }
 }
}
</script>

【讨论】:

  • 很好的例子。但content:'' 变量并非来自任何数据源。它是用户当时正在输入的文本。如何将用户输入的内容绑定到content 变量?
  • @volumeone 我假设,如果用户输入消息你需要一些参数来绑定输入
  • 我已经使用纯 Javascript 解决了它。 Vue.js 无法做到这一点,因为“当 DOM 在 Vue 的控制之外被修改时(可以这么说),它无法检测到更改并跟上它们。换句话说:当使用 contenteditable 时,你不应该将 Vue 绑定放在里面,因为您允许用户在 Vue 上下文之外修改 HTML。值得注意的是,contenteditable 不是由 Vue 默认处理的,因为它非常复杂"
猜你喜欢
  • 1970-01-01
  • 2019-04-19
  • 2019-11-17
  • 2017-07-30
  • 2017-05-04
  • 2021-09-13
  • 2021-04-15
  • 2011-09-20
  • 2021-12-13
相关资源
最近更新 更多