草庐IT

javascript - 如何在 meteor 准备好 DOM 后执行辅助函数

coder 2024-05-09 原文

我有一个 <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;
}

我直接在我的控制台中尝试了相同的操作并且它有效 - 我得到了一个对象 - 所以我猜测在执行此函数之前 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()); 
        } 
      }); 
    });
  });
});

上面的代码在 Meteor.Startup 中创建了一个新的谷歌地图(使用 GMaps.js 插件),然后在一个嵌套的 Subscribe 中从一个集合中获取所有文档,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;
}

最佳答案

Meteor.startup

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

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

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

这是否意味着所有 DOM 都已准备就绪?不!:

我认为这可能会给您带来一些麻烦。如果您使用 Google map 等外部 API,它们可能仍会呈现 map 。 Template.myTemplate.rendered() 意味着 Meteor 已完成使用必要的 react 变量渲染模板。因此,要了解您的 Google map 何时准备就绪,您需要连接到 Google map API。有一个look at this question

Using Meteor.subscribe

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

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

Meteor 使用这个带有模板和 react 数据的总结过程:

  1. 构建没有数据和渲染的模板 - 此阶段还没有数据
  2. 向服务器请求集合中的数据
  3. 使用新数据重建模板并渲染

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

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

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

建议对您的代码进行修改:

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

确保将模板助手放在 Meteor.isClient 而不是 Meteor.startup 中,因为 Meteor.startup 在初始 DOM 准备就绪后被触发( initial 是第一个但在它被 react 变量或路由器改变之前)所以你的模板定义需要在这个阶段之前运行。

关于javascript - 如何在 meteor 准备好 DOM 后执行辅助函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15312812/

有关javascript - 如何在 meteor 准备好 DOM 后执行辅助函数的更多相关文章

  1. ruby - 如何在 Ruby 中顺序创建 PI - 2

    出于纯粹的兴趣,我很好奇如何按顺序创建PI,而不是在过程结果之后生成数字,而是让数字在过程本身生成时显示。如果是这种情况,那么数字可以自行产生,我可以对以前看到的数字实现垃圾收集,从而创建一个无限系列。结果只是在Pi系列之后每秒生成一个数字。这是我通过互联网筛选的结果:这是流行的计算机友好算法,类机器算法:defarccot(x,unity)xpow=unity/xn=1sign=1sum=0loopdoterm=xpow/nbreakifterm==0sum+=sign*(xpow/n)xpow/=x*xn+=2sign=-signendsumenddefcalc_pi(digits

  2. ruby-openid:执行发现时未设置@socket - 2

    我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass

  3. ruby - 如何在 buildr 项目中使用 Ruby 代码? - 2

    如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby​​

  4. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  5. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  6. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  7. ruby - 如何在 Ruby 中拆分参数字符串 Bash 样式? - 2

    我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"

  8. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  9. ruby - 如何在 Lion 上安装 Xcode 4.6,需要用 RVM 升级 ruby - 2

    我实际上是在尝试使用RVM在我的OSX10.7.5上更新ruby,并在输入以下命令后:rvminstallruby我得到了以下回复:Searchingforbinaryrubies,thismighttakesometime.Checkingrequirementsforosx.Installingrequirementsforosx.Updatingsystem.......Errorrunning'requirements_osx_brew_update_systemruby-2.0.0-p247',pleaseread/Users/username/.rvm/log/138121

  10. ruby - Chef 执行非顺序配方 - 2

    我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul

随机推荐