我有这个 Meteor 项目:https ://github.com/jfahrenkrug/code_buddy
它基本上是一个具有大文本区域和预区域的工具,可让您输入自动推送到所有连接客户端的源代码片段。
我想在代码更改时自动运行 highlightSyntax 函数,但它并没有真正起作用。
我试过query.observe,但效果不太好:语法高亮闪过一次,然后又消失了。
所以我的问题是:如何在 DOM 更新后运行代码?
我有这个 Meteor 项目:https ://github.com/jfahrenkrug/code_buddy
它基本上是一个具有大文本区域和预区域的工具,可让您输入自动推送到所有连接客户端的源代码片段。
我想在代码更改时自动运行 highlightSyntax 函数,但它并没有真正起作用。
我试过query.observe,但效果不太好:语法高亮闪过一次,然后又消失了。
所以我的问题是:如何在 DOM 更新后运行代码?
一个hacky方法是:
foo.html
<template name="mytemplate">
<div id="my-magic-div">
.. stuff goes here ..
{{add_my_special_behavior}}
</div>
</template>
foo.js
Template.mytemplate.add_my_special_behavior = function () {
Meteor.defer(function () {
// find #my-magic-div in the DOM
// do stuff to it
});
// return nothing
};
每当渲染(或重新渲染)模板时,都会调用该函数,因此您可以将其用作挂钩来执行您想要执行的任何特殊 DOM 操作。您需要使用 Meteor.defer(与 settimeout(f, 0) 做同样的事情),因为在渲染模板时,它还没有在 DOM 中。
请记住,您可以在不将模板插入 DOM 的情况下渲染模板!例如,这样做是完全合法的:
console.log(Template.mytemplate())
所以当一个模板被渲染时,并不能 100% 保证它最终会出现在 DOM 中。这取决于模板的用户。
从 Meteor 0.4.0 开始,Template.myTemplate.rendered
提供了一个回调
当 Template.myTemplate 的实例第一次呈现到 DOM 节点并放入文档时调用一次。
对于当前版本的 Meteor (1.0),我们现在可以使用 Tracker 的.afterFlush()函数。
Tracker.autorun(function(e){
var data = Router.current().data();
if(data.key !== undefined){
//the data is there but dom may not be created yet
Tracker.afterFlush(function(){
//dom is now created.
});
}
});
更新 DOM 后没有回调,但是您可以使用Tracker.flush()
.
调用 后flush()
,您知道 DOM 已更新,因此您可以执行所需的任何手动 DOM 更改。
这个问题很老了,但两年后的解决方案是集成一个操作转换库与 Meteor并在客户端使用 Ace 或 CodeMirror,它会自动突出显示语法。这具有允许人们同时编辑的额外好处。
我已经为你完成了工作:)
在Blaze Components(我是作者之一)中,您有一个 API,它在插入、移动或删除 DOM 时调用方法。您可以在此处查看如何在 DOM 更改时创建反应变量。
这种方法的缺点是它不会在 DOM 元素属性更改(如class
更改)时更改。仅当 DOM 元素本身发生更改时。这适用于大多数情况,但如果您需要第二种,我建议您简单地使用MutationObserver。在这种情况下,您也可以响应外部变化。
它似乎Template.myTemplate.rendered
无法正常工作或我不明白...
在呈现包含所有帖子的模板后,我需要内联加载 TinyMCE,所以我有:
<div id="wrapper">
{{#each posts}}
<div class="editable">{{post}}</div>
{{/each}}
</div>
Template.myPosts.rendered = function(){
console.dir($("div"));
tinymce.init({
selector: "div.editable",
inline: true,
plugins: [
"advlist autolink lists link image charmap print preview anchor",
"searchreplace visualblocks code fullscreen",
"insertdatetime media table contextmenu paste"
],
toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image"
});
}
但是,控制台只记录包含我的帖子<div id="wrapper">
的 div 而不是div。<div class="editable">
所以,似乎Template.myTemplate.rendered
回调发生在模板渲染之前,对吧?
编辑:我将Template.myTemplate.rendered
代码放在 asetTimeout()
中,一切似乎都可以正常工作,所以我肯定Template.myTemplate.rendered
会导致问题。
我刚刚发现了一个似乎运行良好的小技巧:
Template.myTemplate.onRendered(function() {
this.autorun(function() {
Meteor.setTimeout(function() {
// DOM has been updated
}, 1);
});
});
我不是 Meteor 专家,所以它可能有一些缺点,但我现在还没有找到任何东西——除了它有点脏!