如何在流星期间准备好DOM后执行辅助函数

Geo*_*nos 13 javascript meteor

我有一个<li>使用Meteor.startup填充find()的列表,如下所示.然后我<li>使用data()获取这些数据的所有数据属性并将其放入一个对象并尝试返回/ console.log,以便我可以看到它是否有效.但是我得到null了结果.

    Meteor.startup(function () {
    Template.messages.lists = function () {
        var allitems = lists.find();
        return allitems;
    };
    var map;
    map = new GMaps({
        div: '#map_canvas',
        lat: -12.043333,
        lng: -77.028333
    });
    var lat = map.getCenter().lat();
    var lng = map.getCenter().lng();
    map.addMarker({
        lat: lat,
        lng: lng,
        draggable: true,
        title: 'Test',
        dragend: function (e) {
            $('#lat').val(this.getPosition().lat());
            $('#lng').val(this.getPosition().lng());
        }
    });
    console.log(getMarkers());
});


function getMarkers() {
    var coordinates = {};
    coordinates = $('li.message').data();
    return coordinates;
}
Run Code Online (Sandbox Code Playgroud)

我直接在我的控制台中尝试了相同的操作 - 我得到了一个对象 - 所以我猜测在执行此函数之前DOM尚未准备好/已填充.

我很难理解Meteor.startup和Template.mytemplate.rendered之类的东西之间的区别.在这种情况下,似乎没有一个像我想要的那样工作?

使用DOM(遍历,获取属性,操作)的正确方法/地点是什么?

编辑

因为代码改变了很多,以便做我想要的事情我发布了整个事情.

Meteor.startup(function () {
  var map;
  map = new GMaps({
    div: '#map_canvas',
    lat: 50.853642,
    lng: 4.357452
  });
  Meteor.subscribe('AllMessages', function() {
    var allitems = lists.find().fetch();
    console.log(allitems);
    allitems.forEach(function(item) { 
      var lat = item.location.lat; 
      var lng = item.location.lng;
      console.log('latitude is: ' + lat);
      console.log('longitude is: ' + lng);
      map.addMarker({ 
        lat: lat, 
        lng: lng, 
        draggable: true, 
        title: 'Test', 
        dragend: function(e) { 
          $('#lat').val(this.getPosition().lat()); 
          $('#lng').val(this.getPosition().lng()); 
        } 
      }); 
    });
  });
});
Run Code Online (Sandbox Code Playgroud)

上面的代码在Meteor.Startup中创建了一个新的谷歌地图(使用GMaps.js插件),然后在嵌套的订阅中获取集合中的所有文档,forEaches结果并获取纬度和经度值,然后继续添加谷歌地图中的标记......

编辑2

我将'map'变量设置为全局变量,这样就不需要嵌套.subscribe和.startup.:

Meteor.subscribe('AllMessages', function() {
  var allitems = lists.find().fetch();
  console.log(allitems);
  allitems.forEach(function(item) { 
    var lat = item.location.lat; 
    var lng = item.location.lng;
    console.log('latitude is: ' + lat);
    console.log('longitude is: ' + lng);
    map.addMarker({ 
      lat: lat, 
      lng: lng, 
      draggable: true, 
      title: item.description, 
      dragend: function(e) { 
        $('#lat').val(this.getPosition().lat()); 
        $('#lng').val(this.getPosition().lng()); 
      } 
    }); 
  });
});

Meteor.startup(function () {
  map = new GMaps({
    div: '#map_canvas',
    lat: 50.853642,
    lng: 4.357452
  });
});

Template.messages.lists = function () {
  var allitems = lists.find().fetch();
  return allitems;
}
Run Code Online (Sandbox Code Playgroud)

Aks*_*hat 29

Meteor.startup

Meteor.startup()只运行一次,它在客户端和服务器上运行.因此,当浏览器加载并且初始DOM准备就绪或服务器启动时.正如Sohel Khalifa所说,你在这里放置初始化函数.不要在此处定义模板,因为在触发此函数之前,模板需要准备就绪.

Template.myTemplate.onRendered(function(){...})

这在meteor完成并渲染DOM时运行.另外,每次 HTML在模板中更改时都会运行.因此,对于列表中的每个项目,如子项目/更改项目/更新等,以及列表,您将看到console.log返回一些内容,如果您使用它来检查.它有时会返回null/ undefined调用数据(我会解释):

这是否意味着所有DOM都准备好了?没有!:

我认为这可能会给你带来一些麻烦.如果您使用外部API(例如Google地图),他们仍可能会渲染地图.该Template.myTemplate.rendered()手段流星呈现完毕必要的反应变量的模板.因此,要了解您的Google地图何时准备就绪,您需要加入Google地图API.有一个看看这个问题

使用Meteor.subscribe

您可能获得null/ undefined使用的原因rendered是因为这是流程流星通常将数据呈现到模板中

console.log(getMarkers());在订阅完成之前,您基本上是在调用,这就是您获得null/undefined

Meteor将此汇总过程与模板和反应数据结合使用:

  1. 构建没有数据和渲染的模板 - 此阶段尚无数据
  2. 向服务器询问集合中的数据
  3. 使用新数据和渲染重建模板

因此,如果在过程1)很短的时间内你将没有数据,这就是为什么你可能会得到null(例如在你的代码中)和第一次渲染.为了解决这个问题,您应该使用Meteor.subscribe从服务器下载所有数据时运行的回调:例如

Meteor.subscribe("lists", function() {
    //Callback fired when data received
});
Run Code Online (Sandbox Code Playgroud)

注意:在使用之前,您应该阅读有关使用订阅的文档,因为您需要删除autopublish包,以及Meteor.publish在服务器上创建相应的功能.虽然这可能看起来很乏味,但最终可能会为您的用户提供他们自己的列表和/或实现某种安全性.

建议编辑代码:

您正在正确的位置进行DOM遍历,Template.mytemplate.onRendered(function()..但您还需要连接到Google Maps的API以在地图完成绘制时捕获它们.您还应该使用Meteor.subscribe以确保您获得正确的时间而不是null/ undefined.

确保你把你的模板助手的Meteor.isClient,但不是在Meteor.startup因为Meteor.startup被触发后您最初的DOM准备好(初使是第一次,但之前它通过反应变量或路由器改变)让你的模板定义需要运行之前这个阶段.