在Meteor.js中更新DOM之后进行callback

我有这个Meteor项目: https : //github.com/jfahrenkrug/code_buddy

它基本上是一个带有大文本区域和预先区域的工具,可以让您input源代码片段,并自动将其推送到所有连接的客户端。

我想在代码更改时自动运行highlightSyntax函数,但实际上并不成功。

我已经尝试了query.observe,但那不太好:语法突出显示闪烁一次,然后再次消失。

所以我的问题是:如何在DOM更新后运行代码?

一个很好的方法是:

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提供了一个callback

当Template.myTemplate的一个实例被渲染成DOM节点并且被第一次放入文档时被调用一次

有关详情,请访问http://docs.meteor.com/#template_rendered

至于目前版本的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更新后没有callback,但是可以使用Tracker.flush()强制执行所有挂起的DOM更新。

在你调用flush() ,你知道DOM已经被更新了,所以你可以执行你需要的任何手动DOM更改。

这个问题是相当古老的,但是为期两年的解决scheme将是将操作转换库与Meteor集成,并在客户端上使用Ace或CodeMirror,从而自动执行语法高亮显示。 这有另外的好处,允许人们在同一时间编辑。

我已经为你做了这个工作:)

在Blaze组件中 (我是作者之一),你有一个API,在插入,移动或移除DOM时调用方法。 你可以在这里看到当DOM改变时如何做一个反应variables。

这种方法的缺点是,当DOM元素属性发生变化时(如class更改),它不会改变。 只有当DOM元素本身被改变时。 这适用于大多数情况,但如果您需要第二个,我build议您只使用MutationObserver 。 在这种情况下,您将能够响应外部变化。

看来Template.myTemplate.rendered无法正常工作,或者我不明白…

我需要在所有post被渲染的模板之后加载TinyMCE,所以我有:

– 一个模板

 <div id="wrapper"> {{#each posts}} <div class="editable">{{post}}</div> {{/each}} </div> 

– 和一个function

 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" }); 

}

然而,控制台只logging<div id="wrapper">而不是<div class="editable"> div,其中包含我的post。 所以,看起来Template.myTemplate.renderedcallback发生在模板呈现之前,对吗?

编辑:我把Template.myTemplate.rendered代码里面setTimeout()和所有似乎工作,所以我敢肯定Template.myTemplate.rendered会导致问题。

我刚刚发现了一个似乎工作得很好的小黑客:

 Template.myTemplate.onRendered(function() { this.autorun(function() { Meteor.setTimeout(function() { // DOM has been updated }, 1); }); }); 

我不是meteor专家,所以可能有一些缺点,但我现在还没有find – 除了有点脏!

我想你可能想要传递一个callback

 Meteor.startup(callback) 

请参阅http://docs.meteor.com/#meteor_startup