【问题标题】:Vue: Use data to control DOM (but v-for, v-if, v-model, and v-show don't suffice)Vue:使用数据控制 DOM(但 v-for、v-if、v-model 和 v-show 还不够)
【发布时间】:2019-12-20 20:13:22
【问题描述】:

我以前使用过 Vue,我知道如何使用 v-for 来渲染一系列元素,v-ifv-show 有条件地显示元素,以及 v-model 来控制例如段落的内容.

但现在我需要更好地控制 DOM:

  • 我的组件的data 中有一个ranges 对象,并且我的模板中有一个text div(text 可能是一个id 和/或ref 属性)。
  • 对于每个范围,我想突出显示 text div 内的特定文本部分,而不是基于字符串或正则表达式匹配,而是基于文本索引(我之前使用 Rangy 进行过此操作)。
  • 我还想在每个范围内插入一些工具提示或弹出框,例如 v-tooltip [可选]。

例如,当我的范围对象包含{ start: 0, end: 3 } 时,我想突出显示<div ref='text'>The cat chases a dog.</div>inside 中的

在这种情况下,操作 DOM 对我不起作用,因为 (i) 将更新 data 导致 Vue 再次更新 DOM,删除以前的编辑和 (ii) 随后插入的元素类似于 document.createElement('my-component'); Vue 甚至不将其识别为组件。

有什么方法可以利用 Vue 的数据驱动方法来做我需要的事情吗?

【问题讨论】:

  • 我没有使用 Vue 的原生引擎创建文本高亮的经验,但是可以在某个生命周期挂钩下重新执行非 Vue 相关的算法。只需在updated() 之类的东西中运行您的突出显示方法,确保将其包装在this.$nextTick(func) 中。这样做后,即使 Vue 在组件更改其状态时替换了所有手动 DOM 更新,您也可以重新应用手动 DOM 更新。
  • 除非你的组件经常更新(也许它是一个间隔更新的组件)并且你的手动 DOM 更新非常繁重,否则你不应该有性能问题。

标签: javascript vue.js dom vuejs2


【解决方案1】:

当然,Vue 不支持附加 DOM, 尝试这个。工作正常:

通过拆分文本。我们得到一个长度为 2 的数组

  1. 第一部分数组l[0]是突出显示文本之前的文本
  2. 第二部分数组l[1]是高亮文本之后的文本

然后我们合并:l[0] + <p style="/* some style */"> + hightlighted_text + </p> + l[1]

然后我们使用v-html将HTML绑定到div

您需要进行一些验证,例如:如果突出显示的文本存在在整个文本中。如果没有,这将导致在整个文本中添加新文本

var app = new Vue({
    el: '#app',
    data: {
        words: '',
        text: 'hello world im vue.js',
        hightlighted: ''
    },
    methods: {
        highlightMe() {
            var l = this.text.split(this.words);
            console.log(l);
            this.hightlighted = l[0] + '<p style="background-color: red; display: inline">' + this.words + '</p>' + l[1];
        }
    },
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.4/vue.js"></script>

<div id="app">
<label>text to be highlighted :</label><br />
<input type="text" class="form-control" v-model="words"><br/>
<button @click="highlightMe">hightLight ` {{ words }} `</button>
<div>
  {{text}}
</div>
<div v-html="hightlighted"></div>
</div>

【讨论】:

  • 谢谢!我不能使用你的大部分答案,因为突出显示是由 Rangy 完成的,但似乎我可以让 Rangy 完成它的工作,然后复制修改后的元素。在我的例子中,带有v-html 的元素有一个ID,我们也称它为highlighted,然后我做this.highlighted = document.getElementById('highlighted');
  • 但是有一个问题:我真的很想将事件处理程序 (@click='doSomething') 绑定到 HTML。这不起作用,因为 v-html 插入的 HTML 未编译...有没有办法这样做?
  • 创建一个组件,然后将突出显示的文本绑定到该组件。 - 像 - 然后你需要将第一部分和第二部分绑定到 Vue 数据 - 在 #app 中使用它们并突出显示文本。 - 然后您可以将您的活动包含在 new-comp 中。对不起,我现在不能写代码,因为我在外面,我用手机。
猜你喜欢
  • 2020-03-31
  • 1970-01-01
  • 2020-07-18
  • 2016-11-12
  • 1970-01-01
  • 2020-12-20
  • 2019-05-31
  • 2019-04-30
  • 2022-09-30
相关资源
最近更新 更多