如何使用JavaScript递归将一个模式循环到另一个模式,如果没有手动给定任何参数,它应该在什么时候停止循环?
我正在编写一个程序来打开屏幕中央的模式框。盒子适合屏幕&占据屏幕宽度和高度的80%。当点击该框时,该框有一个指向它的链接,将在其中心以其外部父框的80%大小打开另一个框,以此类推。现在,它应该在数学上不可能容纳另一个框的位置停止,并给我一个警报:不能再循环。我自己写了一些代码,现在,我被卡住了。我有两个疑问: a当我在单击时将子框循环到父框中时,如何禁用父链接,因为我希望单击时事件仅处理子元素? b我的递归停止并给我一个警告的那一点是什么 这是我迄今为止编写的代码: HTML: CSS: Javascript:如何使用JavaScript递归将一个模式循环到另一个模式,如果没有手动给定任何参数,它应该在什么时候停止循环?,javascript,recursion,Javascript,Recursion,我正在编写一个程序来打开屏幕中央的模式框。盒子适合屏幕&占据屏幕宽度和高度的80%。当点击该框时,该框有一个指向它的链接,将在其中心以其外部父框的80%大小打开另一个框,以此类推。现在,它应该在数学上不可能容纳另一个框的位置停止,并给我一个警报:不能再循环。我自己写了一些代码,现在,我被卡住了。我有两个疑问: a当我在单击时将子框循环到父框中时,如何禁用父链接,因为我希望单击时事件仅处理子元素? b我的递归停止并给我一个警告的那一点是什么 这是我迄今为止编写的代码: HTML: CSS: Jav
var loopBtn = document.querySelector('.loop-over');
loopBtn.addEventListener('click', function() {
appendBoxes();
});
function appendBoxes() {
var box = document.getElementById('box');
var clone = box.cloneNode(true);
box.append(clone);
}
提前感谢。A要防止单击一个元素触发对父元素的单击,必须停止单击事件的传播:
function onClickBox(event) {
event.stopPropagation();
}
我认为您不需要这样做,因为您附加事件处理程序的方式只会导致外部框具有单击处理程序,而不管随后添加了多少子框
B递归限制由你决定。然而,我认为,如果下一个盒子的宽度或高度小于1px,则可以合理地确定已达到限制。这是一个任意的限制:从数学上讲,你总是可以将一个值乘以0.8,得到一个新的更小的值。我之所以选择这个极限,是因为视觉化很自然地暗示了一条通向无限路径的地板。您可以通过测量已单击的长方体并计算其任一边是否短到长度*0.8<1.0来确定
我不清楚你想完成什么。我可以想象两种可能性:
1用户点击,出现一个框;用户第二次单击,第二个框出现在第一个框内;每次单击都会添加一个框
2用户单击一次,出现一个大框,然后第二个框出现在其中,然后第三个框出现在其中,以此类推,直到没有足够的空间容纳另一个框
在这两种情况下,真正的递归似乎都不相关;视觉效果让你误入歧途
我来对付2号
一般算法可能如下所示:
function matryoshka() {
while(true) {
// create box and add to document
// measure the box that was just added
// if measurements suggest no more space inside, break
}
}
在这一点上,你只需要研究DOM测量的细节,也许谷歌matryoshka就可以知道它们是俄罗斯的筑巢娃娃
但我认为您将遇到一个问题:这种方法假设DOM是以一种特殊的方式组织的,即框彼此嵌套,并且布局的实现使得每个框的大小自然地等于其父容器的80%。您当前的CSS没有做到这一点,这意味着充实JS存根并不能让您一直做到这一点
最后,我应该指出DOM操作不是瞬时的,其结果是,如果在添加元素后立即测量元素的几何体,通常会得到不正确的值。您可能需要引入延迟,这实际上会导致递归模式,或者只需通过航位推算处理数学:您可以获得视口尺寸,您可以跟踪已创建的框的数量,因此,从理论上讲,您可以将限制检查作为一个纯函数来执行,而不需要询问DOM。请在本文末尾查看此工作片段:
我添加了一个window.onload函数,以确保在添加侦听器之前加载元素
工作原理:
function addListener(element) {
element.addEventListener('click', function() {
if (this.childElementCount === 0 && this.offsetWidth >= 100 &&
this.offsetHeight >= 100) appendBoxes(this);
});
}
调用window.onload函数时,它会将侦听器添加到当前屏幕上的框中:
addListener(document.querySelector('.loop-over'));
如果调用eventListener函数,它首先检查单击的元素this是否没有子元素,因此只有最小的框才会生成新框:
this.childElementCount === 0
然后它还会检查元素是否足够大,我在这里选择的最小值为100px*100px,但您可以更改:
this.offsetWidth >= 100 && this.offsetHeight >= 100
如果这都是真的,它将调用生成框的函数。如果需要,您可以将其全部放在匿名函数中..:
function appendBoxes(element) {
element.append(element.cloneNode(true));
addListener(element.firstChild);
}
首先,创建一个新元素,然后在addListenerelement.firstChild中,该子元素也会获得一个侦听器
片段:
window.onload=函数{
addListenerdocument.querySelector'.loop over';
}
函数addListenerelement{
元素。addEventListener“单击”函数{
如果this.childElementCount==0&&this.offsetWidth>=100&&this.offsetHeight>=100
附属物;
否则,如果达到this.offsetWidth<100 | | this.offsetHeight<100警报堆栈限制!!;
};
}
函数附加框{
element.appendelement.cloneNodetrue;
addListenerelement.firstChild;
}
.莫代尔{
宽度:80%;
身高:80%;
保证金:自动;
位置:绝对位置;
左:0;
右:0;
光标:指针;
排名:0;
底部:0;
边框:1px实心;
显示:内联块;
}
嘿,它工作得很好。我的最后一个疑问是,当它达到最小高度和宽度时,如何获得警报,因为当我添加else语句时,它会在单击一次后立即发出警报,原因是这个.childElementCount==0语句?@V.Spock Yea,this.childElementCount==0检查单击的元素是否没有子元素。因此,可以尝试使用具有this.offsetWidth<100 | | this.offsetHeight<100的else if块?我将把它添加到代码段中。
function appendBoxes(element) {
element.append(element.cloneNode(true));
addListener(element.firstChild);
}