如何使用JavaScript递归将一个模式循环到另一个模式,如果没有手动给定任何参数,它应该在什么时候停止循环?

如何使用JavaScript递归将一个模式循环到另一个模式,如果没有手动给定任何参数,它应该在什么时候停止循环?,javascript,recursion,Javascript,Recursion,我正在编写一个程序来打开屏幕中央的模式框。盒子适合屏幕&占据屏幕宽度和高度的80%。当点击该框时,该框有一个指向它的链接,将在其中心以其外部父框的80%大小打开另一个框,以此类推。现在,它应该在数学上不可能容纳另一个框的位置停止,并给我一个警报:不能再循环。我自己写了一些代码,现在,我被卡住了。我有两个疑问: a当我在单击时将子框循环到父框中时,如何禁用父链接,因为我希望单击时事件仅处理子元素? b我的递归停止并给我一个警告的那一点是什么 这是我迄今为止编写的代码: HTML: CSS: Jav

我正在编写一个程序来打开屏幕中央的模式框。盒子适合屏幕&占据屏幕宽度和高度的80%。当点击该框时,该框有一个指向它的链接,将在其中心以其外部父框的80%大小打开另一个框,以此类推。现在,它应该在数学上不可能容纳另一个框的位置停止,并给我一个警报:不能再循环。我自己写了一些代码,现在,我被卡住了。我有两个疑问:

a当我在单击时将子框循环到父框中时,如何禁用父链接,因为我希望单击时事件仅处理子元素? b我的递归停止并给我一个警告的那一点是什么

这是我迄今为止编写的代码:

HTML:

CSS:

Javascript:

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);

}