Jquery -> 纯JavaScript?

3

我是一名学习jQuery javascript编程的程序员,但从未真正掌握原生javascript(我知道我很淘气)。我的问题是,我该如何使用原生JS复制此功能?

$('select').change(function() {
    if($(this).val() == "Other (please specify)") {
        $(this).parent().parent().find("input.hidden").show();
    }
});

5
你应该做的一件事是查看jQuery源代码,以了解这些方法($changevalparentfindshow)的确切作用。 - rgthree
2
哇,想到有人直接使用jQuery而不掌握基础知识就有点可怕了 :-o 这会给那些知道如何修复问题的人带来更多的工作 ;-) - Alex Gill
2
@ianpgall: 这是一个愚蠢的比较。原生DOM API非常高级且大多数人都可以理解。可悲的是,这是一种典型的jQuery心态。 - I Hate Lazy
2
@jwatts1980:驾驶汽车与制造汽车几乎没有可比性。这更像是驾驶一辆可能一开始不太舒适的汽车,而不是与驾驶一辆汽车相比较。 - I Hate Lazy
1
@ianpgall:是的,我的观点是,关于制造汽车等方面的这些类比表明本机API远远超出了我们的能力范围,并且让它看起来似乎与jQuery之间的差距要大得多。不确定你是否注意到,但是那些没有理解语言和DOM就写jQuery的人常常会写出一些非常糟糕的代码。你见过这个吗? $(this).attr("id")? 或者这个? $(this)[0].outerHTML。就像jQuery是一个神奇的门户,所有DOM元素都必须通过它才能传递一样。 - I Hate Lazy
显示剩余8条评论
2个回答

6

这个网站可能会有帮助!

以下是逐步转换的说明:

var selects = document.getElementsByTagName('select');
for (var i=0; i<selects.length; i++) {
   selects[i].onchange = function() {
    if( this.value == "Other (please specify)") {
        var elements = this.parentNode.parentNode.getElementsByTagName("input");
        for (var j=0; j<elements.length; j++) {
           if( !elements[j].className.match(/\bhidden\b/)) continue;
           elements[j].style.display = ''; // the exact thing to do here would depend on your previous actions 
        }
    }
   }
}

@epascarello没错。对于其他人来说,区别在于onchange会覆盖之前定义的回调函数。但这通常是我们的目标。 - Denys Séguret
@dystroy:我认为show()不会改变visibility。我非常确定它设置了display: none; - jwatts1980
@Kolink感谢您做出的更改,消除了对querySelectorsAll的需要。 - Denys Séguret
@jwatts1980 我认为你的意思是根据元素使用 display: block; 或者 display: inline; - Ian
我进入了 源代码 发现 jQuery 只是简单地执行 'display=""'。 - Denys Séguret
显示剩余10条评论

6

$('select') - 使用 document.getElementsByTagName,然后循环遍历返回的列表

.change(function() {…} - 查看高级事件注册模型,以了解浏览器之间的差异

$(this).val() - 简单地使用this.value。即使在 jQuery 中,您也应该使用这种方法

$(this).parent().parent() - 获取该元素的父节点(两次)parentNode

.find("input.hidden") - 这有点难。您可以使用.querySelector[All],但这在旧式浏览器中不起作用。jQuery 使用其跨浏览器选择器引擎添加了大量功能。您可能会尝试另一种可跨浏览器工作的获取输入元素的方式;您可以尝试类似于javascript document.getElementsByClassName compatibility with IE的方法。

.show() - 通过el.style.display = "";删除 display:none;。顺便说一下,您可能只想使用remove,而不是用内联样式重写它 :-)

适用于符合 W3C 标准的浏览器的真正纯净代码:

[].each.call(document.getElementsByTagName('select'), function(select) {
    select.addEventListener("change", function(e) {
        if (this.value == "Other (please specify)") {
            var inputs = this.parentNode.parentNode.querySelectorAll("input.hidden");
            for (var i=0; i<inputs.length; i++)
                inputs[i].classList.remove("hidden");
        }
    }, false);
});

这应该也能在旧版浏览器中运行:
(function(selects, handler) {
    if (document.addEventListener)
        for (var i=0; i<selects.length; i++)
            selects[i].addEventListener("change", handler, false);
    else
        for (var i=0; i<selects.length; i++)
            selects[i].attachEvent("onchange", handler);
})(document.getElementsByTagName('select'), function() {
    if (this.value == "Other (please specify)") {
        var inputs = this.parentNode.parentNode.getElementsByTagName("input");
        for (var i=0; i<inputs.length; i++)
            if (/\bhidden\b/.test(inputs[i].className))
                inputs[i].style.display = "";
    }
});

是的,你会“重复”代码,但你会让它正确。在这种情况下,一个跨浏览器的 .querySelectorAll 的方法是使用 .getElementsByTagName(“input”) 然后匹配类... 这就是 Dystroy 所做的。但是值得提到所有选项以涵盖所有情况。 - Ian
1
我也不认为jQuery只是设置.style.display = ""...它会保存先前的状态。虽然在这种情况下我理解这并不严重或必要,但你可以在CSS中为一个div设置display: inline,并期望它回来,但使用display = ""会将其转换回block - Ian
1
jQuery如何实现完全无关紧要。您可以拥有一个完美工作的实现,而无需模拟jQuery。我并没有说执行display = ""就足够了。我确实说,在没有更多信息的情况下很难知道最佳方法。 - I Hate Lazy
@user1689607 这仍然是相关的。无论以何种方式正确地执行,采用类似的方法来回答OP的问题是必要的,但是现在display =''已经足够了。 - Ian
@ianpgall:是的,我认为所有内联样式都是不好的做法(有些像<div style="display:inline;">甚至“奇怪”),但应该真正使用样式表和类来处理这些事情。 - Bergi
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接