我正在尝试制作一个 Meteor 应用程序,允许多人同时编辑文本正文(例如 Google Docs/Drive)。
我认为为了做到这一点,我需要一个模板,它只显示数据库中当前的文本,然后每当修改文本时,它都需要更新数据库中的文本。
我能够在下面的最小复制中从我的完整应用程序中重现相同的问题(设计为由单个用户而不是多个用户使用,因此从使用 Mongo Collection 切换到使用 session 。)
<body>
{{> hello}}
</body>
<template name="hello">
<pre contentEditable="true">{{text}}</pre>
</template>
(如果我使用 div
而不是 pre
,也会出现完全相同的问题。)
if (Meteor.isClient) {
Session.setDefault('text', "Edit me!");
Template.hello.helpers({
text: function () {
return Session.get('text');
}
});
Template.hello.events({
"input pre": function (event) {
Session.set('text', $(event.target).text());
}
});
}
尝试在应用程序中输入一些内容,您很快就会发现错误:每次击键时,它都会获取所有现有文本并将其附加到您键入的内容中(因此,每次击键时,它都会复制所有现有文本)文本)。这是真正奇怪的部分:这种行为并不总是立即开始......事实上,我还没有找到任何特别可靠的方法来重现它。一旦它复制了一次文本,它就会在每次击键时可靠地一次又一次地重复该文本,直到您刷新页面。刷新页面后,有时该错误会在您下一次击键时再次出现,有时可能需要大约 20 次击键才会出现。
我已在 Safari 8(OS X 和 iOS)、Chrome(OS X 和 Windows)和 Firefox(仅限 OS X)上进行了测试,每个浏览器中都会出现此问题。
如果您还无法重现它,请尝试突出显示所有文本,删除它,然后输入。也尝试开始一个新行。我发现这些操作似乎更有可能引发文本重复,但即使这些操作也不一定会引发问题。
我的问题是:
- 为什么会出现此错误?
- 如何阻止这种情况发生?
如果你想直接看到问题,而不必运行 meteor 服务器(尽管我已经给了你所有的代码......)我把它扔了 here .
最佳答案
这是一个已知问题,详细讨论 here 。我正在使用this solution (来自 Swavek)并且效果很好。
简单地说,当两个人同时操作相同的 DOM 元素时就会出现问题:
- meteor ,但具有反应性
- 负责管理 contenteditable div 内部的浏览器代码。
解决方案是告诉 Meteor 不要操作 contenteditable div 的内部,而是刷新整个 div。你这样做:
<body>
{{> hello}}
</body>
<template name="hello">
{{{getContenteditableDiv}}} <!-- Beware: triple brackets! -->
</template>
Template.hello.helpers({
getContenteditableDiv: function() {
return '<pre contentEditable="true">' + Session.get('text') + '</pre>';
}
});
关于javascript - Meteor 中的文本复制?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29292054/