簡體   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