2017-03-14 39 views
0

我正在努力研究流星應用程序,其目標是在谷歌地圖上動態顯示車輛的路徑,例如海上的小船。流星:自動運行不會使我的代碼動態

現在,我看到這個庫名爲gmaps.js,並且因爲它在npm上可用(就像google maps api一樣),所以我決定使用它作爲繪製地圖的解決方案。因此,我有一個頁面,每次點擊一個按鈕(這是測試enougth)添加地理位置(/ runs /發送)在數據庫中。然後,在我的另一頁(/ 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功能在自動運行塊,和我使用的數據是從數據庫中,所以它是一個遊標,所以它也應該是被動的。

有反應的數據,在反應塊代碼(謝謝autorun)?預計在我的第二頁按下「發送」按鈕時,我的屏幕上會出現一個新行(此頁面只是在run.positions中添加一組[x,y]),但是......沒有!事實上,如果我手動重新加載頁面,當然會出現新行,但是wellll ...這不是我想說實話...

就這樣!任何想法,爲了有一些真正的反應性缺少什麼?

編輯:

此代碼部分:我第一次加載頁面時,執行console.log(圖)給出了一個定義,但我只需要重裝一次,然後該頁面將工作完全按照預期顯示我想要的動態。然而,一個單一的代碼重新加載,然後,再次,console.log(地圖)給出了不確定的,我需要一個新的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之間傳輸數據,這是我應該做的嗎?)

+0

嘗試使用'Tracker.autorun'而不是'self.autorun'或將'.bind(this)'添加到'self .autorun(function(){..}。bind(this));' – mutdmour

+0

.bind的用途是什麼?關於管理'this'的範圍或上下文的 – xababafr

+0

。它將'this'綁定到'Template'而不是回調。 [示例](HTTPS://計算器。com/questions/35000844/meteor-template-autorun-is-not-a-function-when-using-es6) – mutdmour

回答

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> 

附:這主要是僞代碼,因爲我從來沒有測試它,所以只是用它作爲指導

+0

好吧,我剛剛看到你的答案,這很有趣......感謝你付出了一些努力來幫助我,我很感激。我現在不能測試它,但是幾天後我就能夠,然後我會告訴你是否有任何事情能夠以這種方式變得更好。無論如何,我可能永遠不會那麼想,所以,好主意:p – xababafr

+0

你知道嗎?這工作!太棒了! – xababafr

+0

幸福,它幫助! @xababafr –

0

似乎問題是,訂閱回調不是一個被動的上下文。嘗試做別人的工作herehere,以及把你的onRendered跟蹤。

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