【问题标题】:meteor reactive client: How to correctly change template parts on connect and disconnect events流星反应客户端:如何正确更改连接和断开事件的模板部分
【发布时间】:2014-06-05 12:13:32
【问题描述】:

请参阅描述的示例项目。这个非常简单的代码只显示一个绿色或红色(successdanger 类)div 块和带有连接状态的文本,如 ONoff

当您完全重新加载(Shift - F5)浏览器页面时,它可以按预期工作 10 次中的 9 次。

但有时文本会显示ON,但 div 仍然具有 html 源代码中预定义的类危险。

这是因为,Template...rendered 事件的触发晚于Meteor.status().connected

我想省略在两个地方检查是否必须交换课程。

我已经尝试在Template...renderedTemplate...connection_status 函数中移动...removeClass().addClass()... 行。

无论如何,有时 div 会保持红色。

浏览器控制台会在以下情况下显示日志:

[日志] SET CLASS SUCCESS(connection.js,第 10 行)

[日志] 模板渲染(connection.js,第 24 行)

问:有没有人知道比复制类检查更好的解决方案?

备注:是的,我知道,您可以通过使用空格键来解决这个示例问题,并编写类似class="alert alert-{{connection_alert_type}}" 的内容

但我正在寻找与 jQuery UI 相结合的通用解决方案,以便也可以有类似 switchClass 的转换。

问:是否可以选择(以及如何做)在连接状态更改时使模板无效并重新呈现?


自己测试样本

创建流星示例应用并通过流星添加包

  1. mrt 创建示例
  2. CD 样本
  3. mrt 添加 bootstrap-3
  4. mrt 添加 jquery
  5. rm 样本。*
  6. mkdir 客户端
  7. cd 客户端
  8. 创建文件client.htmlclient.js 列出的内容
  9. 地铁

client.html

<head>
  <title>connection</title>
</head>

<body>
  {{> connection_tpl}}
</body>

<template name="connection_tpl">
  <div id="connection-div" class="col-sm-12 alert alert-danger">
        <div><label>Connection Status:</label>{{connection_status}}</div>
  </div>
</template>

client.js(仅适用于 10 个或更少的 9 个):

// save reference to div element
var Div_Connection = undefined;

Deps.autorun(function () {
  // be reactive on Meteor connection
  var connected = Meteor.status().connected;

  // switch classes on connection
  if (connected) {
    console.log("SET CLASS SUCCESS");
    if (!_.isUndefined(Div_Connection))
      Div_Connection.removeClass('alert-danger').addClass('alert-success');
  } else {
    console.log("SET CLASS DANGER");
    if (!_.isUndefined(Div_Connection)) 
      Div_Connection.removeClass('alert-success').addClass('alert-danger');
  }
  // set session reactive flag
  Session.set("connected", connected);
});

Template.connection_tpl.rendered = function () {
  Div_Connection = $(this.find("#connection-div"));
  console.log("TEMPLATE RENDERED");
}

Template.connection_tpl.connection_status = function () {
  return Session.get("connected") ? "ON" : "off";
}

这是我目前的解决方案,但我不喜欢这种风格:-(

client.js(有效,但重复检查 - 性能不佳?可能两次转换?)

// save reference to div element
var Div_Connection = undefined;

var check_Classes = function(connected) {
  if (connected) {
    console.log("SET CLASS SUCCESS");
    if (!_.isUndefined(Div_Connection))
      if (!Div_Connection.hasClass('alert-success'))
        Div_Connection.removeClass('alert-danger').addClass('alert-success');
  } else {
    console.log("SET CLASS DANGER");
    if (!_.isUndefined(Div_Connection)) 
      if (!Div_Connection.hasClass('alert-danger'))
        Div_Connection.removeClass('alert-success').addClass('alert-danger');
  }
}

Deps.autorun(function () {
  // be reactive on Meteor connection
  var connected = Meteor.status().connected;
  // switch classes on connection
  check_Classes(connected);  
  // set session reactive flag
  Session.set("connected", connected);
});

Template.connection_tpl.rendered = function () {
  Div_Connection = $(this.find("#connection-div"));

  // switch classes on connection
  check_Classes(Session.get("connected"));  

  console.log("TEMPLATE RENDERED");
}

Template.connection_tpl.connection_status = function () {
  return Session.get("connected") ? "ON" : "off";
}

【问题讨论】:

    标签: jquery meteor


    【解决方案1】:

    不错的解决方案,一些建议:

    1. 为什么要有第一个Deps.autorun,为什么不在助手中直接调用Meteor.status()
    2. 您需要确保任何Deps.autorun 都被停止,如果您在.created.rendered 中启动一个,您可以将它们分配给模板实例,然后在.destroy 上停止它们

      Template.connection_tpl.rendered = function () {
        var Div_Connection = $(this.find("#connection-div"));
        this.computation = Deps.autorun(function () {
          var connected = Meteor.status().connected;
          Div_Connection.toggleClass('alert-danger', !connected).toggleClass('alert-succes', connected);
        });
      }
    
      Template.connection_tpl.destroyed = function(){
        if (this.computation){
          this.computation.stop()
        }
      };
    
      Template.connection_tpl.connection_status = function () {
        return Meteor.status().connected ? "ON" : "off";
      }
    

    【讨论】:

    • 嗨内森,感谢您的建议。在这个示例案例中,第一个 Deps.autorun() 不是必需的,这是绝对正确的。它已从我当前需要这样一个 Session 值的项目中取出并留在其中。还有一个问题留给我: 问:我是否还需要在 .rendered 或 @987654332 之外停止 Deps.autorun() @ 方法?我认为我“可以”这样做(如果用例定义了它),但在其他方面它仍然会永远运行。这是正确的理解吗?
    • 如果您的Deps.autorun 在任何功能等之外,那么您没有 阻止它...例如。如果没有风险,它可以像渲染的块一样再次运行(并加倍),那么就没有必要将其拆除。
    • 感谢您的回答和澄清
    【解决方案2】:

    有时候生活就是这么简单。

    考虑到这个问题,得出的结论就是加了Deps.autorun()两次。

    一次用于更新我们的 Session 值,第二次用于在 Template...rendered 方法内更新类。因此很确定所有必要的元素都已经在渲染中创建了。

    这是(从我的角度来看)正确的方式:


    client.js

    // this one checks for Session value
    Deps.autorun(function () {
      // be reactive on Meteor connection
      var connected = Meteor.status().connected;
      // set session reactive flag
      Session.set("connected", connected);
    });
    
    
    Template.connection_tpl.rendered = function () {
      var Div_Connection = $(this.find("#connection-div"));
    
      // this one checks for class exchange
      Deps.autorun(function () {
        // be reactive on Meteor connection
        var connected = Meteor.status().connected;
        // switch classes on connection
        if (connected) {
          console.log("SET CLASS SUCCESS");
          Div_Connection.removeClass('alert-danger').addClass('alert-success');
        } else {
          console.log("SET CLASS DANGER");
          Div_Connection.removeClass('alert-success').addClass('alert-danger');
        }
      });
    
      console.log("TEMPLATE RENDERED");
    }
    
    Template.connection_tpl.connection_status = function () {
      return Session.get("connected") ? "ON" : "off";
    }
    

    client.js(没有 console.log 的简称)

    // this one checks for Session value
    Deps.autorun(function () {
      var connected = Meteor.status().connected;
      Session.set("connected", connected);
    });
    
    
    Template.connection_tpl.rendered = function () {
      var Div_Connection = $(this.find("#connection-div"));
    
      // this one checks for class exchange
      Deps.autorun(function () {
        var connected = Meteor.status().connected;
        if (connected) {
          Div_Connection.removeClass('alert-danger').addClass('alert-success');
        } else {
          Div_Connection.removeClass('alert-success').addClass('alert-danger');
        }
      });
    }
    
    Template.connection_tpl.connection_status = function () {
      return Session.get("connected") ? "ON" : "off";
    }
    

    【讨论】:

    • 无论如何,请注意并查看 Nathan 接受的答案。他改进并更正了我的答案,特别是如果模板将被破坏,则应停止计算。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-03
    • 1970-01-01
    • 1970-01-01
    • 2011-03-21
    相关资源
    最近更新 更多