我目前正在使用地图构建Vue应用程序。其功能基本上是这样的。我在地图上有一个位置和一个算法来确定这个位置是在水面上还是陆地上。如果是在水面上,我想重申一下附近的随机位置,直到我的位置在陆地上,并返回这些坐标。因此,基本上,我的代码(首先测试它的基本步骤)看起来与下面的类似
模板片段
<mapbox-marker :lngLat="getPositionOverLand([0,5])" />对应代码
const getPositonOverLand = (coords: any, tries=100) => {
const newCoords = [coords[0], coords[1]] as [number, number];
let thisTry = 0;
while(isOverWater(newCoords) && thisTry < tries){
newCoords[0] = coords[0] + (Math.random() - 0.5)*0.5
newCoords[1] = coords[1] + (Math.random() - 0.5)*0.5
thisTry++;
}
if(thisTry === tries)
throw new Error('No position on land nearby could be found');
coords[0] = newCoords[0];
coords[1] = newCoords[1];
}现在我调试了算法,它运行得很好。通常情况下,在5次左右的尝试之后,在陆地上的一个位置已经被找到并被归还。我还实现了一个参数,以便最大限度地尝试,因此,如果在开阔的海洋上的一个位置被抛出一个错误,在一定次数的尝试之后。
现在我在vue的问题是这个。如果更改函数中的坐标(使用返回语句或更改数组中的坐标并不重要),则函数将再次触发,留下无限循环。
有没有可能阻止这种行为,并确保算法只运行一次,或者我错过了其他的东西。
奇怪的是,我也试图只返回给定的和弦,只是为了测试,这并不会导致无限循环。
发布于 2021-04-08 23:35:53
不知道是什么触发了反应。从所发布的代码中,我们无法判断,因为看不到任何反应变量,因此它可能是由更多的上游因素引起的。
但是,我看到这一点:当涉及到vue时,<mapbox-marker :lngLat="getPositionOverLand([0,5])" />作为一种代码气味,因为它有可能导致您所看到的问题的类型。
当您将函数结果作为参数传递时,每当任何父函数触发重呈现时,该函数都会重新运行。如果函数中有触发重呈现的内容(这里似乎不是这样,但我没有看到返回,所以我知道它没有全部显示)。
更好的方法是使用computed或通过watch更新的data,这种方式存储值,并且只根据需要进行更改。
发布于 2021-04-09 09:20:01
好的,
正如已经指出的那样,问题是,位置上的每一个突变都会触发另一个修改器(这仍然不能解释为什么函数中参数本身的直接返回不会导致相同的行为)。
然而,我能够解决我的问题。现在,由于涉及到另一个具有异步行为的组件,我将发布比我原来问题中包含的代码更多的代码。所以我的html看起来像这样
<mapbox-map :accessToken="myToken" @loaded="updateMyPosition">
<mapbox-marker :lngLat="myPosition" />
</mapbox-map>现在,这个位置需要是一个参考文件,一旦地图被加载和可用,它就会被更新。这将确保数据只发生一次突变,而不是一次又一次地运行函数。
我还稍微修改了getPositionOverLand函数,但功能与以前基本相同。相对于while循环,我更喜欢递归变体。
const myPosition = ref([10,10]);
const getPositionOverLand = (coords, currentTry=0, maxTries=100) => {
if(!isOverWater(coords))
return coords;
let newCoords = [
coords[0] + (Math.random() - 0.5)*0.5,
coords[1] + (Math.random() - 0.5)*0.5
];
if(currentTry >= maxTries)
throw new Error('No position on land could be found');
return (isOverWater(newCoords) && currentTry < maxTries)
? getPositonOverLand(coords, currentTry+1, maxTries)
: newCoords;
}
const updateMyPosition = map => {
myPosition.value = getPositionOverLand(myPosition.value);
}现在,虽然这是有效的,我仍然认为它是不漂亮的。我更喜欢使用这个函数,而不是对ref进行变异,因为那样的话,使用v就会更加干净,就像在代码中迭代该数组并更改每个值一样。
现在,我将把这个作为答案,但是如果有人想出一个更干净的方法来做这件事,我会非常乐意改变这个被接受的答案;)
https://stackoverflow.com/questions/67011800
复制相似问题