如何在流星期间准备好DOM后执行辅助函数 [英] How to execute helper function after DOM is ready in meteor

查看:76
本文介绍了如何在流星期间准备好DOM后执行辅助函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a list of <li>'s which gets populated with a find() using Meteor.startup as you see below. Then I'm getting all the data attributes of these <li>'s using data() and putting it in an object and trying to return/console.log it so I can see if it works. But I'm getting null as a result.

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

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

I tried the same in my console directly and it works - I get an object back - so I'm guessing that the DOM is not ready/populated before this function is executed.

我很难理解Meteor.startup和Template.mytemplate.rendered之类的区别。在这种情况下,它们似乎都没有按我的意愿工作?

I am having a hard time understanding the difference between things like Meteor.startup and Template.mytemplate.rendered. In this case it seems that none of them works as I want?

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

What's the right way/place to do stuff with the DOM (traversing,getting attributes,manipulating)?

编辑

因为代码改变很多才能做我的事情我希望发布整件事。

as the code changed a lot in order to do what I wanted I post the whole thing.

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

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

The above code creates a new google map (using the GMaps.js plugin) inside Meteor.Startup, and then in a nested Subscribe fetchs all documents from a collection, forEaches the results and gets the latitude and longitude values, then goes on to add markers in the google map...

编辑2

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

I made my 'map' variable a global one this way no need to nest .subscribe and .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;
}


推荐答案

Meteor.startup

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

Meteor.startup() runs only once, its run on the client and server. So when the browser loads and the initial DOM is ready or the server starts. As Sohel Khalifa said you place initialization functions here. Don't define templates in here because the the templates need to be ready before this function can be fired.

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

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

This is run when meteor has finished and rendered the DOM. Additionally is run each time the HTML changes within the template. So for each item in your list in a subtemplate/a change in an item/update,etc as well as the list you will see the console.log return something if you use it to check. It will return null/undefined when calling for data sometimes (which i'll explain):

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

我认为这可能会给您带来一些麻烦。如果您使用外部API(例如Google地图),他们仍可能会渲染地图。 Template.myTemplate.rendered()表示 Meteor 已完成渲染模板,其中包含必要的反应变量。因此,要了解您的Google地图何时准备就绪,您需要加入Google地图API。请查看此问题

I think this is what might be causing you a bit of trouble. If you use external APIs such as Google maps, they might still render the map. the Template.myTemplate.rendered() means Meteor has finished rendering the template with the reactive variables necessary. So to find out when your Google maps might be ready you need to hook into the Google maps API. Have a look at this question

使用Meteor.subscribe

你可能得到的原因 null / undefined 使用渲染是因为这是流程通常会将数据渲染到模板中

The reason you might get null/undefined while using rendered is because this is the process meteor usually renders data into templates

你基本上是在调用<$ c订阅完成之前$ c> console.log(getMarkers()); ,这就是为什么你得到 null / undefined

You are basically calling console.log(getMarkers()); before the subscription is complete, which is why you get null/undefined

Meteor使用这个汇总过程和模板&反应数据:

Meteor uses this summarized process with templates & reactive data:


  1. 构建没有数据的模板&渲染 - 此阶段尚无数据

  2. 向服务器询问集合中的数据

  3. 使用新数据重建模板&渲染

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

So if at process 1) for a very short time you will have no data yet, which is why you might get null (such as in your code) & at the first render. To get past this you should use Meteor.subscribe's callback which is run when all the data is downloaded from the server: e.g

Meteor.subscribe("lists", function() {
    //Callback fired when data received
});

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

Note: Before you use this you should read the docs on using subscriptions as you need to remove the autopublish package, as well as make a corresponding Meteor.publish function on the server. While this may seem tedious you may end up doing it anyway to give your users their own lists &/or implement some kind of security.

建议修改为你的代码:

你正在正确的地方进行DOM遍历, Template.mytemplate.onRendered(function().. 但你还需要挂钩谷歌地图的API来捕捉他们的地图完成绘图。你还应该使用 Meteor.subscribe 来确保你得到正确的时间,而不是 null / undefined

You are doing DOM traversing in the right place, Template.mytemplate.onRendered(function().. but you also need to hook into Google Maps' API to capture when their map is finished drawing. You should also use Meteor.subscribe to make sure you get the timing right and not get null/undefined.

确保将模板助手放在 Meteor.isClient 中,但不要放在 Meteor.startup 中,因为Meteor。在初始DOM准备就绪后触发启动(初始化是第一个,但在被反应变量或路由器更改之前),因此模板定义需要在此阶段之前运行

Make sure you put your Template helpers in a Meteor.isClient but not in a Meteor.startup because Meteor.startup is fired after your initial DOM is ready (the intitial is the first but before its changed by reactive variables or a router) so your template definitions need to run before this stage.

这篇关于如何在流星期间准备好DOM后执行辅助函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆