流星:自动运行不会让我的代码动态

时间:2017-03-14 21:32:57

标签: javascript mongodb google-maps meteor gmaps.js

我在流星App上努力工作,目标是在谷歌地图上动态显示车辆的路径,例如海上的船。

现在,我看到这个名为gmaps.js的库,因为它在npm上可用(就像谷歌地图api一样),我决定用这个作为绘制地图的解决方案。

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

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


              });
        });
    });

  });

因此,正如您所看到的,我将onCreated函数放在一个自动运行块中,而我使用的数据来自数据库,因此它是一个游标,所以它也应该是被动的。

使用反应数据,在反应代码块内(感谢自动运行)?我按下"发送"我的屏幕上会出现一个新行。在我的第二页(这个页面只是向run.positions添加一组新的[x,y]),但是....没什么!事实上,如果我手动重新加载页面,当然会出现新的一行,但是很好......那不是我想说实话的......

这就是它!任何想法,以便有一些真正的反应性?

编辑:

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

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

             });
        });
    });

 });

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

2 个答案:

答案 0 :(得分:0)

似乎问题是订阅回调不是反应性上下文。尝试对其他人herehere执行有效的操作,并将跟踪放在onRendered中。

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

答案 1 :(得分:0)

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

//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。这主要是伪代码,因为我从来没有测试它,所以只是用它作为指南