Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 国产成人福利视频,日本特黄特色aaa大片免费欧,美女高清毛片免费播放给你下载看

          整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          Web開發(fā)學(xué)習(xí)筆記(27)-CSS3(1)選擇器

          Web開發(fā)學(xué)習(xí)筆記(27)-CSS3(1)選擇器

          1)CSS3 中提供的新選擇器 —— 屬性選擇器:

          • 屬性選擇器

          屬性選擇器就是通過正則的方式去匹配指定屬性的元素,為其設(shè)置樣式。

          在 CSS3 中新增了三種屬性選擇器,如下所示:

          選擇器

          描述

          E[attr^=“xx”]

          選擇元素 E,其中 E 元素的 attr 屬性是以 xx 開頭的任何字符。

          E[attr$=“xx”]

          選擇元素 E,其中 E 元素的 attr 屬性是以 xx 結(jié)尾的任何字符。

          E[attr*=“xx”]

          選擇元素 E,其中 E 元素的 attr 屬性是包含 xx 的任何字符。

          例子,

          <!DOCTYPE html>
          <html lang="en">
            <head>
              <meta charset="UTF-8" />
              <meta name="viewport" content="width=device-width, initial-scale=1.0" />
              <title>Document</title>
              <style>
                a[href^="#"] {
                  color: rgb(179, 255, 0);
                }
                a[href$="org"] {
                  color: rgb(195, 0, 255);
                }
                a[href*="le"] {
                  background-color: rgb(0, 255, 149);
                  color: white;
                }
              </style>
            </head>
            <body>
              <ul>
                <li><a href="#">本地鏈接</a></li>
                <li><a href="https://www.wangyelang.cn">王耶浪</a></li>
                <li><a href="https://developer.mozilla.org">Web開發(fā)</a></li>
                <li><a href="https://learningnotes.com">學(xué)習(xí)筆記</a></li>
              </ul>
            </body>
          </html>

          顯示為,

          • 在上面代碼中,我們使用 a[href^="#"] 去匹配 a 標(biāo)簽中 href 屬性值以 # 開頭的元素。
          • 使用 a[href$="org"] 去匹配 a 標(biāo)簽中 href 屬性值以 org 結(jié)尾的元素。
          • 使用 a[href*="le"] 去匹配 a 標(biāo)簽中 href 屬性值包含 un 的元素。

          (2)子元素偽類選擇器就是選擇某元素的子元素的一種選擇器。

          在 CSS3 中,有以下幾種子元素偽類選擇器:

          選擇器

          描述

          E:first-child

          選擇元素 E 的第一個(gè)子元素。

          E:last-child

          選擇元素 E 的最后一個(gè)子元素。

          E:nth-child(n)

          選擇元素 E 的第 n 個(gè)子元素,n 有三種取值,數(shù)字、odd 和 even。注意第一個(gè)子元素的下標(biāo)是 1。

          E:only-child

          選擇元素 E 下唯一的子元素。

          E:first-of-type

          選擇父元素下第一個(gè) E 類型的子元素。

          E:last-of-type

          選擇父元素下最后一個(gè) E 類型的子元素。

          E:nth-of-type(n)

          選擇父元素下第 n 個(gè) E 類型的子元素,n 有三種取值,數(shù)字、odd 和 even。

          E:only-of-type

          選擇父元素唯一的 E 類型的子元素。

          E:nth-last-child(n)

          選擇所有 E 元素倒數(shù)的第 n 個(gè)子元素。

          E:nth-last-of-type(n)

          選擇所有 E 元素倒數(shù)的第 n 個(gè)為 E 的子元素。

          例子,

          <!DOCTYPE html>
          <html lang="en">
            <head>
              <meta charset="UTF-8" />
              <meta name="viewport" content="width=device-width, initial-scale=1.0" />
              <title>Document</title>
              <style>
                div {
                  width: 100px;
                  height: 100px;
                  margin-top: 10px;
                  background-color: rgb(0, 255, 242);
                }
                div:nth-child(2) {
                  background-color: rgb(0, 255, 128);
                }
                div:nth-of-type(4) {
                  background-color: rgb(111, 0, 255);
                }
              </style>
            </head>
            <body>
              <div></div>
              <div></div>
              <div></div>
              <div></div>
            </body>
          </html>
          

          顯示效果,

          • div:nth-child(2)div 的第 2 個(gè)子元素添加綠色背景顏色。
          • div:nth-of-type(4) 給父元素下第 4 個(gè) div 子元素添加紫色背景顏色。

          (3)UI 偽類選擇器是通過元素的狀態(tài)來選擇的一種選擇器。

          在 CSS3 中有以下幾種 UI 偽類選擇器。

          選擇器

          描述

          :focus

          給獲取焦點(diǎn)的元素設(shè)置樣式。

          ::selection

          給頁(yè)面中被選中的文本內(nèi)容設(shè)置樣式。

          :checked

          給被選中的單選框或者復(fù)選框設(shè)置樣式。

          :enabled

          給可用的表單設(shè)置樣式。

          :disabled

          給不可用的表單設(shè)置樣式。

          :read-only

          給只讀表單設(shè)置樣式。

          :read-write

          給可讀寫的表單元素設(shè)置樣式。

          :valid

          驗(yàn)證有效。

          :invalid

          驗(yàn)證無(wú)效。

          練習(xí)一:屬性有效性驗(yàn)證

          頁(yè)面上有一個(gè)郵箱輸入框,當(dāng)你的輸入滿足郵箱格式時(shí),輸入框的背景顏色為綠色;當(dāng)你的輸入不滿足要求,背景顏色為紅色。

          <!DOCTYPE html>
          <html lang="en">
            <head>
              <meta charset="UTF-8" />
              <meta name="viewport" content="width=device-width, initial-scale=1.0" />
              <title>Document</title>
              <style>
                /*格式錯(cuò)誤*/
                input:invalid {
                  background-color: red;
                }
                /*格式正確*/
                input:valid {
                  background-color: green;
                }
              </style>
            </head>
            <body>
              電子郵箱:<input type="email" />
            </body>
          </html>

          練習(xí)二:獲得焦點(diǎn)驗(yàn)證

          頁(yè)面上有一個(gè)姓名輸入框和一個(gè)密碼輸入框,當(dāng)聚焦輸入框時(shí),輸入框的背景顏色會(huì)發(fā)生改變,

          <!DOCTYPE html>
          <html lang="en">
            <head>
              <meta charset="UTF-8" />
              <meta name="viewport" content="width=device-width, initial-scale=1.0" />
              <title>Document</title>
              <style>
                input:focus {
                  background-color: rgb(255, 153, 0);
                }
              </style>
            </head>
            <body>
              姓名:<input type="text" /><br />
              密碼:<input type="password" />
            </body>
          </html>

          練習(xí):

          實(shí)現(xiàn)一個(gè)五彩導(dǎo)航

          在前面的內(nèi)容中,我們已經(jīng)學(xué)習(xí)了 CSS3 的選擇器應(yīng)用。我們?cè)谥暗恼鹿?jié)中也做過橫向?qū)Ш剑@里我們結(jié)合所學(xué)的 CSS3 選擇器來實(shí)現(xiàn)一個(gè)升級(jí)版的導(dǎo)航。

          知識(shí)點(diǎn)

          • hover 偽類選擇器

          要求

          1. 新建一個(gè) html 文件。
          2. <a> 標(biāo)簽轉(zhuǎn)換成行內(nèi)塊,寬 120px 高 58px、設(shè)置背景顏色 #FFFAE8;
          3. 當(dāng)鼠標(biāo)移動(dòng)到鏈接上時(shí)達(dá)到以下要求:
          • 背景顏色分別變?yōu)?#E1D15E、#F9D6D1、#5BDE66、#EBAA8D、#BED780;
          • 設(shè)置圓角效果(border-radius);
          • 字體:顏色為 #fff,去掉鏈接下劃線。

          驗(yàn)證測(cè)試

          按以上要求用 HTML 完成以下效果:

          解題:

          S 鼠標(biāo)框選(頁(yè)面選擇)時(shí)返回對(duì)應(yīng)的 HTML 或文案內(nèi)容

          一、需求背景

          1、項(xiàng)目需求

          當(dāng)用戶進(jìn)行鼠標(biāo)框選選擇了頁(yè)面上的內(nèi)容時(shí),把選擇的內(nèi)容進(jìn)行上報(bào)。

          2、需求解析

          雖然這需求就一句話的事,但是很顯然,沒那么簡(jiǎn)單...

          因?yàn)槭髽?biāo)框選說起來簡(jiǎn)單,就是選擇的內(nèi)容,但是這包含很多中情況,比如:只選擇文案、選擇圖片、選擇輸入框、輸入框中的內(nèi)容選擇、iframe、等。

          簡(jiǎn)單總結(jié),分為以下幾點(diǎn):

          1. 選擇文案時(shí)
          2. 選擇圖片、svg、iframe、video、audio 等標(biāo)簽時(shí)
          3. 選擇 input、select、textarea 等標(biāo)簽時(shí)
          4. 選擇 input、textarea 標(biāo)簽內(nèi)容時(shí)
          5. 選擇類似 字符時(shí)
          6. 鍵盤全選時(shí)
          7. 鼠標(biāo)右鍵選擇
          8. 以上各模塊結(jié)合時(shí)
          9. 當(dāng)包含標(biāo)簽的時(shí)候,返回 html 結(jié)構(gòu),只有文本時(shí)返回文本內(nèi)容

          二、技術(shù)要點(diǎn)

          鼠標(biāo)框選包含以下幾點(diǎn):

          1. debounce 防抖
          2. addEventListener 事件監(jiān)聽
          3. Range 對(duì)象
          4. Selection 對(duì)象

          1、debounce

          老生常談的技術(shù)點(diǎn)了,這里不能用節(jié)流,因?yàn)榭隙ú荒苣闶髽?biāo)選擇的時(shí)候,隔一段時(shí)間返回一段內(nèi)容,肯定是選擇之后一起返回。

          這里用 debounce 主要也是用在事件監(jiān)聽和事件處理上。

          • 【debounce 掘金】
          • 【debounce CSDN】

          2、addEventListener

          事件監(jiān)聽,因?yàn)槭髽?biāo)選擇,不僅僅是鼠標(biāo)按下到鼠標(biāo)抬起,還包括雙擊、右鍵、全選。

          需要使用事件監(jiān)聽對(duì)事件作處理。

          • 【addEventListener MDN】

          3、Range

          Range 接口表示一個(gè)包含節(jié)點(diǎn)與文本節(jié)點(diǎn)的一部分的文檔片段。

          Range 是瀏覽器原生的對(duì)象。

          3.1. 創(chuàng)建 Range 實(shí)例,并設(shè)置起始位置

          <body>
            <ul>
              <li>Vite</li>
              <li>Vue</li>
              <li>React</li>
              <li>VitePress</li>
              <li>NaiveUI</li>
            </ul>
          </body>
          <script>
            // 創(chuàng)建 Range 對(duì)象
            const range=new Range()
            const liDoms=document.querySelectorAll("li");
            // Range 起始位置在 li 2
            range.setStartBefore(liDoms[1]);
            // Range 結(jié)束位置在 li 3
            range.setEndAfter(liDoms[2]);
            // 獲取 selection 對(duì)象
            const selection=window.getSelection();
            // 添加光標(biāo)選擇的范圍
            selection.addRange(range);
          </script>


          可以看到,選擇內(nèi)容為第二行和第三行

          3.1.1 瀏覽器兼容情況


          3.2. Range 屬性

          1. startContainer:起始節(jié)點(diǎn)。
          2. startOffset:起始節(jié)點(diǎn)偏移量。
          3. endContainer:結(jié)束節(jié)點(diǎn)。
          4. endOffset:結(jié)束節(jié)點(diǎn)偏移量。
          5. collapsed:范圍的開始和結(jié)束是否為同一點(diǎn)。
          6. commonAncestorContainer:返回完整包含 startContainer 和 endContainer 的最深一級(jí)的節(jié)點(diǎn)。

          3.2.1. 用我們上面創(chuàng)建的實(shí)例來看下 range 屬性的值


          3.2.2. 如果我們只選擇文本內(nèi)容時(shí)

          只選擇 li 中的 itePres


          可以看出 range 屬性對(duì)應(yīng)的值


          3.3. Range 方法

          1. cloneContents():復(fù)制范圍內(nèi)容,并將復(fù)制的內(nèi)容作為 DocumentFragment 返回。
          2. cloneRange():創(chuàng)建一個(gè)具有相同起點(diǎn)/終點(diǎn)的新范圍, 非引用,可以隨意改變,不會(huì)影響另一方。
          3. collapse(toStart):如果 toStart=true 則設(shè)置 end=start,否則設(shè)置 start=end,從而折疊范圍。
          4. compareBoundaryPoints(how, sourceRange):兩個(gè)范圍邊界點(diǎn)進(jìn)行比較,返回一個(gè)數(shù)字 -1、0、1。
          5. comparePoint(referenceNode, offset):返回-1、0、1具體取決于 是 referenceNode 在 之前、相同還是之后。
          6. createContextualFragment(tagString):返回一個(gè) DocumentFragment。
          7. deleteContents():刪除框選的內(nèi)容。
          8. extractContents():從文檔中刪除范圍內(nèi)容,并將刪除的內(nèi)容作為 DocumentFragment 返回。
          9. getBoundingClientRect():和 dom 一樣,返回 DOMRect 對(duì)象。
          10. getClientRects():返回可迭代的對(duì)象序列 DOMRect。
          11. insertNode(node):在范圍的起始處將 node 插入文檔。
          12. intersectsNode(referenceNode):判斷與給定的 node 是否相交。
          13. selectNode(node):設(shè)置范圍以選擇整個(gè) node。
          14. selectNodeContents(node):設(shè)置范圍以選擇整個(gè) node 的內(nèi)容。
          15. setStart(startNode, startOffset):設(shè)置起點(diǎn)。
          16. setEnd(endNode, endOffset):設(shè)置終點(diǎn)。
          17. setStartBefore(node):將起點(diǎn)設(shè)置在 node 前面。
          18. setStartAfter(node):將起點(diǎn)設(shè)置在 node 后面。
          19. setEndBefore(node):將終點(diǎn)設(shè)置為 node 前面。
          20. setEndAfter(node):將終點(diǎn)設(shè)置為 node 后面。
          21. surroundContents(node):使用 node 將所選范圍內(nèi)容包裹起來。

          3.4. 創(chuàng)建 Range 的方法

          3.4.1. Document.createRange

          const range=document.createRange();

          3.4.2. Selection 的 getRangeAt() 方法

          const range=window.getSelection().getRangeAt(0)

          3.4.3. caretRangeFromPoint() 方法

          if (document.caretRangeFromPoint) {
              range=document.caretRangeFromPoint(e.clientX, e.clientY);
          }

          3.4.4. Range() 構(gòu)造函數(shù)

          const range=new Range()

          3.5. Range 兼容性


          4、Selection

          Selection 對(duì)象表示用戶選擇的文本范圍或插入符號(hào)的當(dāng)前位置。它代表頁(yè)面中的文本選區(qū),可能橫跨多個(gè)元素。

          4.1. 獲取文本對(duì)象

          window.getSelection()



          4.2. Selection 術(shù)語(yǔ)

          4.2.1. 錨點(diǎn) (anchor)

          錨指的是一個(gè)選區(qū)的起始點(diǎn)(不同于 HTML 中的錨點(diǎn)鏈接)。當(dāng)我們使用鼠標(biāo)框選一個(gè)區(qū)域的時(shí)候,錨點(diǎn)就是我們鼠標(biāo)按下瞬間的那個(gè)點(diǎn)。在用戶拖動(dòng)鼠標(biāo)時(shí),錨點(diǎn)是不會(huì)變的。

          4.2.2. 焦點(diǎn) (focus)

          選區(qū)的焦點(diǎn)是該選區(qū)的終點(diǎn),當(dāng)你用鼠標(biāo)框選一個(gè)選區(qū)的時(shí)候,焦點(diǎn)是你的鼠標(biāo)松開瞬間所記錄的那個(gè)點(diǎn)。隨著用戶拖動(dòng)鼠標(biāo),焦點(diǎn)的位置會(huì)隨著改變。

          4.2.3. 范圍 (range)

          范圍指的是文檔中連續(xù)的一部分。一個(gè)范圍包括整個(gè)節(jié)點(diǎn),也可以包含節(jié)點(diǎn)的一部分,例如文本節(jié)點(diǎn)的一部分。用戶通常下只能選擇一個(gè)范圍,但是有的時(shí)候用戶也有可能選擇多個(gè)范圍。

          4.2.4. 可編輯元素 (editing host)

          一個(gè)用戶可編輯的元素(例如一個(gè)使用 contenteditable 的 HTML 元素,或是在啟用了 designMode 的 Document 的子元素)。

          4.3. Selection 的屬性

          首先要清楚,選擇的起點(diǎn)稱為錨點(diǎn)(anchor),終點(diǎn)稱為焦點(diǎn)(focus)。

          1. anchorNode:選擇的起始節(jié)點(diǎn)。
          2. anchorOffset:選擇開始的 anchorNode 中的偏移量。
          3. focusNode:選擇的結(jié)束節(jié)點(diǎn)。
          4. focusOffset:選擇開始處 focusNode 的偏移量。
          5. isCollapsed:如果未選擇任何內(nèi)容(空范圍)或不存在,則為 true。
          6. rangeCount:選擇中的范圍數(shù),之前說過,除 Firefox 外,其他瀏覽器最多為1。
          7. type:類型:None、Caret、Range

          4.4. Selection 方法

          1. addRange(range): 將一個(gè) Range 對(duì)象添加到當(dāng)前選區(qū)。
          2. collapse(node, offset): 將選區(qū)折疊到指定的節(jié)點(diǎn)和偏移位置。
          3. collapseToEnd(): 將選區(qū)折疊到當(dāng)前選區(qū)的末尾。
          4. collapseToStart(): 將選區(qū)折疊到當(dāng)前選區(qū)的起始位置。
          5. containsNode(node, partlyContained): 判斷選區(qū)是否包含指定的節(jié)點(diǎn),可以選擇是否部分包含。
          6. deleteFromDocument(): 從文檔中刪除選區(qū)內(nèi)容。
          7. empty(): 從選區(qū)中移除所有范圍(同 `removeAllRanges()``,已廢棄)。
          8. extend(node, offset): 將選區(qū)的焦點(diǎn)節(jié)點(diǎn)擴(kuò)展到指定的節(jié)點(diǎn)和偏移位置。
          9. getRangeAt(index): 返回選區(qū)中指定索引處的 Range 對(duì)象。
          10. removeAllRanges(): 移除所有選區(qū)中的范圍。
          11. removeRange(range): 從選區(qū)中移除指定的 Range 對(duì)象。
          12. selectAllChildren(node): 選中指定節(jié)點(diǎn)的所有子節(jié)點(diǎn)。
          13. setBaseAndExtent(anchorNode, anchorOffset, focusNode, focusOffset): 設(shè)置選區(qū)的起始和結(jié)束節(jié)點(diǎn)及偏移位置。
          14. setPosition(node, offset):collapse 的別名

          4.5. Selection 兼容性


          三、項(xiàng)目實(shí)現(xiàn)

          1、實(shí)現(xiàn)思路

          1. 先獲取選擇的內(nèi)容,開發(fā) getSelectContent 函數(shù)
          2. 對(duì)獲取的內(nèi)容進(jìn)行判斷,是否存在 selection 實(shí)例,沒有直接返回 null
          3. 判斷 selection 實(shí)例的 isCollapsed 屬性 沒有選中,對(duì) selection 進(jìn)行 toString().trim() 操作,判斷內(nèi)容 有內(nèi)容,直接返回 text 類型 無(wú)內(nèi)容,返回 null 有選中,則判斷內(nèi)容
          4. 判斷選中的內(nèi)容有沒有節(jié)點(diǎn) 沒有節(jié)點(diǎn),則和沒有選中一樣處理,進(jìn)行 toString().trim() 操作,判斷內(nèi)容 有內(nèi)容,直接返回 text 類型 無(wú)內(nèi)容,返回 null 有節(jié)點(diǎn),進(jìn)行 toString().trim() 操作,判斷內(nèi)容 沒有內(nèi)容,判斷是否有特殊節(jié)點(diǎn) 有 'iframe', 'svg', 'img', 'audio', 'video' 節(jié)點(diǎn),返回 html 類型 有 'input', 'textarea', 'select',判斷 value 值,是否存在 存在:返回 html 類型 不存在:返回 null 沒有特殊節(jié)點(diǎn),返回 null 有內(nèi)容,返回 html 類型
          5. 對(duì)鼠標(biāo) mousedown、mouseup 事件和 selectionchange、contextmenu、dblclick 事件進(jìn)行監(jiān)聽,觸發(fā) getSelectContent 函數(shù)
          6. 在需要的地方進(jìn)行 debounce 防抖處理

          2、簡(jiǎn)易流程圖


          2、Debounce 方法實(shí)現(xiàn)

          2.1. JS

          function debounce (fn, time=500) {
            let timeout=null; // 創(chuàng)建一個(gè)標(biāo)記用來存放定時(shí)器的返回值
            return function () {
              clearTimeout(timeout) // 每當(dāng)觸發(fā)時(shí),把前一個(gè) 定時(shí)器 clear 掉
              timeout=setTimeout(()=> { // 創(chuàng)建一個(gè)新的 定時(shí)器,并賦值給 timeout
                fn.apply(this, arguments)
              }, time)
            }
          }

          2.2. TS

          /**
           * debounce 函數(shù)類型
           */
          type DebouncedFunction<F extends (...args: any[])=> any>=(...args: Parameters<F>)=> void
          /**
           * debounce 防抖函數(shù)
           * @param {Function} func 函數(shù)
           * @param {number} wait 等待時(shí)間
           * @param {false} immediate 是否立即執(zhí)行
           * @returns {DebouncedFunction}
           */
          function debounce<F extends (...args: any[])=> any>(
            func: F,
            wait=500,
            immediate=false
          ): DebouncedFunction<F> {
            let timeout: ReturnType<typeof setTimeout> | null
            return function (this: ThisParameterType<F>, ...args: Parameters<F>) {
              // eslint-disable-next-line @typescript-eslint/no-this-alias
              const context=this
              const later=function () {
                timeout=null
                if (!immediate) {
                  func.apply(context, args)
                }
              }
              const callNow=immediate && !timeout
              if (timeout) {
                clearTimeout(timeout)
              }
              timeout=setTimeout(later, wait)
              if (callNow) {
                func.apply(context, args)
              }
            }
          }

          3、獲取選擇的文本/html 元素

          3.1. 獲取文本/html 元素

          nterface IGetSelectContentProps {
            type: 'html' | 'text'
            content: string
          }
          /**
           * 獲取選擇的內(nèi)容
           * @returns {null | IGetSelectContentProps} 返回選擇的內(nèi)容
           */
          const getSelectContent=(): null | IGetSelectContentProps=> {
            const selection=window.getSelection()
            if (selection) {
              // 1. 是焦點(diǎn)在 input 輸入框
              // 2. 沒有選中
              // 3. 選擇的是輸入框
              if (selection.isCollapsed) {
                return selection.toString().trim().length
                  ? {
                      type: 'text',
                      content: selection.toString().trim()
                    }
                  : null
              }
              // 獲取選擇范圍
              const range=selection.getRangeAt(0)
              // 獲取選擇內(nèi)容
              const rangeClone=range.cloneContents()
              // 判斷選擇內(nèi)容里面有沒有節(jié)點(diǎn)
              if (rangeClone.childElementCount > 0) {
                // 創(chuàng)建 div 標(biāo)簽
                const container=document.createElement('div')
                // div 標(biāo)簽 append 復(fù)制節(jié)點(diǎn)
                container.appendChild(rangeClone)
                // 如果復(fù)制的內(nèi)容長(zhǎng)度為 0
                if (!selection.toString().trim().length) {
                  // 判斷是否有選擇特殊節(jié)點(diǎn)
                  const isSpNode=hasSpNode(container)
                  return isSpNode
                    ? {
                        type: 'html',
                        content: container.innerHTML
                      }
                    : null
                }
                return {
                  type: 'html',
                  content: container.innerHTML
                }
              } else {
                return selection.toString().trim().length
                  ? {
                      type: 'text',
                      content: selection.toString().trim()
                    }
                  : null
              }
            } else {
              return null
            }
          }
          /**
           * 判斷是否包含特殊元素
           * @param {Element} parent 父元素
           * @returns {boolean} 是否包含特殊元素
           */
          const hasSpNode=(parent: Element): boolean=> {
            const nodeNameList=['iframe', 'svg', 'img', 'audio', 'video']
            const inpList=['input', 'textarea', 'select']
            return Array.from(parent.children).some((node)=> {
              if (nodeNameList.includes(node.nodeName.toLocaleLowerCase())) return true
              if (
                inpList.includes(node.nodeName.toLocaleLowerCase()) &&
                (node as HTMLInputElement).value.trim().length
              )
                return true
              if (node.children) {
                return hasSpNode(node)
              }
              return false
            })
          }

          3.2. 只需要文本

          /**
           * 獲取框選的文案內(nèi)容
           * @returns {string} 返回框選的內(nèi)容
           */
          const getSelectTextContent=(): string=> {
            const selection=window.getSelection()
            return selection?.toString().trim() || ''
          }

          4、添加事件監(jiān)聽

          // 是否時(shí)鼠標(biāo)點(diǎn)擊動(dòng)作
          let selectionchangeMouseTrack: boolean=false
          const selectionChangeFun=debounce(()=> {
            const selectContent=getSelectContent()
            console.log('selectContent', selectContent)
            // todo... 處理上報(bào)
            selectionchangeMouseTrack=false
          })
          // 添加 mousedown 監(jiān)聽事件
          document.addEventListener('mousedown', ()=> {
            selectionchangeMouseTrack=true
          })
          // 添加 mouseup 監(jiān)聽事件
          document.addEventListener(
            'mouseup',
            debounce(()=> {
              selectionChangeFun()
            }, 100)
          )
          // 添加 selectionchange 監(jiān)聽事件
          document.addEventListener(
            'selectionchange',
            debounce(()=> {
              if (selectionchangeMouseTrack) return
              selectionChangeFun()
            })
          )
          // 添加 dblclick 監(jiān)聽事件
          document.addEventListener('dblclick', ()=> {
            selectionChangeFun()
          })
          // 添加 contextmenu 監(jiān)聽事件
          document.addEventListener(
            'contextmenu',
            debounce(()=> {
              selectionChangeFun()
            })
          )

          也可以進(jìn)行封裝

          /**
           * addEventlistener function 類型
           */
          export interface IEventHandlerProps {
            [eventName: string]: EventListenerOrEventListenerObject
          }
          
          let selectionchangeMouseTrack: boolean=false
          const eventHandlers: IEventHandlerProps={
            // 鼠標(biāo) down 事件
            mousedown: ()=> {
              selectionchangeMouseTrack=true
            },
            // 鼠標(biāo) up 事件
            mouseup: debounce(()=> selectionChangeFun(), 100),
            // 選擇事件
            selectionchange:  debounce(()=> {
              if (selectionchangeMouseTrack) return
              selectionChangeFun()
            }),
            // 雙擊事件
            dblclick: ()=> selectionChangeFun(),
            // 右鍵事件
            contextmenu: debounce(()=> selectionChangeFun())
          }
          Object.keys(eventHandlers).forEach((event)=> {
            document.addEventListener(event, eventHandlers[event])
          })

          5、返回內(nèi)容

          5.1. 純文本內(nèi)容


          5.2. html 格式


          6. 完整 JS 代碼

          function debounce (fn, time=500) {
            let timeout=null; // 創(chuàng)建一個(gè)標(biāo)記用來存放定時(shí)器的返回值
            return function () {
              clearTimeout(timeout) // 每當(dāng)觸發(fā)時(shí),把前一個(gè) 定時(shí)器 clear 掉
              timeout=setTimeout(()=> { // 創(chuàng)建一個(gè)新的 定時(shí)器,并賦值給 timeout
                fn.apply(this, arguments)
              }, time)
            }
          }
          
          let selectionchangeMouseTrack=false
          document.addEventListener('mousedown', (e)=> {
            selectionchangeMouseTrack=true
            console.log('mousedown', e)
          })
          document.addEventListener('mouseup', debounce((e)=> {
            console.log('mouseup', e)
            selectionChangeFun()
          }, 100))
          document.addEventListener('selectionchange', debounce((e)=> {
            console.log('selectionchange', e)
            if (selectionchangeMouseTrack) return
            selectionChangeFun()
          }))
          document.addEventListener('dblclick', (e)=> {
            console.log('dblclick', e)
            selectionChangeFun()
          })
          document.addEventListener('contextmenu',debounce(()=> {
            selectionChangeFun()
          }))
          
          const selectionChangeFun=debounce(()=> {
            const selectContent=getSelectContent()
            selectionchangeMouseTrack=false
            console.log('selectContent', selectContent)
          })
          
          const getSelectContent=()=> {
            const selection=window.getSelection();
            if (selection) {
              // 1. 是焦點(diǎn)在 input 輸入框
              // 2. 沒有選中
              // 3. 選擇的是輸入框
              if (selection.isCollapsed) {
                return selection.toString().trim().length ? {
                  type: 'text',
                  content: selection.toString().trim()
                } : null
              }
              // 獲取選擇范圍
              const range=selection.getRangeAt(0);
              // 獲取選擇內(nèi)容
              const rangeClone=range.cloneContents()
              // 判斷選擇內(nèi)容里面有沒有節(jié)點(diǎn)
              if (rangeClone.childElementCount > 0) {
                const container=document.createElement('div');
                container.appendChild(rangeClone);
                if (!selection.toString().trim().length) {
                  const hasSpNode=getSpNode(container)
                  return hasSpNode ? {
                    type: 'html',
                    content: container.innerHTML
                  } : null
                }
                return {
                  type: 'html',
                  content: container.innerHTML
                }
              } else {
                return selection.toString().trim().length ? {
                  type: 'text',
                  content: selection.toString().trim()
                } : null
              }
            } else {
              return null
            }
          }
          
          const getSpNode=(parent)=> {
            const nodeNameList=['iframe', 'svg', 'img', 'audio', 'video']
            const inpList=['input', 'textarea', 'select']
            return Array.from(parent.children).some((node)=> {
              if (nodeNameList.includes(node.nodeName.toLocaleLowerCase())) return true
              if (inpList.includes(node.nodeName.toLocaleLowerCase()) && node.value.trim().length) return true
              if (node.children) {
                return getSpNode(node)
              }
              return false
            })
          }

          四、總結(jié)

          1. 鼠標(biāo)框選上報(bào)能監(jiān)控用戶在頁(yè)面的行為,能為后續(xù)的數(shù)據(jù)分析等提供便利
          2. 基于 JS 中的 Selection 和 Range 實(shí)現(xiàn)的,使用原生 JS
          3. 涉及到的操作比較多,包含鍵盤、鼠標(biāo)右鍵、全選等
          4. 能對(duì)框選的內(nèi)容進(jìn)行分類,區(qū)別 html 和 text,更方便的看出用戶選擇了哪些內(nèi)容

          面是承接上文的知識(shí)點(diǎn)簡(jiǎn)介:

          6.表單

          對(duì)于功能性的表單,HTML僅僅是產(chǎn)生表單的表面樣子,為后臺(tái)提供數(shù)據(jù)。

          創(chuàng)建所有表單 <form></form>

          創(chuàng)建一個(gè)滾動(dòng)菜單,size設(shè)置在需要滾動(dòng)前可以看到的表單項(xiàng)數(shù)目 <select multiple name=”NAME” size=</select>

          設(shè)置每個(gè)表單項(xiàng)的內(nèi)容 <option>

          創(chuàng)建一個(gè)下拉菜單 <select name=”NAME”></select>

          文本框區(qū)域,列的數(shù)目設(shè)置寬度,行的數(shù)目設(shè)置高度 <textarea name=”NAME” cols=40 rows=8></textarea>

          復(fù)選框,文字在標(biāo)簽后面 <input type=”checkbox” name=”NAME”>

          單選框,文字在標(biāo)簽后面 <input type=”radio” name=”NAME” value=”x”>

          單行文本輸入?yún)^(qū)域,size設(shè)置以字符計(jì)的寬度 <input type=text name=”foo” size=20>

          submit(提交)按鈕 <input type=”submit” value=”NAME”>

          使用圖象的submit(提交)按鈕 <input type=”image” border=0 name=”NAME” src=”name.gif”>

          reset(重置)按鈕 <input type=”reset”>

          本來以為后面還會(huì)有更多知識(shí)點(diǎn)可以分享給大家,誰(shuí)知都是一下雜亂無(wú)章的筆記而已

          下面我想和大家分享一下,CSS的選擇器吧

          文章如下

          在CSS中,選擇器用于選擇需要添加樣式的元素,簡(jiǎn)單的講,就是確定你要把樣式給那個(gè)元素。在我們寫web前端的時(shí)候,選擇器的使用是非常頻繁的,合理的使用選擇器會(huì)精簡(jiǎn)大量的代碼。小松果總結(jié)了下,CSS選擇器大致的歸類為基礎(chǔ)選擇器和符合選擇器兩類。

          1、基礎(chǔ)選擇器

          a、html標(biāo)簽選擇器:

          標(biāo)簽{屬性:屬性值}

          div、p、h1、span……

          b、class 類選擇器,可以共用重復(fù):

          .name {屬性:屬性值}

          標(biāo)簽中有class=”name”的元素

          c、id選擇器: 唯一性

          #name{屬性:屬性值}

          標(biāo)簽中有id=”name”的元素

          d、屬性選擇器

          *[title] {屬性:屬性值}

          所有包含標(biāo)題(title)的元素

          e、通配符選擇器,所有的元素:

          * {屬性:屬性值}

          例:* {margin:0; padding:0}

          2、復(fù)合選擇器

          a、 后代選擇器:

          A B { 屬性:屬性值}

          注:A指父級(jí)選擇器 B指子級(jí)選擇器

          b、偽類選擇器:

          a:link {屬性:屬性值} 默認(rèn)

          a:visited {屬性:屬性值} 訪問過的鏈接

          a:hover {屬性:屬性值} 鼠標(biāo)經(jīng)過

          a:active {屬性:屬性值} 激活狀態(tài)(選中時(shí)的狀態(tài))

          注:順序不能錯(cuò) l v h a,還有一個(gè)a {屬性:屬性值} ,這個(gè)也要寫,里面放超鏈接中相同屬性,不同屬性分別寫在不同的偽類選擇器中。


          主站蜘蛛池模板: 国产在线无码一区二区三区视频| 中文日韩字幕一区在线观看| 日韩有码一区二区| 91在线一区二区| 中文字幕aⅴ人妻一区二区| 亚洲综合无码一区二区痴汉 | 日韩精品无码一区二区三区不卡| 精品福利一区3d动漫| 亚洲日韩AV无码一区二区三区人 | 无码日韩AV一区二区三区| 日韩好片一区二区在线看| 国产一区二区三区久久精品| 日本强伦姧人妻一区二区 | 人妻无码一区二区三区免费| 99精品国产一区二区三区| 精品一区精品二区| 国产伦精品一区二区三区在线观看| 亚洲欧美成人一区二区三区| 国产乱码一区二区三区四| 91video国产一区| 亚洲国产韩国一区二区| 中文字幕日韩丝袜一区| 日韩精品人妻一区二区三区四区| 国产成人精品一区二区三区免费 | 理论亚洲区美一区二区三区| 国产日韩精品视频一区二区三区| 久久伊人精品一区二区三区 | 日韩AV在线不卡一区二区三区| 国产精品资源一区二区| 日本无卡码免费一区二区三区| 日韩精品一区二区三区毛片| 国产成人一区二区三区免费视频| 国产萌白酱在线一区二区| 一区二区三区日本视频| 手机看片福利一区二区三区| 免费视频精品一区二区三区| 亚洲日本va午夜中文字幕一区| 中文字幕在线一区二区在线 | 中文字幕人妻无码一区二区三区| 夜夜添无码试看一区二区三区 | 色窝窝免费一区二区三区|