流星:autorun不会让我的代码动态 [英] Meteor : autorun won't make my code dynamic

查看:127
本文介绍了流星:autorun不会让我的代码动态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力研究一款流星应用程序,其目标是在谷歌地图上动态显示车辆的路径,例如海上的一艘船。

现在,我看到这个图书馆名为 gmaps.js ,因为它在npm上可用(就像google maps api),我决定使用它作为绘制地图的解决方案。



所以,每次点击一个按钮时(这是为了测试),我都有一个页面在数据库中添加地理位置(/ runs / send)。然后,在我的另一页(/ runs / show)上,目标是从mongo获取数据并在地图上动态提示它(也就是说,如果通过按按钮添加数据,我会看到新路径显示在地图)。下面是代码现在的样子:

  import'Template'from'meteor / templating'; 
从'meteor / tracker'导入{Tracker};
从'meteor / meteor'中导入{Meteor}
从'gmaps'导入gmaps;
从'google-maps'导入google_maps;

从'meteor / mongo'导入{Mongo};

从'./run.js'导入{Run};
导入'./methods.js';

Template.runs_show.helpers({
all(){
return Run.find({});
}
});

Template.runs_show.onCreated(function(){

var self = this;
self.autorun(function(){
self.subscribe ('allRuns',function(){
google_maps.KEY =MY API KEY;
google_maps.load(google){

console.log(Google加载地图);

//创建一个新地图
var map = new gmaps({
el:'#map-gmaps',
lat: -12.043333,
lng:-77.028333
});

//现在,数据正在运行{maxSpeed:75}
var dada = Run.findOne({maxSpeed:75});

//路径看起来像[[x1,y1],[x2,y2]]
var path = dada.positions;

//在路径
中定义的点之后,在地图上绘制一条红线map.drawPolyline({
路径:路径,
strokeColor:'#FC291C',
strokeOpacity:0.85,
strokeWeight:6
});


});
});
});

});

所以,你可以看到,我把我的onCreated函数放在一个自动运行块中,数据i使用来自数据库,所以它是一个游标,所以它也应该是被动的。

对于反应性数据,在反应性代码块内(谢谢autorun)?预计在我的第二页按下发送按钮时,我的屏幕上会出现一个新行(此页面只是在run.positions中添加一组[x,y]),但是......没有!事实上,如果我手动重新加载页面,当然会出现新行,但是wellll ...这不是我想说实话的...

所以而已!任何想法什么是缺少为了有一些真正的反应?

编辑:



<这段代码部分起作用:第一次加载页面时,console.log(map)给出了一个未定义的,但我只需要重新加载一次,然后页面将按照预期工作,显示我想要的动态。然而,一个单一的代码重新加载,然后,再次,console.log(地图)给出了未定义的,我需要一个新的F5 ....任何想法为什么这样做/如何解决它?

  Template.runs_show.onCreated(function(){

google_maps.KEY =MY API KEY;
google_maps.load(google){
var map = new gmaps({
el:'#map-gmaps',
lat:-12.043333,
lng: - 77.028333
});

//我可以在onRendered
Template.runs_show.map = map;
}); $ b中使用地图
$ b console.log(Template.runs_show);

});

Template.runs_show.onRendered(function(){

var self = this;
self.autorun(function(){
self.subscribe ('allRuns',function(){
Tracker.autorun(function(){

var map = Template.runs_show.map;

console.log map);

var dada = Run.findOne({maxSpeed:75});
var path = dada.positions;

map。 drawPolyline({
path:path,
strokeColor:'#FC291C',
strokeOpacity:0.85,
strokeWeight:6
});

//似乎不是必需的
//map.refresh();

});
});
});

});

(在这个新代码中,我只是在onCreated中创建映射,当gmaps加载时,然后,我在onRendered中绘制所有的绘图。顺便说一句,我使用Template.xxx.map在onCreated和onRendered之间传输数据,这是我应该做的吗?)

解决方案

尝试为此使用嵌套模板。以便您的包装模板订阅数据,并且只在订阅准备就绪时呈现嵌套模板:

  //处理订阅的包装模板
Template.wrapper.onCreated(function(){
this.subscribe('allRuns');
});

Template.runs_show.onRendered(function(){
google_maps.KEY =MY API KEY;
google_maps.load(function(google){
var map = new gmaps({
el:'#map-gmaps',
lat:-12.043333,
lng:-77.028333
});

)Tracker.autorun(function(){
// Run.find将重新触发整个自动运行块
//如果集合的任何元素被更改或
//元素从集合
//创建或删除//因此使该块对数据更改产生反应
//这也可以与findOne一起使用,以防您只想要
//一次只能运行
var runs = Run.find({maxSpeed:75})。fetch();
// map.clear()或类似的东西来删除所有多段线
//在重新编译之前 - 渲染它们
runs.forEach(function(run){
map.drawPolyline({
path:path,
strokeColor:'#FC291C',
strokeOpacity:0.85,
strokeWeight:6
});
});

});
// ^^这很愚蠢,每次重新渲染所有项目
//更聪明的东西只会实际重新渲染
//更改项目,不要触及那些谁没有改变,但
//需要稍微更复杂的逻辑

});
});

wrapper.html:

 < template name =wrapper> 
{{#if Template.subscriptionsReady}}
{{> runs_show}}
{{/ if}}
< / template>

这主要是伪代码,因为我从来没有测试过它,所以只是用它作为指导


I'm working hard on a meteor App which goal is to dynamically display on a google map the path of a vehicle, for example a boat on the sea.

Now, I see this library called gmaps.js, and since it is available on npm (just like google maps api) I decide to use this as a solution to draw of the map.

So, I have one page that add a geographic position (/runs/send) in the database each time I click on a button (this is enougth for testing). Then, on my other page (/runs/show) the goal is to get that data from mongo and prompt it dynamically on the map (meaning, if I add data by pressing the button, I'll see the new path appear on the map). Here is what the code looks like for now :

import { Template } from 'meteor/templating';
import {Tracker} from 'meteor/tracker';
import { Meteor } from 'meteor/meteor'
import gmaps from 'gmaps';
import google_maps from 'google-maps';

import {Mongo} from 'meteor/mongo';

 import {Run} from './run.js';
 import './methods.js';

Template.runs_show.helpers({
    all() {
        return Run.find({});
    }
});

Template.runs_show.onCreated(function() {

    var self = this;
    self.autorun(function() {
        self.subscribe('allRuns',function() {
            google_maps.KEY = "MY API KEY";
            google_maps.load(function(google){

                console.log("Google Maps loaded");

                // this creates a new map
                var map = new gmaps({
                      el: '#map-gmaps',
                      lat: -12.043333,
                      lng: -77.028333
                });

              // for now , the data is on the run with {"maxSpeed" : "75"}
              var dada = Run.findOne({"maxSpeed" : "75"});

              // path look like [[x1,y1],[x2,y2]]
              var path = dada.positions;

              // this draws a red line on the map following the points defined in path
              map.drawPolyline({
                  path: path,
                  strokeColor: '#FC291C',
                  strokeOpacity: 0.85,
                  strokeWeight: 6
              });


              });
        });
    });

  });

So, as you can see, I put my onCreated function in a autorun block, and the data i'm using is from a database, so it's a cursor, so it should be reactive as well.

With a reactive data, inside a reactive block of code (thanks autorun)? expected to see a new line appear on my screen when I press "send" in my second page (this page just add a new set of [x,y] to the run.positions), but.... Nothing ! In fact, If I reload the page manually, the new line appears, of course, but wellll... That's not what I wanted to be honest...

So that's it! any idea what is missing in order to have some true reactivity?

EDIT :

This code works partially : the first time I load the page, the console.log(map) gives a undefined, but I just need to reload once, and then the page will work exactly as intended, showing what I want dynamically. However, one single code reload, and then, again, the console.log(map) gives undefined, and I need a new F5.... Any idea on why it does that / how to solve it?

Template.runs_show.onCreated(function() {

        google_maps.KEY = "MY API KEY";
        google_maps.load(function(google){
            var map = new gmaps({
                  el: '#map-gmaps',
                  lat: -12.043333,
                  lng: -77.028333
            });

            // with that, I can use the map in the onRendered
            Template.runs_show.map = map;
        });

        console.log(Template.runs_show);

 });

 Template.runs_show.onRendered(function() {

     var self = this;
     self.autorun(function() {
         self.subscribe('allRuns',function() {
             Tracker.autorun(function(){

                 var map = Template.runs_show.map;

                 console.log(map);

                 var dada = Run.findOne({"maxSpeed" : "75"});
                 var path = dada.positions;

                 map.drawPolyline({
                     path: path,
                     strokeColor: '#FC291C',
                     strokeOpacity: 0.85,
                     strokeWeight: 6
                 });

                  // seems to not be necesary
                 //map.refresh();

             });
        });
    });

 });

(in this new code, I just create the map in the onCreated, when the gmaps is loaded, and then, I make all the drawing in the onRendered. Btw, I used Template.xxx.map to transmit data between onCreated and onRendered, is that what i'm supposed to do?)

解决方案

Try using nested templates for this. So that your wrapper template subscribes to data and only renders nested template when subscriptions is ready:

//wrapper template that manages subscription
Template.wrapper.onCreated(function() {
  this.subscribe('allRuns');
});

Template.runs_show.onRendered(function() {
  google_maps.KEY = "MY API KEY";
  google_maps.load(function(google){
    var map = new gmaps({
      el: '#map-gmaps',
      lat: -12.043333,
      lng: -77.028333
    });

    Tracker.autorun(function() {
      // Run.find will re-trigger this whole autorun block
      // if any of the elements of the collection gets changed or
      // element gets created or deleted from collection
      // thus making this block reactive to data changes
      // this will also work with findOne in case you only want to
      // one run only
      var runs = Run.find({"maxSpeed" : "75"}).fetch();
      // map.clear() or something like that to remove all polylines
      // before re-rendering them
      runs.forEach(function(run){
        map.drawPolyline({
          path          : path,
          strokeColor   : '#FC291C',
          strokeOpacity : 0.85,
          strokeWeight  : 6
        });
      });

    });
    // ^^ this is pretty dumb and re-renders all items every time
    // something more intelligent will only re-render actually 
    // changed items and don't touch those who didn't change but
    // that will require a slightly more complex logic

  });
});

wrapper.html:

<template name="wrapper">
  {{#if Template.subscriptionsReady }}
    {{> runs_show }}
  {{/if}}
</template>

P.S. this is mostly pseudo code since I never tested it, so just use it as a guide

这篇关于流星:autorun不会让我的代码动态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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