【发布时间】:2019-11-07 22:39:42
【问题描述】:
前言:这是我计划为各种网页重复使用和添加的内容。因此,我不想为此使用任何 JQuery,部分原因是我使用它的许多页面不需要其他任何东西(使我使用 JQuery 有点像用面粉填充 50 加仑桶,只是为了使用一茶匙面粉),部分原因是它是为资源稀少的移动浏览器设计的。
JQuery 效率低下似乎没什么大不了,特别是因为 its consolidated library 的大小不到 31MB,但根据 this page 的说法,对于 JavaScript 来说,它的 document.getElementById('foo'); 调用速度快了近 16 倍在 Chrome 中比 JQueries 等效:$('#foo');。此外,尽管$('#foo'); 在 Firefox 和 Safari 中比在 Chrome 中更快,document.getElementById('foo'); 在 Safari 中仍然快 10 倍,在 Firefox 中快 500 倍。不过,如果您的来源有相互矛盾的信息,请随时将其发布在 cmets 中并为任何已经做过的 cmets 点赞。
我有一组导航链接,我正试图以一定速度向上移动到一个位置,相对于它们与第一个导航链接的距离。为了帮助您了解我的意思,这是我的导航栏的动画(使用 JQuery slideUp 和 slideDown 函数完成),因此您可以看到它是如何工作的(口吃):
如果有帮助,我还将包含导航栏的 HTML:
<nav>
<ul id='nav'>
<li><a href="index.php"><icon><img src="images/home-icon.png"></icon>Home</a></li>
<li><a href="skillsets.php"><icon><img src="images/skills-icon.png"></icon>Skillsets</a></li>
<li><a href="gallery.php"><icon><img src="images/gallery-icon.png"></icon>Gallery</a></li>
<li><a href="about.php"><icon><img src="images/about-icon.png"></icon>About</a></li>
<li><a href="contact.php" style='border-right:1px solid black;'><icon><img src="images/contact-icon.png"></icon>Contact</a></li>
</ul>
</nav>
我的 JavaScript 文件有一个名为 prepareList() 的函数,它只是用来设置列表并折叠它(通过移动除第一个导航链接之外的所有链接)。为了防止 prepareList() 和它使用的任何变量在 HTML 加载之前被初始化,它们都包含在这个函数中:
document.addEventListener("DOMContentLoaded", function(event) {/*all the code*/});
我现在将包含我的 prepareList() JavaScript 函数,以及所有使用变量的初始化和值。我已经很好地评论了这一点,您可能仅从代码中的 cmets 就能理解它,但我会澄清我之后想要做什么:
//I will consolidate the first three objects into one href variable when I get the program working
var ul = document.getElementsByTagName("nav")[0].children[0],
li = ul.children,
href = new Array(li.length),
is404 = true,
isDown = false;
var itterator;
for(itterator = 0; itterator < li.length; itterator++)
href[itterator] = li[itterator].children[0];
prepareList();
function prepareList() {
//add a plus to the first nav link making it more obvious that it's the button to open the nav
href[0].innerHTML = href[0].innerHTML + "<span> +</span>";
//hide the remaining nav links with animations that move them up, at a speed,
//and to a postion, relative to how far they are from the first nav link
var lastTick = +new Date();
/*This function will be called for each nav link so they move at the same time
navElement is one of the li elements, number is the number (index) of the li element,
and number is negative if the list is collapsing (moving up)*/
var tick = function(navElement, number) {
var navElementStyleTop = parseFloat(navElement.style.top) + number * navElement.clientHeight * (new Date() - lastTick) / 1000;
//navElement.style.top = (navElementStyleTop + number * navElement.clientHeight * (new Date() - lastTick) / 1000) + "px"; //milliseconds
navElement.style.top = navElementStyleTop + "px";
lastTick = +new Date();
//requestAnimationFrame(tick) will only loop tick if the animation can be performed: http://www.javascriptkit.com/javatutors/requestanimationframe.shtml
//setTimeout(tick, 1000/15) will force the animation to be performed if it's been more than 1/15th of a second in order to maintain persistance of motion
if(number < 0){
if (navElementStyleTop > number * navElement.clientHeight)
requestAnimationFrame(tick(navElement, number)) || setTimeout(tick, 1000/15);
else //To prevent rounding errors from messing up the final position
navElement.style.top = (number * navElement.clientHeight) + "px";
}
else{
if (navElementStyleTop < 0)
requestAnimationFrame(tick(navElement, number)) || setTimeout(tick, 1000/15);
else //To prevent rounding errors from messing up the final position
navElement.style.top = "0px";
}
};
/*The for loop is to make this work no matter the number of links in the nav bar
(as the function executed before this may add a link to the nav bar)*/
for(itterator = 1; itterator < li.length; itterator++){
//necessary for top to work
href[itterator].style.position = "relative";
//give top a value so this doesn't rely on the browser defaulting it to 0
href[itterator].style.top = "0px";
tick(href[itterator], (-1) * itterator);
}
}
如果你没有看到我不能怪你的问题,那就是requestAnimationFrame(tick(navElement, number))。为了不抱怨递归,它必须以这种方式执行:requestAnimationFrame(tick)。根据this StackOverFlow answer,requestAnimationFrame是异步的,意思是“主线程不等待requestAnimFrame调用返回,之前”继续函数。
问题是我必须至少将number 传递给函数,以便函数知道它正在使用哪个元素。我可以看到使函数不需要传入任何参数的唯一方法是每次都在 for 循环中对其进行初始化。我真的不喜欢那个解决方案,因为我希望能够重用这个功能,以免浪费周期(可能还有很多内存)在第一个之后为每个导航链接重新创建它。所以,我想知道是否有办法将number 传递到所有的刻度函数中,同时保持requestAnimationFrame 的异步特性。
如果您有比 JQuery 的 slideUp 和 slideDown 函数更高效的更好方法,我会全力以赴。也许有人在网上某个地方有一个效率更高的 JavaScript 版本,但我还没有找到。
如果您需要更多信息,或者我有任何拼写错误,请随时在 cmets 中告诉我。
【问题讨论】: