繁体   English   中英

如果没有jQuery,请创建一个“显示更多”,“显示更少”的href

[英]Without jQuery, make a “show more” “show less” a href

我知道使用jQuery非常简单,但是对于大学作业,需要在单击更多链接时插入新段落,然后在单击较少链接时将其删除-我们不使用CSS或jQuery,因此到目前为止我的代码看起来像这样-插入有效但是remove less()函数没有任何原因(即使尝试了less函数的简单警报,并且href上的return false也无法将页面重定向到无JavaScript默认值。

window.onload= function()
{
    var href = document.getElementById("more");
    href.setAttribute("onclick","more(); return false;");
    var more = document.getElementById("more");
    more.onclick = function more()
    {   
        var para1 = document.createElement("p");
        para1.setAttribute("id", "para1");  
        var para1Cont = document.createTextNode("my text block 1");
        para1.appendChild(para1Cont);
        var more = document.getElementById("more");
        more.parentNode.insertBefore(para1,more);
        var para2 = document.createElement("p");
        para2.setAttribute("id", "para2");
        var para2Cont = document.createTextNode("My text block 2");
        para2.appendChild(para2Cont);
        more.parentNode.insertBefore(para2,more);
        var toLess = more.setAttribute("id", "less");
        var less = document.getElementById("less");
        less.setAttribute("onclick", "less(); return false;");
        less.innerHTML ="click here for less";
        return false;
    };
    var less = document.getElementById("less");
    less.onclick = function less()
    {
        var para1 = document.getElementById("para1");
        var para2 = document.getElementById("para2");
        alert("fr");
        alert( para1.innerHTML);
        para1.parentNode.removeChild(para1);
        para2.parentNode.removeChild(para2);
        var less = document.getElementById("less");
        var toMore = less.setAttribute("id", "more");
        var more = document.getElementById("more");
        more.setAttribute("onclick", "more(); return false;");
        more.innerHTML ="click here for more";
         return false;
     }; 
};

和html代码

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
  <head>
<title>Help meeeee</title>
<link rel="stylesheet" type="text/css" href="styles/style.css">
    <link href="scripts/mystyles.css" rel="stylesheet" type="text/css" />
  </head>
  <body>
    <div id="header">
      <h1>test page</h1>
    </div>
    <div id="content">
       <a href="nojs.htm"  id="more"> click for more </a>
    </div>
    <script type="text/javascript" src="scripts/myscript.js"></script>
  </body>

好的,您有很多学习要做。 我并不是说这很糟糕,但这是我如何解决此问题的vanillaJS示例:

window.addEventListener('load',function l()
{//use addEventListener, to avoid mem-leaks
    "use strict";//for JSLint
    var more = document.getElementById('more'),
        less = document.getElementById('less'),
        div = more.parentNode,//3 DOM reference, to be used by event handlers
        added = [],//keep references to added elements, use as stack
        rmHandle = function(e)
        {//callback definition, don't bind unless less link should be usable
            var rm = added.pop();
            rm.parentNode.removeChild(rm);
            if (added.length === 0)
            {
                less.removeEventListener('click', rmHandle, false);
            }
            e.preventDefault();
            e.stopPropagation();
        };
    more.addEventListener('click',function(e)
    {//add node:
        var newP, count = added.length;
        e.preventDefault();
        e.stopPropagation();
        if (count === 0)
        {//bind less event handler here
            less.addEventListener('click', rmHandle, false);
        }
        ++count;
        newP = document.createElement('p');//create node
        newP.setAttribute('id','param'+count);//set id
        newP.appendChild(document.createTextNode('New Paragraph #'+count));//add txt content
        added.push(newP);//keep reference to node
        div.insertBefore(newP, less);//append at end...
    },false);
    window.removeEventListener('load',l,false);//unbind load handler, this is the leak in IE
}, false);

现在,这本身是有点意义的,所以我已经先行一步,并成立这个小提琴

还有很多事情要做(即,卸载事件处理程序,隐藏较少的链接等...)

一些说明可帮助您理解代码:

  • addEventListener :不是添加服装,也不是使用onloadonclick直接绑定事件处理程序,而是添加事件侦听器。 这些具有保留所有JS端的好处。 您在代码中的某处使用setAttribute('onclick'...) 这将在DOM中设置一个属性,该属性会引用回JS。 这被认为是不好的做法,并且已经过时了。
  • l回调。 我的主回调( window.addEventListener('load', function l()...称为l 。在此函数中,我查询DOM三次(某种程度),并将对这些DOM节点的引用分配给变量: morelessdiv接下来,我声明一个数组,以容纳要创建的所有节点,这是一种堆栈,因此无需查询dom即可获得对我创建的那些节点的引用。
  • 我还声明了一个函数( rmHandle ),它将处理less链接上的单击。 因为我在l的范围内声明了此函数,所以该函数可以访问我先前声明的所有变量( lessmoreadded )。 再说一次:我永远不需要查询DOM ...
  • more.addEventListener :此链接必须more.addEventListener开始工作,因此我在加载时将事件侦听器附加到此DOM节点。
  • no return false :您的问题表明您知道/曾经使用过jQuery。 return false在JQ和return false在JavaScript 是不一样的东西 如果将事件处理程序附加到VanillaJS中的表单,则return false可能会让您大吃一惊,因为有时:表单仍会提交。 阅读有关W3C事件模型的信息:捕获和冒泡阶段。 quirksmode.org是获取详细信息的好资源。 您将了解为什么我会尽快足够明确地调用这些方法。
  • document.createTextNode :现在,我也将不时使用innerHTML 但是,既然您正在学习,我可能会指出, innerHTML 不是标准的 ,官方标准是使用createTextNode
  • 最后,我删除了load事件侦听器, 因为IE倾向于泄漏内存(如果您不这样做的话) 然后,回调超出范围,您对此无能为力。 因此,一切都可以标记为GC,并且没有任何办法可以泄漏内存,但是...

编辑:
我将承认,列出一些列表项,其中仅涉及JS在嵌套作用域中解析变量名的方法还不够清楚。 当我第一次开始学习闭包时,这并不适合我,这当然不足以解释我发布的代码为什么会比您的代码性能好很多。
因此,如果您愿意的话,我将使用代码摘录来进一步解释这一点,并逐步进行清理复习:

var less = document.getElementById("less");
less.onclick = function less()
{
    var para1 = document.getElementById("para1");
    var para2 = document.getElementById("para2");
    alert("fr");
    alert( para1.innerHTML);
    para1.parentNode.removeChild(para1);
    para2.parentNode.removeChild(para2);
    var less = document.getElementById("less");
    var toMore = less.setAttribute("id", "more");
    var more = document.getElementById("more");
    more.setAttribute("onclick", "more(); return false;");
    more.innerHTML ="click here for more";
     return false;
 }; 

这段代码对您来说应该很熟悉(毕竟是从您的问题中粘贴出来的)。 现在我为什么要改变这个? 首先:DOM API( 不是 JS BTW的一部分)缓慢,笨拙,不合逻辑,并且是沮丧的主要根源,过多使用它会杀死林地小动物。 在此片段中,我们看到了以下内容:

var less = document.getElementById("less");
less.onclick = function less()
{
    //...
    var less = document.getElementById("less");
}

因此, less名称在分配上下文中使用了3次。 这些分配中有两个涉及DOM查询。 不只是一个查询,而且是完全相同的查询document.getElementById("less"); 人们常说,编写良好代码的规则之一是“ 不要重复自己”
你可能听说过的另一件事是,使用松散类型的语言,即使,它不是一个坏主意, 分配不同类型的一个变量。 尽管这样做是在编写function less(){} 除了一些语义上的差异(有时很重要,但这是另一些时间)之外,这基本上与以下操作相同:

var less = function(){};

这些分配中的每一个都掩盖了前一个分配。 如果你会写:

var less = document.getElementById("less");
less.onclick = function less_func()
{
    console.log(less);//logs a dom reference!
};
//or even:
less.onclick = function()
{//anonymous or lambda functions are valid... and quite common, too
    console.log(less);
};

您完全不需要使用onclick函数的第二个DOM查询。 这是因为JS尝试将所有变量解析为先前声明的变量的方式。 考虑一下:

var evilGlobal = 'Do not use Globals';
function()
{
    var goodLocal = 'Declared in function',
        funcVar = function()
        {
            console.log(goodLocal);
            console.log(evilGlobal);
        },
        func2 = function goodLocal(evilGlobal)
        {
            console.log(goodLocal);
            console.log(evilGlobal);
            console.log(funcVar());
        };
    funcVar();//logs Declared in function and Do not use Globals
    func2();//logs itself (function), and undefined and then same as above
    func2(goodLocal);//logs itself, Declared in Function and the same as funcVar
}

这是怎么发生的? funcVar这非常简单:

console.log(goodLocal);//<-- JS looks inside funcVar's function scope for var goodLocal
//not found? JS looks in the outer scope, that of the anonymous function that starts
//with var goodLocal = 'Declared in Function'
//This is the var used

同样适用于console.log(evilGlobal) 只有这一次,JS才扫描funcVar的范围,匿名函数的范围全局名称空间。 为什么不使用全局变量? 好吧,它们显然较慢,它们可以更改状态,因为函数可以自由访问它们,并且阻塞了内存(垃圾收集器仅释放不再在任何地方引用的内容。始终可以访问全局名称空间)。

第二种情况有点棘手,但不是很多:

function goodLocal()//the goodLocal name is defined as the function!

此名称掩盖了外部作用域中的变量。 JS 开始扫描本地范围,并发现goodLocal指向该函数。 它从不检查外部作用域,因此从不在父函数中看到goodLocal var。
这同样适用于evilGlobal

function goodLocal(evilGlobal)

参数是在函数范围内声明的变量。 JS绝不会扫描全局ns,因为这两个名称都可以解析为本地语言,除了:

的console.log(funcVar());

这将导致对父函数进行范围扫描,该函数声明了funcVar变量,并为其分配了先前讨论的函数。 该函数的行为仍然没有什么不同,因为该函数是在其自己的作用域/上下文中调用的。
调用上下文也很棘手,因此我将在稍后介绍一下。

回到您的代码:其他语句实际上也是您之前编写的内容的重复: var para1var para2是多余的,如果只是让它们在外部范围内可访问。

嗯,只要继续阅读并继续学习,您就会很快得到它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM