3

我正在尝试在 Jade 模板中实现 Google 地图。使用 KeystoneJS 作为 CMS,我有许多“个人资料”(基本上是带有地址的人),我想将它们作为标记添加到地图中。

block js
  script.
        var map;
        function initialize() {
            var mapOptions = {
              center: new google.maps.LatLng(51.0360272, 3.7359072),
              zoom: 8
            };
            map = new google.maps.Map(document.getElementById("map-canvas"),
                mapOptions);

        }

        google.maps.event.addDomListener(window, 'load', initialize);

block content
   .container
       script(src='https://maps.googleapis.com/maps/api/js?key=<GOOGLE_API_KEY>&sensor=false')

     if data.profiles
        each profile in data.profiles
            #{new google.maps.Marker({position: new google.maps.LatLng(profile.address.geo[1], profile.address.geo[0]), map: map, title: profile.name.full})}

    div(id="map-canvas", style="width:100%; height:700px;")

地图显示正确,但是当我添加“每个”代码块时,出现错误“无法读取未定义的属性 'maps'”。

如何在 Jade 中添加一段在“每个”上执行的 js 代码?

4

2 回答 2

6

你真的很接近,唯一的问题是变量的内部,即#{this_stuff}全部jade的上下文中执行(它不会有google对象,因为这是客户端)。

这有点棘手,因为您在这里处理两个完全不同的 JavaScript 环境:服务器端客户端

所以你需要将你的jade中的服务器端变量输出到将在客户端执行的javascript代码中。

在相关说明中,您可以在脚本块中使用 Jade 变量语法,但不能做其他事情(如循环)。

首先,让我们清理它,以便您的所有script标签都在js块中(假设您使用的是示例 KeystoneJS 模板将位于<body>标签的底部)并正确生成这些配置文件:

block js
    script(src='https://maps.googleapis.com/maps/api/js?key=<GOOGLE_API_KEY>&sensor=false')
    script.
        var map;
        function initialize() {
            var mapOptions = {
                center: new google.maps.LatLng(51.0360272, 3.7359072),
                zoom: 8
            };
            map = new google.maps.Map(document.getElementById("map-canvas"),
                mapOptions);
        }

        google.maps.event.addDomListener(window, 'load', initialise);

    if data.profiles
        each profile in data.profiles
            script.
                new google.maps.Marker({
                    position: new google.maps.LatLng(#{profile.address.geo[1]}, #{profile.address.geo[0]}),
                    map: map,
                    title: "#{profile.name.full}"
                });

block content
   .container
        div(id="map-canvas", style="width:100%; height:700px;")

这越来越接近(并且 Jade 将生成您现在所期望的),但它(还)不起作用,因为您可能在函数运行之前将标记添加到地图中。initialize

它也不会转义值,因此"名称中的字符之类的东西会导致语法错误。

一种更强大的方法是填充客户端数组,然后在创建地图后循环该数组。我们还将用于JSON.stringify确保正确转义值。

block js
    script(src='https://maps.googleapis.com/maps/api/js?key=<GOOGLE_API_KEY>&sensor=false')
    script.
        var map,
            profiles = [];

        function initialize() {
            var mapOptions = {
                center: new google.maps.LatLng(51.0360272, 3.7359072),
                zoom: 8
            };
            map = new google.maps.Map(document.getElementById("map-canvas"),
                mapOptions);

            for (var i = 0; i < profiles.length; i++) {
                new google.maps.Marker({
                    position: new google.maps.LatLng(profiles[i].geo[1], profiles[i].geo[0]),
                    map: map,
                    title: profiles[i].name
                });
            }
        }

        google.maps.event.addDomListener(window, 'load', initialise);

    if data.profiles
        each profile in data.profiles
            script.
                profiles.push({
                    geo: !{JSON.stringify(profile.address.geo)},
                    name: !{JSON.stringify(profile.name.full)}
                });

block content
   .container
        div(id="map-canvas", style="width:100%; height:700px;")

请注意对 !{variable} 的更改,因此 JSON 不会被转义

最后,我建议profiles在您的路由文件中为视图构建数组.js,而不是在翡翠模板中进行。它更干净,并且您最终不会<script>在页面中出现大量标签。

所以你的路线看起来像这样(我假设给你一些想法,并使用下划线使代码比香草 javascript 更整洁)

var keystone = require('keystone'),
    _ = require('underscore');

exports = module.exports = function(req, res) {

    var view = new keystone.View(req, res),
        locals = res.locals;

    // Load the profiles
    view.query('profiles', keystone.list('Profile').model.find());

    // Create the array of profile markers
    view.on('render', function(next) {
        locals.profileMarkers = locals.profiles ? _.map(locals.profiles, function(profile) {
            return { geo: profile.address.geo, name: profile.name.full };
        }) : [];
        next();
    });

    // Render the view
    view.render('profiles');

}

然后在您的视图模板中:

block js
    script(src='https://maps.googleapis.com/maps/api/js?key=<GOOGLE_API_KEY>&sensor=false')
    script.
        var profileMarkers = !{JSON.stringify(profileMarkers)},
            map;

        function initialize() {
            var mapOptions = {
                center: new google.maps.LatLng(51.0360272, 3.7359072),
                zoom: 8
            };
            map = new google.maps.Map(document.getElementById("map-canvas"),
                mapOptions);

            _.each(profileMarkers, function(profile) {
                new google.maps.Marker({
                    position: new google.maps.LatLng(profile.geo[1], profile.geo[0]),
                    map: map,
                    title: profile.name
                });
            });
        }

        google.maps.event.addDomListener(window, 'load', initialise);

block content
   .container
        div(id="map-canvas", style="width:100%; height:700px;")
于 2014-03-08T15:20:56.603 回答
0

“无法读取未定义的属性‘地图’”

对此无能为力,似乎谷歌地图无法初始化或类似的东西。

但我可以告诉你,如果你想在你的 Jade 模板中执行 JavaScript,你只需要以破折号开头:var x = Math.random()

我认为以 . 开头的行中有(另一个)错误#{new google.maps.Maker...
这不是 JS,它是 Jade,构造函数的结果将用作 HTML 标记,我想你不希望这样。

这是一个示例,您可以将其粘贴到http://jade-lang.com/demo/上的此在线编辑器中

- var ar = [1,2,3]
ul
  each item in ar
    - var x = Math.random()*item
    li= x

您可以查看我的 gist 以获得一些 Jade 语法提示:https ://gist.github.com/timaschew/7543cf3d0c455f686784

于 2014-03-07T22:26:55.677 回答