gpt4 book ai didi

javascript - 具有动态作用域编译的动态模板

转载 作者:行者123 更新时间:2023-11-28 05:32:34 27 4
gpt4 key购买 nike

我有一个非常具体的需求,无法通过标准数据绑定(bind)真正解决。

我有一个传单 map ,我想将其与 vue View 模型绑定(bind)。

我成功地显示了与我的 View 有点绑定(bind)的 geojson 功能,但我在显示与 vue.js 绑定(bind)的弹出窗口方面遇到了困难

主要问题是:“如何打开弹出窗口(可能同时打开多个弹出窗口)并将其绑定(bind)到 View 属性”

现在我已经找到了一个可行的解决方案,但这太棒了:

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 函数。但它经常用于将附加子项编译为 html。我不想附加它然后编译它。我想编译它,然后让传单为我附加它。

最佳答案

这对你有用吗?您不使用组件,而是创建一个要传递给 bindPopup 的新元素,然后在该元素上 new Vue 并设置您的 data适本地。

new Vue({
el: 'body',
data: {
popups: [1, 2, 3],
message: "I'm Dad",
statements: []
},
methods: {
handleFeature: function(id) {
const newDiv = document.createElement('div');
const theStatement = {
name: 'Some name for ' + id
};
newDiv.innerHTML = document.getElementById('map-statement-popup-template').innerHTML;
new Vue({
el: newDiv,
data: {
statement: theStatement
},
parent: this
});

// Mock call to layer.bindPopup
const layerEl = document.getElementById(id);
this.bindPopup(layerEl, newDiv);
},
bindPopup: function(layerEl, el) {
layerEl.appendChild(el);
}
}
});
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<div class="leaflet-zone">
<div v-for="popup in [1,2,3]">
<button @click="handleFeature('p-' + popup)">Bind</button>
<div id="p-{{popup}}"></div>
</div>
</div>

<template id="map-statement-popup-template">
{{ statement.name }} {{$parent.message}}
</template>

认为你可以使用$compile做同样的事情,但是$compile的记录很差(真的不)并且旨在用于内部使用。它对于在当前作用域中将新的 DOM 元素置于当前 Vue 的控制之下非常有用,但是您有一个新的作用域以及一个新的 DOM 元素,正如您所指出的,该绑定(bind)正是 Vue 的目的是。

您可以通过指定 parent option 来建立父链因为我已经更新了我的代码片段。

关于javascript - 具有动态作用域编译的动态模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39572122/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com