【问题标题】:Meteor call JS after DOM changed by reactive template data响应式模板数据更改 DOM 后 Meteor 调用 JS
【发布时间】:2015-03-20 03:00:29
【问题描述】:

我正在尝试在一个更大的项目中想办法解决这个问题,但我把这个小例子放在一起希望找到解决方案..

通过创建一个新的流星项目(使用流星 1.0.3.1)并添加 mizzao:bootstrap-3 并使用以下文件来组合示例:

test.html

<head>
  <title>test</title>
</head>

<body>
  <div class="container-fluid">
    <div class="row">
      {{> example}}
    </div>
    {{> controls}}
  </div>
</body>

<template name="example">
  <div class="col-xs-{{zoom}}">
    <div class="panel panel-default">
      <div class="panel-heading">
        <h3 class="panel-title"><span data-toggle="tooltip" data-placement="auto" title="Some text that will appear in the tooltip (which should be centered above or below this span) when hovering over the this span">Text that can spill out</span></h3>
      </div>
      <div class="panel-body">
        <p>Foo</p>
      </div>
    </div>
  </div>
</template>

<template name="controls">
  <button id="in">+</button>
  <button id="out">-</button>
</template>

test.css

.panel-title > span {
  display: inline-block;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.panel-title div.tooltip {
  white-space: initial;
}

test.js

if (Meteor.isClient) {
  var minZoom = 1;
  var maxZoom = 4;
  Session.setDefault('zoom', 4);

  Template.example.helpers({
    zoom: function () {
      return Session.get('zoom');
    }
  });

  Template.controls.events({
    'click button': function(event) {
      switch(event.currentTarget.id) {
        case 'in':
          if (Session.get('zoom') < maxZoom)
            Session.set('zoom', Session.get('zoom') + 1);
          break;
        case 'out':
          if (Session.get('zoom') > minZoom)
            Session.set('zoom', Session.get('zoom') - 1);
          break;
      }
    }
  })

  test = function() {
    $('.panel-heading').each(function(index) {
      var h3 = $(this).find('h3');
      var span = $(this).find('span');
      span.width('initial');
      if (span.width() > h3.width()) {
        span.width('100%');
      }
    });
    $('[data-toggle="tooltip"]').tooltip();
  }

  Template.example.rendered = function() {
    test();
  }
}

希望很清楚(ish)我想要实现的是跨度(在悬停时切换到工具提示)设置为与 h3 相同的宽度,否则跨度将超过 h3 的宽度 -或者如果 h3 更大,则跨度设置为默认值(内联/初始宽度)。这样做的原因是当初始化工具提示时,工具提示应该出现在跨度文本上方(或下方)的中心。 渲染模板时对 test() 的调用按预期工作(您可以更改“缩放”会话的默认值以在首次加载页面时更改面板的宽度 - 我一直在使用 1 和 4测试。 但是,当单击 + 或 - 按钮时发生响应式会话变量“缩放”更改导致 DOM 更新时,我需要调用 test()。发生这种情况时,面板类 col-md-# 会发生变化,其中 # 是缩放会话变量的值。

总而言之,DOM 发生了变化,但这并不是对我直接进行的 JavaScript 调用的响应,也不是由于订阅的数据发生了变化,所以我不相信我可以使用 Tracker.afterFlush 回调. 由于缩放助手必须在 DOM 更新之前返回,我看不到任何特定事件触发的调用“test()”的方法,并且在单击按钮时添加一些东西会为时过早有人有任何想法吗?

此外,根据我的阅读,Mutation Observers 还没有得到广泛支持,所以这可能不是一个选项。

谢谢

【问题讨论】:

  • 你有没有找到一个好的解决方案?将 setTimeout 放在跟踪器自动运行中是令人作呕的 :(
  • 不幸的是,超时很难看,但没有用于更新 DOM 的触发器/事件。
  • 你把这个发到任何官方的流星地方了吗?得到关于他们如何做的想法的任何回应?我试图在一个隐藏的元素上调用 focus() ,直到在元素上更改了一个类之后......并且 Meteor.setTimeout 50 有效,但我写了我写过的最抱歉的评论。
  • 我想我除了 stackoverflow 没有问过任何其他问题,虽然现在有新的流星论坛,所以你可以在那里尝试..
  • 我现在在他们的论坛上发布一些东西..

标签: javascript twitter-bootstrap events dom meteor


【解决方案1】:

如果我说得对,您实际上是在更改会话变量,并且希望在更改时进行回调?如果这是正确的,那么将该变量包装在一个自动运行函数中将在每次变量更改时执行它。

此外,如果仍然存在赛车问题,您可以在调用 test() 之前使用 setTimeout 稍有延迟。

Tracker.autorun(function () {
  Session.get('zoom');
  test();
});

【讨论】:

  • 感谢尼克的建议。在发帖之前我已经尝试过这两种方法,自动运行通常可以正常工作,但我确实遇到了竞争条件,有时它会起作用,有时不会。之后,我在单击缩放按钮时设置了超时(或者它可能在自动运行中),这可以工作,但这总是一个讨厌的解决方法。我希望有一些事件驱动/一致的东西,但想不出在这里发布的任何东西。很高兴知道您提出了相同的两个选项。
  • 目前无法检测 {{zoom}} 何时在 DOM 中呈现(至少在您的情况下不是),所以恐怕目前没有其他选择。我不会将 setTimeout 放在 click 事件上,而是放在自动运行中,这样至少你知道变量已经更新。使用非常小的延迟可能会很好(50ms 应该绰绰有余),所以它不应该带来任何问题。我同意这感觉有点老套,但有时我们别无选择;)
【解决方案2】:

这是我在 Meteor 论坛发帖后的无耻回答。

在您进行更改以引起反应性更改后,将您的 javascript 放入 Tracker.afterFlush 回调中。

http://docs.meteor.com/#/full/tracker_afterflush

【讨论】:

    猜你喜欢
    • 2016-11-21
    • 2014-08-10
    • 1970-01-01
    • 2014-10-10
    • 2021-08-24
    • 2014-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多