Meteor.js 中更新 DOM 后的回调
Posted
技术标签:
【中文标题】Meteor.js 中更新 DOM 后的回调【英文标题】:Callback after the DOM was updated in Meteor.js 【发布时间】:2012-04-23 23:38:47 【问题描述】:我有这个 Meteor 项目:https://github.com/jfahrenkrug/code_buddy
它基本上是一个具有大文本区域和预区域的工具,可让您输入源代码 sn-ps 自动推送到所有连接的客户端。
我想在代码更改时自动运行 highlightSyntax 函数,但它并没有真正起作用。
我试过 query.observe,但效果不太好:语法高亮显示一次,然后又消失了。
所以我的问题是:更新 DOM 后如何运行代码?
【问题讨论】:
【参考方案1】:一个 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 中。这取决于模板的用户。
【讨论】:
我实际上是通过使用 window.setTimeout 解决了它,因为 Meteor.setTimeout 在从 query.observe 调用时会通过异常来解决。 我遇到了一些时间问题。我必须使用几秒钟的非常长的超时,因为在渲染之前似乎仍然存在延迟。Template.contextualFeed.feedItems = -> Meteor.defer -> console.log "Template.contextualFeed.feedItems delayed" console.log $("abbr.timeago") # -> logs as [], with a additional delay it finds them $("abbr.timeago").timeago() Feed.find()
嗯...也许是这样,因为 Feed.find() 首先需要从 Feed 模型中获取数据?甚至可能是往返?当它获取数据时还没有真正弄清楚......
这个仍然有效,谢谢!它现在只需要写一点不同: Template.templateName.helpers( add_my_special_behavior: function() ... );
你可能想要 Meteor 的起源行为。写在这里:github.com/avital/meteor-ui-new-rendered-callback/blob/master/…【参考方案2】:
从 Meteor 0.4.0 开始,Template.myTemplate.rendered
提供了一个回调
在 Template.myTemplate 的实例被渲染到 DOM 节点并第一次放入文档时调用一次。
更多信息http://docs.meteor.com/#template_rendered
【讨论】:
这些天并没有真正起作用。见groups.google.com/forum/#!msg/meteor-talk/47Orrrz7kjg/… DOM 更新时不会调用此回调,例如当一个新元素被添加到模板中的#each
时。只有当 Template.myTemplate 的实例被渲染到 DOM 节点并第一次放入文档时,它才会被称为“once。”【参考方案3】:
对于当前版本的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.
);
);
【讨论】:
【参考方案4】:更新 DOM 后没有回调,但是您可以使用 Tracker.flush()
强制所有待处理的 DOM 更新。
致电flush()
后,您知道 DOM 已更新,因此您可以执行任何需要的手动 DOM 更改。
【讨论】:
拥有这种功能真是太好了。Template.myView.onFlush(function() )
之类的东西或特殊事件。例如,刚才我正在寻找一种方法来在每次刷新时设置元素的滚动顶部。可能吗?谢谢
@LarZuK 作为 Meteor 开发人员之一(我想我们现在都是开发人员,但我的意思是最初的 4 人团队 :)),我认为这是个好主意,而且我经常想要这样的东西,但我不确定它应该如何工作。如果我在控制台中输入console.log(Template.myView())
,你有什么建议吗?在这种情况下永远不要调用该函数?
另一种情况:假设我使用var frag = Meteor.ui.render(Template.myView)
将模板渲染到DOM 节点,然后等待几秒钟,然后才将frag
实际插入到页面中。你认为新的回调应该在模板被渲染到 DOM 节点时触发,还是在那些 DOM 节点被放到屏幕上时触发? (前者容易,后者真的很难……)【参考方案5】:
这个问题很老了,但两年后的解决方案是集成operational transformation library with Meteor 并在客户端使用 Ace 或 CodeMirror,它会自动突出显示语法。这具有允许人们同时进行编辑的额外好处。
我已经为你完成了工作:)
【讨论】:
【参考方案6】:在Blaze Components(我是作者之一)中,您有一个 API,它在插入、移动或删除 DOM 时调用方法。你可以see here如何在 DOM 发生变化时制作一个响应式变量。
这种方法的缺点是它不会在 DOM 元素属性更改时发生更改(例如 class
更改)。仅当 DOM 元素本身发生更改时。这适用于大多数情况,但如果您需要第二种,我建议您只需使用MutationObserver。在这种情况下,您也可以响应外部变化。
【讨论】:
【参考方案7】:似乎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 class="editable">
div,其中包含我的帖子。所以,似乎Template.myTemplate.rendered
回调发生在模板渲染之前,对吧?
编辑:我将Template.myTemplate.rendered
代码放在setTimeout()
中,似乎一切正常,所以我确信Template.myTemplate.rendered
会导致问题。
【讨论】:
【参考方案8】:我刚刚发现了一个看起来运行良好的小技巧:
Template.myTemplate.onRendered(function()
this.autorun(function()
Meteor.setTimeout(function()
// DOM has been updated
, 1);
);
);
我不是 Meteor 专家,所以它可能有一些缺点,但我目前还没有发现任何缺点 - 除了它有点脏!
【讨论】:
【参考方案9】:我想你可能想将回调传递给
Meteor.startup(callback)
见http://docs.meteor.com/#meteor_startup
【讨论】:
谢谢,但这并不是要知道 DOM 何时在页面加载时准备就绪。由于来自服务器的数据更改,我需要知道 DOM 何时完成更新。以上是关于Meteor.js 中更新 DOM 后的回调的主要内容,如果未能解决你的问题,请参考以下文章