亚洲国产日韩欧美一区二区三区,精品亚洲国产成人av在线,国产99视频精品免视看7,99国产精品久久久久久久成人热,欧美日韩亚洲国产综合乱

搜索
博主信息
博文 54
粉絲 6
評論 31
訪問量 124125
最新下載
更多>
網(wǎng)站特效
網(wǎng)站源碼
網(wǎng)站素材
前端模板
JS五個精選的實戰(zhàn)案例
吾逍遙
原創(chuàng)
9961人瀏覽過

一、實戰(zhàn)前準(zhǔn)備知識

1、DOM元素常用操作

http://ipnx.cn/blog/detail/24740.html已經(jīng)介紹了DOM元素的獲取和遍歷,不清楚可以去熟悉下,這里介紹DOM元素常用操作,包括創(chuàng)建元素、添加元素、插入元素、替換元素、刪除元素以及大量添加元素時優(yōu)化方案 文檔片斷DocumentFragment 。這里增加了一些拓展測試,值得一看

1、 創(chuàng)建元素createElement 語法:document.createElement(‘tag’), 根是document ,參數(shù)是標(biāo)簽名稱,用單引號或雙引號包裹 ,創(chuàng)建元素對象并不在頁面中 ,而在 內(nèi)存中 ,沒有添加到頁面,需要掛載到頁面才顯示。這里要注意標(biāo)簽名稱一般是HTML規(guī)范的名稱,經(jīng)測試也可以是自定義的。

  1. // 1.創(chuàng)建元素對象,此時在內(nèi)存中,需要掛載才可顯示
  2. const ul = document.createElement('ul');
  3. ul.id = 'ul1';
  4. // 創(chuàng)建元素時,標(biāo)簽名稱也可以是自定義的
  5. const score = document.createElement('score');
  6. score.innerHTML = '大家好';

2、 添加元素appendChild 也稱 掛載 ,語法:父元素對象.appendChild(新元素對象), 根是父元素對象 ,添加元素前提要有一個父元素,否則無法定位位置, 參數(shù)是元素對象,不要引號 元素對象可以是createElement創(chuàng)建的元素對象,也可以是獲取的或遍歷的得到的元素對象。在測試時發(fā)現(xiàn)了它的一個 有趣現(xiàn)象 ,就是測試同一個父元素反復(fù)添加和添加到不同父元素的結(jié)果。

  • 父元素對象 可以是在內(nèi)存中的元素對象(createElement或createDocumentFragment),也可以頁面中元素對象。常見的頁面元素對象有document.head,document.body和document.documetElement(Html對象)
  • 參數(shù)中元素對象 同父元素對象,但要注意不能是頁面中唯一的對象,如body對象、head對象等。經(jīng)測試document.appendChild時會報唯一對象沖突錯誤。
  • 總是在尾部添加 append英文翻譯是追加,就是在最后添加元素的意思。
  • 同一個父元素反復(fù)添加 先說測試結(jié)果,反復(fù)添加最終是只算一個 ,估計是元素對象在頁面文檔流中都有唯一標(biāo)號,不可以重復(fù)出現(xiàn)。
  • 添加到不同父元素 這個更有趣,它會 刪除以前所在位置 ,出現(xiàn)在最后添加的位置 。這個結(jié)果就非常有用了,經(jīng)典應(yīng)用場景 就是用戶在備用選項中選擇,如選擇了某項愛好后,它就在提供的備用選項中移動到選擇中。
  1. <style>
  2. ul { width: 10em; height: 5em; }
  3. #ul1 { background-color: aquamarine; }
  4. #ul2 { background-color: seagreen; }
  5. </style>
  6. <script>
  7. const ul = document.createElement('ul');
  8. ul.id = 'ul1';
  9. // 2.頁面加載元素,父元素一般是頁面中元素對象
  10. document.body.appendChild(ul);
  11. const li = document.createElement('li');
  12. li.innerHTML = '123';
  13. // appendChild父元素可以是內(nèi)存中元素對象
  14. ul.appendChild(li);
  15. const ul2 = document.createElement('ul');
  16. ul2.id = 'ul2';
  17. document.body.appendChild(ul2);
  18. // 當(dāng)同一個元素添加到不同父元素時,出現(xiàn)有趣移動效果,這個應(yīng)用場景就是用戶在備用選項中選擇
  19. ul.onclick = function (ev) {
  20. ul2.appendChild(li);
  21. };
  22. ul2.onclick = function (ev) {
  23. ul.appendChild(li);
  24. };
  25. </script>

appendChild

3、 插入元素insertBefore 相比于appendChild只能在最后添加元素對象的限制外,insertBefore可以在指定元素對象前插入元素對象。語法:父元素對象.insertBefore(新元素對象,參考元素對象)。

  • 父元素對象和參考元素對象 二者是父子關(guān)系 即二者所在空間是一致的,即同為內(nèi)存中元素對象或頁面中元素對象。
  • 新元素對象 同appendChild中一樣
  • 不在insertAfter JS默認(rèn)沒提供insertAfter,可以根據(jù)insertBefore寫一個。
  1. const li2 = document.createElement('li');
  2. li2.innerHTML = 'hello';
  3. li2.style.color = 'red';
  4. ul.insertBefore(li2,ul.firstChild);

insert

4、 替換元素replaceChild 語法:父元素對象.replaceChild(新元素對象,參考元素對象)。比較簡單,參考插入,不再演示
5、 刪除元素removeChild 語法: 父元素對象.removeChild(存在元素對象),其實刪除并不是真正的刪除,它在內(nèi)存中仍然存在,可再次掛載。

  1. // 刪除并不是真正的刪除,它在內(nèi)存中仍然存在,可再次掛載
  2. score.onclick = function (ev) {
  3. document.body.removeChild(score);
  4. document.body.appendChild(score);
  5. };

2、大量dom元素操作時優(yōu)化方案

在說優(yōu)化方案之前,我簡單說下網(wǎng)頁的二個重要部分:DOM樹和內(nèi)存,前者就是頁面中已經(jīng)存在的元素,后者應(yīng)該是頁面緩存(我也不清楚對不對,有的文檔稱為內(nèi)存)。DOM樹是已經(jīng)渲染完成后的結(jié)果,每一次更新操作都會導(dǎo)致頁面再渲染,所以大量dom操作則會導(dǎo)致頁面一直忙于渲染,這種 “頁面回流” 用戶體驗就非常不好。目前老師解決方案是文檔片斷,來優(yōu)化或提升dom操作的效率。不過在前面我在偶然發(fā)現(xiàn)在內(nèi)存中也可以組裝,于是就有了兩種優(yōu)化方案。比較如下:

  1. // 大量元素時優(yōu)化方案
  2. ul = document.createElement('ul');
  3. // 第一種優(yōu)化方案:內(nèi)存組裝,一次加載
  4. for (let i = 0; i < 1000; i++) {
  5. let li = document.createElement('li');
  6. li.innerHTML = 'item' + i;
  7. ul.appendChild(li);
  8. }
  9. // 第二種優(yōu)化方案:文檔片斷組裝,一次加載
  10. // const frag = document.createDocumentFragment();
  11. // for (let i = 0; i < 1000; i++) {
  12. // let li = document.createElement('li');
  13. // li.innerHTML = 'item' + i;
  14. // frag.appendChild(li);
  15. // }
  16. // ul.appendChild(frag);
  17. document.body.appendChild(ul);

good1
good2

測試結(jié)果和結(jié)論: 二者加載1000個列表元素 時間相近 ,實質(zhì)都是在 內(nèi)存中組裝 。關(guān)于二者區(qū)別,后來咨詢了老師,老師說文檔片斷是通用容器,可臨時存儲任何類型對象,不過前者在內(nèi)存中好像也是可以存儲任何類型,目前我沒發(fā)現(xiàn)什么區(qū)別。

3、事件對象

事件是js操作中經(jīng)常要打交道的,我們重點關(guān)注和用戶交互的事件,就是鼠標(biāo)事件和鍵盤事件。不過之前還是要看下事件常用的兩個屬性target和currentTarget。

事件的兩個重要屬性: 觸發(fā)者target和綁定者currentTarget 以前錯誤想法是target是當(dāng)前元素,而currentTarget是上級對象,經(jīng)測試才明白它們的區(qū)別

  • currentTarget 綁定者就是 綁定這個事件的元素對象 ,即是在JS中定義事件時的對象。
  • target 觸發(fā)者是 觸發(fā)事件行為的元素對象 ,估計這個不好理解。那就實際測試?yán)斫?,測試結(jié)果是 觸發(fā)者一定是綁定者或綁定者的子孫元素 。如只定義了元素的事件,那么該元素的子孫元素若沒有定義事件時,則自動繼承該事件。

上面對target的測試的結(jié)論,是 事件委托代理的工作原理 ,就是 事件也有繼承性 。本文中實戰(zhàn)案例大量應(yīng)用事件委托代理,其實在日常JS編程中事件委托代理是經(jīng)常使用的技巧,可簡化邏輯和代碼。

  1. <style>
  2. .parent {
  3. width: 20em;
  4. height: 20em;
  5. background-color: red;
  6. }
  7. .self {
  8. width: 15em;
  9. height: 15em;
  10. background-color: green;
  11. }
  12. .child {
  13. width: 10em;
  14. height: 10em;
  15. color: white;
  16. background-color: blue;
  17. }
  18. </style>
  19. <div class="parent">
  20. <div class="self">
  21. <div class="child">大家好,學(xué)習(xí)事件</div>
  22. </div>
  23. </div>
  24. <script>
  25. const parent1 = document.querySelector('.parent');
  26. const self1 = document.querySelector('.self');
  27. const child = document.querySelector('.child');
  28. // 1.target和currentTarget
  29. parent1.onclick = function (ev) {
  30. console.log('類名:%s => 觸發(fā)者:%s , 綁定者:%s', this.className, ev.target, ev.currentTarget);
  31. };
  32. </script>

event-target

鼠標(biāo)事件MouseEvent: 感覺常用的就是點擊類型type、各種位置坐標(biāo)x與y,具體可以console.dir打印

鍵盤事件KeyboardEvent 感覺常用的就是鍵盤事件類型type、key和keyCode等,一般鍵盤事件添加到window或input。

  1. window.onkeyup=function(ev){
  2. console.log(ev.key);
  3. console.dir(ev);
  4. }

keyevent

4、 視口高度clientHeight、滾動高度scrollTop和元素偏移高度offsetTop

  • 視口高度clientHeight 通俗地講就是 可視區(qū)域高度 ,它總是小于設(shè)備屏幕尺寸。通過 document.documentElement.clientHeight 獲取,要注意不是viewHeight,我案例中開始以為它,它是代表看過的高度。
  • 滾動高度scrollTop 就是滾動條上邊距可視區(qū)域頂部的高度。它加上視口高度所包括的內(nèi)容就是用戶可以瀏覽的內(nèi)容。通過 document.documentElement.scrollTop 獲取。
  • 元素偏移高度offsetTop 元素在文檔流中,到文檔頂部的高度。通過 元素的offsetTop 屬性獲取。

三者關(guān)系見下圖:

clientheight

5、其它的

  • this 事件函數(shù)中this表示觸發(fā)者,若是事函數(shù)使用箭頭函數(shù)時,此時this不是事件觸發(fā)者。
  • innerHTML和innerText 前者功能比后者強大,可以解析html標(biāo)簽元素。
  • dataset自定義數(shù)據(jù)屬性 在元素中,用戶可以通過data-為前綴添加自定義的數(shù)據(jù)屬性,尤其是多個元素中同步切換子元素時非常有用,如tab選項卡中tab和選項區(qū)兩個同步。

二、實戰(zhàn)案例1:留言本

實現(xiàn)功能:

  1. 用戶輸入留言后,若不是空格或空,回車后則添加留言區(qū)
  2. 最新的留言總是在最上面
  3. 留言條可以刪除
  1. <div class="container">
  2. <label for="content">輸入留言:</label>
  3. <input type="text" id="content" name="content" value="" placeholder="輸入留言后回車確認(rèn)" />
  4. <ul id="lists"></ul>
  5. </div>
  6. <script>
  7. const content = document.querySelector('#content');
  8. const lists = document.querySelector('#lists');
  9. content.onkeyup = function (ev) {
  10. // console.log(ev.key);
  11. // 判斷回車時,添加內(nèi)容到列表中
  12. if (ev.key == 'Enter') {
  13. // trim除去空格,空內(nèi)容不添加
  14. if (content.value.trim().length > 0) {
  15. let li = document.createElement('li');
  16. li.innerHTML = content.value + "<button onclick='del(this)'>刪除</button>";
  17. // 若列表有內(nèi)容則添加到最前,沒有則追加
  18. lists.childElementCount == 0 ? lists.appendChild(li) : lists.insertBefore(li, lists.firstElementChild);
  19. // 添加內(nèi)容后,清空輸入框
  20. content.value = null;
  21. } else {
  22. // 無效添加后,輸入框獲取焦點
  23. content.focus();
  24. }
  25. }
  26. };
  27. function del(el) {
  28. // confirm確認(rèn)返回true,取消返回false
  29. if (confirm('確認(rèn)刪除')) lists.removeChild(el.parentElement);
  30. }
  31. </script>

todolist

Codepen演示 https://codepen.io/woxiaoyao81/pen/ExyeEad

三、實戰(zhàn)案例2:tab選項卡

tab選項卡功能就不說了,這里我是通過dataset自定義屬性同步tab和內(nèi)容區(qū),另一個我是通過切換order來實現(xiàn)內(nèi)容區(qū)切換的

  1. <script>
  2. const divs = document.querySelectorAll('.container div:nth-child(n)');
  3. const ul = document.querySelector('ul');
  4. // console.log(divs);
  5. ul.addEventListener('click', tab, false);
  6. function tab(ev) {
  7. // tab菜單切換:先清除所有,再設(shè)置當(dāng)前選擇的
  8. for (let el of ul.children) {
  9. el.classList.remove('active');
  10. }
  11. ev.target.classList.toggle('active');
  12. // tab區(qū)切換:先清除激活樣式和order,然后設(shè)置和tab相同數(shù)據(jù)屬性的區(qū)
  13. for (let el of divs) {
  14. if (el.dataset.index == ev.target.dataset.index) {
  15. el.classList.add('active');
  16. el.style.order = 0;
  17. } else {
  18. el.classList.remove('active');
  19. el.style.order = 1;
  20. }
  21. }
  22. }
  23. </script>

tab

四、實戰(zhàn)案例3:頁面換背景

太簡單了,就是設(shè)置body的background-image

  1. <div class="container">
  2. <img src="static/images/1.jpg" alt="" />
  3. <img src="static/images/2.jpg" alt="" />
  4. <img src="static/images/3.jpg" alt="" />
  5. </div>
  6. <script>
  7. const container = document.querySelector('.container');
  8. container.onclick = ev => (document.body.style.backgroundImage = 'url(' + ev.target.src + ')');
  9. </script>

background

五、實戰(zhàn)案例4:圖片懶加載

這里關(guān)鍵是:一個是圖片占位的概念,另一個就是通過真正的圖片路徑已經(jīng)包括在元素data-src自定義屬性中。當(dāng)元素的偏移高度小于視口高度和滾動高度之和就加載圖片。

  1. <script>
  2. const imgs = document.querySelectorAll('.container img');
  3. // 視口高度,即可視區(qū)域高度
  4. const clientHeight = document.documentElement.clientHeight;
  5. window.addEventListener('scroll', lazy, false);
  6. window.addEventListener('load', lazy, false);
  7. function lazy(ev) {
  8. // 滾動高度,可視區(qū)域滾動過的距離
  9. let scrollTop = document.documentElement.scrollTop;
  10. for (let img of imgs) {
  11. // 元素在文檔中偏移高度,也可稱為真實高度
  12. let offsetTop = img.offsetTop;
  13. // 當(dāng)元素偏移高度小于(視口高度+滾動高度)時,元素就出現(xiàn)在可視區(qū)域了
  14. if (offsetTop <= scrollTop + clientHeight) {
  15. setTimeout(() => (img.src = img.dataset.src), 500);
  16. }
  17. }
  18. }
  19. </script>

lazy

六、實戰(zhàn)案例5:用戶選擇愛好

功能描述: 從提供的愛好中選擇自己的愛好,此時備選區(qū)的愛好就移動到自己愛好區(qū)。
關(guān)鍵技術(shù): 還記得本文前面介紹appendChild有趣的現(xiàn)象了嗎?不知道可以向上看看。

select

  1. <div class="container">
  2. <div class="box">
  3. <h2>你的愛好:</h2>
  4. <ul id="selected" class="item"></ul>
  5. </div>
  6. <div class="box">
  7. <h2>從下面選擇愛好:</h2>
  8. <ul id="unselected" class="item">
  9. <li>攝影</li>
  10. <li>編程</li>
  11. <li>游戲</li>
  12. <li>旅游</li>
  13. <li>駕駛</li>
  14. <li>文學(xué)</li>
  15. </ul>
  16. </div>
  17. </div>
  18. <script>
  19. // 移動關(guān)鍵是利用appendchild一個特性:不同父元素添加同一個元素時,以前的位置會刪除,最終出現(xiàn)在最后的位置
  20. const ulSelect = document.querySelector('#selected');
  21. const ul = document.querySelector('#unselected');
  22. ul.addEventListener('click', ulAdd, false);
  23. function ulAdd(ev) {
  24. // 判斷是否有子元素,防止一次多選擇
  25. if (ev.target.childElementCount == 0) ulSelect.appendChild(ev.target);
  26. }
  27. ulSelect.addEventListener('click', ulDel, false);
  28. function ulDel(ev) {
  29. if (ev.target.childElementCount == 0) ul.appendChild(ev.target);
  30. }
  31. </script>

Codepen演示代碼 https://codepen.io/woxiaoyao81/pen/mdEGxyJ

七、學(xué)習(xí)后的總結(jié)

今天是原生JS實戰(zhàn)課,非常感謝朱老師這段時間的耐心的講解,同時也很慶幸自己每節(jié)課都認(rèn)真梳理、測試和總結(jié),在實戰(zhàn)環(huán)節(jié)沒什么壓力,視頻看了一遍就自己完成代碼,只參考了老師核心的思想,具體實現(xiàn)有自己的改進。上面只貼了關(guān)鍵代碼,源文件歡迎訪問我的GitHubhttps://github.com/woxiaoyao81/phpcn13或Giteehttps://gitee.com/freegroup81/phpcn13

  • JS基本知識的核心要理解透,如條件、循環(huán)控制、函數(shù)和dom操作
  • 熟悉json、ajax的原理和流程,最好能動手寫出代碼。
  • 熟悉事件的添加、傳遞和委托代理,尤其是本文中測試的target和currentTaget的總結(jié)。

到這里原生JS已經(jīng)學(xué)完,學(xué)習(xí)關(guān)鍵是多寫代碼,多思為什么,對自己疑問要測試,不要輕易相信網(wǎng)上搜的文章,要經(jīng)過驗證才能變成自己的。

批改老師:天蓬老師天蓬老師

批改狀態(tài):合格

老師批語:1. 文檔片斷不會被添加到頁面,只有它的引用才會被添加 2. 具體到本例,如果<ul>是頁面中已經(jīng)存在的元素,需要給它創(chuàng)建1000個子元素,你覺得應(yīng)該怎么做呢?是否是創(chuàng)建一個添加一個呢? 咱們課堂上的案例是一個特例,沒有體現(xiàn)出文檔片斷的優(yōu)勢
本博文版權(quán)歸博主所有,轉(zhuǎn)載請注明地址!如有侵權(quán)、違法,請聯(lián)系admin@php.cn舉報處理!
全部評論 文明上網(wǎng)理性發(fā)言,請遵守新聞評論服務(wù)協(xié)議
1條評論
吾逍遙 2020-11-09 07:28:39
通過你的舉例子我明白了兩者區(qū)別了,就比如ul...li結(jié)構(gòu),一般都是頁面已經(jīng)存在ul元素了,li是動態(tài)添加,此時文檔片斷就虛擬ul角色,在內(nèi)存中組裝,然后一次性加載。而內(nèi)存直接組裝則因為沒有父元素?zé)o法進行。所以在內(nèi)存組裝階段,文檔片斷是虛擬了頁面中真實存在的元素,掛載時將子元素真實添加到頁面中的元素下
1樓
作者最新博文
關(guān)于我們 免責(zé)申明 意見反饋 講師合作 廣告合作 最新更新
php中文網(wǎng):公益在線php培訓(xùn),幫助PHP學(xué)習(xí)者快速成長!
關(guān)注服務(wù)號 技術(shù)交流群
PHP中文網(wǎng)訂閱號
每天精選資源文章推送
PHP中文網(wǎng)APP
隨時隨地碎片化學(xué)習(xí)
PHP中文網(wǎng)抖音號
發(fā)現(xiàn)有趣的

Copyright 2014-2025 http://ipnx.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號

  • 登錄PHP中文網(wǎng),和優(yōu)秀的人一起學(xué)習(xí)!
    全站2000+教程免費學(xué)