【发布时间】:2016-09-19 11:30:04
【问题描述】:
我有一个非常具体的需求,但标准数据绑定无法真正解决。
我有一张传单地图,我想与 vue 视图模型绑定。
我成功地在我的视图中显示了 geojson 功能,但我在显示与 vue.js 绑定的弹出窗口时遇到了困难
主要问题是:“如何打开一个弹窗(可能同时有多个弹窗)并将其绑定到一个视图属性”
现在我已经找到了一个可行的解决方案,但这太棒了:
map.html
<div id="view-wrapper">
<div id="map-container"></div>
<div v-for="statement in statements" id="map-statement-popup-template-${statement.id}" style="display: none">
<map-statement-popup v-bind:statement="statement"></map-statement-popup>
</div>
</div>
<!-- base template for statement map popup -->
<script type="text/template" id="map-statement-popup-template">
{{ statement.name }}
</script>
map.js
$(document).ready(function() {
var map = new L.Map('map-container');
map.setView(new L.LatLng(GLOBALS.MAP.STARTCOORDINATES.lng, GLOBALS.MAP.STARTCOORDINATES.lat), GLOBALS.MAP.STARTZOOM);
var osm = new L.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png');
osm.addTo(map);
//Initialize map dynamic layers
var mapLayers = {};
//View-model data-bindings
var vm = new Vue({
el: '#view-wrapper',
data: {
statements: []
},
methods: {
getStatements: function() {
return $.get('api/statements');
},
updateStatements: function() {
var that = this;
return that.getStatements().then(
function(res) {
that.statements = res.data;
}
);
},
refreshStatements: function() {
mapLayers.statements.layer.clearLayers();
if(this.statements && this.statements.length){
var geoJsonStatements = geoJsonFromStatements(this.statements);
mapLayers.statements.layer.addData(geoJsonStatements);
}
},
handleStatementFeature: function(feature, layer) {
var popupTemplateEl = $('#map-statement-popup-template-' + feature.properties.statement.id);
layer.bindPopup(popupTemplateEl.html());
var statementIndex = _.findIndex(this.statements, {statement:{id: feature.properties.statement.id}});
if(feature.geometry.type === 'LineString') {
this.statements[statementIndex].layer = {
id: L.stamp(layer)
};
}
},
openStatementPopup: function(statement) {
if(statement.layer) {
var featureLayer = mapLayers.statements.layer.getLayer(statement.layer.id);
featureLayer.openPopup();
}
}
},
created: function() {
var that = this;
//Set dynamic map layers
var statementsLayer = L.geoJson(null, {
onEachFeature: this.handleStatementFeature
});
mapLayers.statements = {
layer: statementsLayer
};
map.addLayer(mapLayers.statements.layer);
this.updateStatements().then(this.refreshStatements);
this.$watch('statements', this.refreshStatements);
},
components: {
'map-statement-popup': {
template: '#map-statement-popup-template',
props: {
statement: null
}
}
}
});
function geoJsonFromStatementsLocations(statements){
var geoJson = {
type: "FeatureCollection",
features: _.map(statements, function(statement) {
return {
type: "Feature",
geometry: {
type: "LineString",
coordinates: statement.coordinates
},
properties: {
statement: statement
}
};
});
};
return geoJson;
}
});
这对我来说似乎很可怕,因为我必须使用 v-for 循环遍历 语句,为每个语句的自定义元素呈现一个 div,隐藏它,然后在弹出窗口中使用它,用动态 id 技术抓取它。
我想做这样的事情:
map.html
<div id="view-wrapper">
<div id="map-container"></div>
</div>
<!-- base template for statement map popup -->
<script type="text/template" id="map-statement-popup-template">
{{ statement.name }}
</script>
map.js
$(document).ready(function() {
[...]
//View-model data-bindings
var vm = new Vue({
el: '#view-wrapper',
data: {
statements: []
},
methods: {
handleStatementFeature: function(feature, layer) {
var popupTemplateEl = $('<map-statement-popup />');
var scope = { statement: feature.properties.statement };
var compiledElement = this.COMPILE?(popupTemplateEl[0], scope);
layer.bindPopup(compiledElement);
}
},
components: {
'map-statement-popup': {
template: '#map-statement-popup-template',
props: {
statement: null
}
}
}
});
function geoJsonFromStatementsLocations(statements){
var geoJson = {
type: "FeatureCollection",
features: _.map(statements, function(statement) {
return {
type: "Feature",
geometry: {
type: "LineString",
coordinates: statement.coordinates
},
properties: {
statement: statement
}
};
});
};
return geoJson;
}
});
...但我找不到“编译”的功能?基于定义的范围。基本上我想:
- 创建自定义元素实例
- 传递一个范围
- 编译它
编辑:实际上,我可以找到 $compile 函数。但它通常用于将 appended 子元素编译到 html。我不想附加它然后编译它。我想编译它,然后让传单为我附加它。
【问题讨论】:
-
我不完全理解您的问题,但我的直觉是您应该使用自定义指令。
-
我的问题是我不知道如何编译带有作为参数传递的范围的自定义元素。阅读
handleStatementFeature,里面有几行我不知道怎么编码。 -
我不明白为什么你需要这个功能。看起来您只需要插入一个
selectedStatement变量即可。 -
@RoyJ,感谢您的建议。这是我的第二个想法,但我需要能够拥有我的自定义组件的多个并行实例。这就是为什么我将它实例化为每个可能的数据(语句)一次,但我觉得这很难看。我更喜欢 on demand 实例化它,从而准确地从 js 运行时编译它。如果您需要更多详细信息,请告诉我。
标签: javascript data-binding leaflet vue.js