成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

?如何用JS實現(xiàn)“劃詞高亮”的在線筆記功能??

trigkit4 / 1188人閱讀

1. 什么是“劃詞高亮”?

有些同學(xué)可能不太清楚“劃詞高亮”是指什么,下面就是一個典型的“劃詞高亮”:

上圖的示例網(wǎng)站可以點擊這里訪問。用戶選擇一段文本(即劃詞),即會自動將這段選取的文本添加高亮背景,用戶可以很方便地為網(wǎng)頁添加在線筆記。

筆者前段時間為線上業(yè)務(wù)實現(xiàn)了一個與內(nèi)容結(jié)構(gòu)非耦合的文本高亮在線筆記功能。非耦合是指不需要為高亮功能建立特殊的頁面 DOM 結(jié)構(gòu),而高亮功能對業(yè)務(wù)近乎透明。該功能核心部分具有較強的通用性與移植性,故拿出來和大家分享交流一下。

本文具體的核心代碼已封裝成獨立庫 web-highlighter,閱讀中如有疑問可參考其中代碼↓↓。
2. 實現(xiàn)“劃詞高亮”需要解決哪些問題?

實現(xiàn)一個“劃詞高亮”的在線筆記功能需要解決的核心問題有兩個:

加高亮背景。即如何根據(jù)用戶在網(wǎng)頁上的選取,為相應(yīng)的文本添加高亮背景;

高亮區(qū)域的持久化與還原。即如何保存用戶高亮信息,并在下次瀏覽時準確還原,否則下次打開頁面用戶高亮的信息就丟失了。

一般來說,劃詞高亮的業(yè)務(wù)需求方主要是針對自己產(chǎn)出的內(nèi)容,你可以比較容易對內(nèi)容在網(wǎng)頁上的排版、HTML 標簽等方面進行控制。這種情況下,處理高亮需求會更方便一些,畢竟自己可以根據(jù)高亮需求調(diào)整現(xiàn)有內(nèi)容的 HTML。

而筆者面對的情況是,頁面 HTML 排版結(jié)構(gòu)復(fù)雜,且無法根據(jù)高亮需求來推動業(yè)務(wù)改動 HTML。這也催生出了對解決方案更通用化的要求,目標就是:針對任意內(nèi)容均可“劃詞高亮”并支持后續(xù)訪問時還原高亮狀態(tài),而不用去關(guān)心內(nèi)容的組織結(jié)構(gòu)

下面就來具體說說,如何解決上面的兩個核心問題。

3. 如何“加高亮背景”?

根據(jù)動圖演示我們可以知道,用戶選擇某一段文本(下文稱為“用戶選區(qū)”)后,我們會給這段文本加一個高亮背景。

例如用戶選擇了上圖中的文本(即藍色部分)。為其加高亮的基本思路如下:

獲取選中的文本節(jié)點:通過用戶選擇的區(qū)域信息,獲取所有被選中的所有文本節(jié)點;

為文本節(jié)點添加背景色:給這些文本節(jié)點包裹一層新的元素,該元素具有指定的背景顏色。

3.1. 如何獲取選中的文本節(jié)點? 1)Selection API

需要基于瀏覽器為我們提供的 Selection API 。它的兼容性還不錯。如果要支持更低版本的瀏覽器則需要用 polyfill。

Selection API 可以返回一系列關(guān)于用戶選區(qū)的信息。那么是不是可以通過它直接獲取選取中的所有 DOM 元素呢?

很遺憾并不能。但好在它可以返回選區(qū)的首尾節(jié)點信息:

const range = window.getSelection().getRangeAt(0);
const start = {
    node: range.startContainer,
    offset: range.startOffset
};
const end = {
    node: range.endContainer,
    offset: range.endOffset
};

Range 對象包含了選區(qū)的開始與結(jié)束信息,其中包括節(jié)點(node)與文本偏移量(offset)。節(jié)點信息不用多說,這里解釋一下 offset 是指什么:例如,標簽

這是一段文本的示例

,用戶選取的部分是“一段文本”這四個字,這時首尾的 node 均為 p 元素內(nèi)的文本節(jié)點(Text Node),而 startOffset 和 endOffset 分別為 2 和 6。

2)首尾文本節(jié)點拆分

理解了 offset 的概念后,自然就發(fā)現(xiàn)有個問題需要解決。由于用戶選區(qū)(selection)可能只包含一個文本節(jié)點的一部分(即 offset 不為 0),所以我們最后得到的用戶選區(qū)所包含的節(jié)點里,也只希望有首尾文本節(jié)點的這“一部分”。對此,我們可以使用 .splitText() 拆分文本節(jié)點:

// 首節(jié)點
if (curNode === $startNode) {
    if (curNode.nodeType === 3) {
        curNode.splitText(startOffset);
        const node = curNode.nextSibling;
        selectedNodes.push(node);
    }
}

// 尾節(jié)點
if (curNode === $endNode) {
    if (curNode.nodeType === 3) {
        const node = curNode;
        node.splitText(endOffset);
        selectedNodes.push(node);
    }
}

以上代碼會依據(jù) offset 對文本節(jié)點進行拆分。對于開始節(jié)點,只需要收集它的后半部分;而對于結(jié)束節(jié)點則是前半部分。

3)遍歷 DOM 樹

到目前為止,我們準確找到了首尾節(jié)點,所以下一步就是找出“中間”所有的文本節(jié)點。這就需要遍歷 DOM 樹。

“中間”加上引號是因為,在視覺上這些節(jié)點是位于首尾之間的,但由于 DOM 不是線性結(jié)構(gòu)而是樹形結(jié)構(gòu),所以這個“中間”換成程序語言,就是指深度優(yōu)先遍歷時,位于首尾兩節(jié)點之間的所有文本節(jié)點。DFS 的方法有很多,可以遞歸,也可以用棧+循環(huán),這里就不贅述了。

需要提一下的是,由于我們是要為文本節(jié)點添加高亮背景,因此在遍歷時只會收集文本節(jié)點。

if (curNode.nodeType === 3) {
    selectedNodes.push(curNode);
}
3.2. 如何為文本節(jié)點添加背景色?

這一步本身并不困難。在上一步的基礎(chǔ)上,我們已經(jīng)選出了所有被用戶選中的 文本節(jié)點(包括拆分后的首尾節(jié)點)。對此,一個最直接的方法就是為其“包裹上”一個帶背景樣式的元素。

具體的,我們可以給每個文本節(jié)點外加上一個 class 為 highlight 元素;而背景樣式則通過 CSS .highlight 選擇器設(shè)置。

// 使用上一步中封裝的方法獲取選區(qū)內(nèi)的文本節(jié)點
const nodes = getSelectedNodes(start, end);

nodes.forEach(node => {
    const wrap = document.createElement("span");
    wrap.setAttribute("class", "highlight");
    wrap.appendChild(node.cloneNode(false));
    node.parentNode.replaceChild(wrap);
});
.highlight {
    background: #ff9;
}

這樣就可以給被選中的文字添加一個“永久”的高亮背景了。

p.s. 選區(qū)的重合問題

然而,文本高亮里還有一個比較棘手的需求 —— 高亮區(qū)域的重合。舉個例子,最開始的演示圖(下圖)里,第一個高亮區(qū)域和第二個高亮區(qū)域之間存在重疊部分,即“本區(qū)域高”四個字。

這個問題目前來看似乎還不是問題,但在結(jié)合下面要提到的一些功能與需求時,就會變成非常麻煩,甚至無法正常運行(一些開源庫這塊處理也不盡如人意,這也是沒有選擇它們的一個原因)。這里簡單提一下,具體的情況我會放到后續(xù)對應(yīng)的地方再詳細說。

4. 如何實現(xiàn)高亮選區(qū)的持久化與還原?

到目前我們已經(jīng)可以給選中的文本添加高亮背景了。但還有一個大問題:

想象一下,用戶辛辛苦苦劃了很多重點(高亮),開心地退出頁面后,下次訪問時發(fā)現(xiàn)這些都不能保存時,該有多么得沮喪。因此,如果只是在頁面上做“一次性”的文本高亮,那它的使用價值會大大降低。這也就促使我們的“劃詞高亮”功能要能夠保存(持久化)這些高亮選區(qū)并正確還原。

持久化高亮選區(qū)的核心是找到一種合適的 DOM 節(jié)點序列化方法。

通過第三部分可以知道,當(dāng)確定了首尾節(jié)點與文本偏移(offset)信息后,即可為其間文本節(jié)點添加背景色。其中,offset 是數(shù)值類型,要在服務(wù)器保存它自然沒有問題;但是 DOM 節(jié)點不同,在瀏覽器中保存它只需要賦值給一個變量,但想在后端保存所謂的 DOM 則不那么直接了。

4.1 序列化 DOM 節(jié)點標識

所以這里的核心點就是找到一種方法,能夠定位 DOM 節(jié)點,同時可以被保存成普通的 JSON Object,用以傳給后端保存,這個過程在本文中被稱為 DOM 標識 的“序列化”。而下次用戶訪問時,又可以從后端取回,然后“反序列化”為對應(yīng)的 DOM 節(jié)點。

有幾種常見的方式來標識 DOM 節(jié)點:

使用 xPath

使用 CSS Selector 語法

使用 tagName + index

這里選擇了使用第三種方式來快速實現(xiàn)。需要注意一點,我們通過 Selection API 取到的首尾節(jié)點一般是文本節(jié)點,而這里要記錄的 tagName 和 index 都是該文本節(jié)點的父元素節(jié)點(Element Node)的,而 childIndex 表示該文本節(jié)點是其父親的第幾個兒子:

function serialize(textNode, root = document) {
    const node = textNode.parentElement;
    let childIndex = -1;
    for (let i = 0; i < node.childNodes.length; i++) {
        if (textNode === node.childNodes[i]) {
            childIndex = i;
            break;
        }
    }
    
    const tagName = node.tagName;
    const list = root.getElementsByTagName(tagName);
    for (let index = 0; index < list.length; index++) {
        if (node === list[index]) {
            return {tagName, index, childIndex};
        }
    }
    return {tagName, index: -1, childIndex};
}

通過該方法返回的信息,再加上 offset 信息,即定位選取的起始位置,同時也完全可發(fā)送給后端進行保存了。

4.2 反序列化 DOM 節(jié)點

基于上一節(jié)的序列化方法,從后端獲取到數(shù)據(jù)后,可以很容易反序列化為 DOM 節(jié)點:

function deSerialize(meta, root = document) {
    const {tagName, index, childIndex} = meta;
    const parent = root.getElementsByTagName(tagName)[index];
    return parent.childNodes[childIndex];
}

至此,我們大體已經(jīng)解決了兩個核心問題,這似乎已經(jīng)是一個可用版本了。但其實不然,根據(jù)實踐經(jīng)驗,如果僅僅是上面這些處理,往往是無法應(yīng)對實際需求的,存在一些“致命問題”。

但不用灰心,下面會具體來說說所謂的“致命問題”是什么,而又是如何解決并實現(xiàn)一個線上業(yè)務(wù)可用的通用“劃詞高亮”功能的。

5. 如何實現(xiàn)一個生產(chǎn)環(huán)境可用的“劃詞高亮”? 1)上面的方案有什么問題?

首先來看看上面的方案會有什么問題。

當(dāng)我們需要高亮文本時,會為文本節(jié)點包裹span元素,這就改動了頁面的 DOM 結(jié)構(gòu)。它可能會導(dǎo)致后續(xù)高亮的首尾節(jié)點與其 offset 信息其實是基于被改動后的 DOM 結(jié)構(gòu)的。帶來的結(jié)果有兩個:

下次訪問時,程序必須按上次用戶高亮的順序還原。

用戶不能隨意取消(刪除)高亮區(qū)域,只能按添加順序從后往前刪。

否則,就會有部分的高亮選區(qū)在還原時無法定位到正確的元素。

文字可能不好理解,下面我舉個例子來直觀解釋下這個問題。

非常高興今天能夠在這里和大家分享一下文本高亮(在線筆記)的實現(xiàn)方式。

對于上面這段 HTML,用戶分別按順序高亮了兩個部分:“高興”和“文本高亮”。那么按照上面的實現(xiàn)方式,這段 HTML 變成了下面這樣:

非常 高興 今天能夠在這里和大家分享一下 文本高亮 (在線筆記)的實現(xiàn)方式。

對應(yīng)的兩個序列化數(shù)據(jù)分別為:

// “高興”兩個字被高亮?xí)r獲取的序列化信息
{
    start: {
        tagName: "p",
        index: 0,
        childIndex: 0,
        offset: 2
    },
    end: {
        tagName: "p",
        index: 0,
        childIndex: 0,
        offset: 4
    }
}
// “文本高亮”四個字被高亮?xí)r獲取的序列化信息。
// 這時候由于p下面已經(jīng)存在了一個高亮信息(即“高興”)。
// 所以其內(nèi)部 HTML 結(jié)構(gòu)已被修改,直觀來說就是 childNodes 改變了。
// 進而,childIndex屬性由于前一個 span 元素的加入,變?yōu)榱?2。
{
    start: {
        tagName: "p",
        index: 0,
        childIndex: 2,
        offset: 14
    },
    end: {
        tagName: "p",
        index: 0,
        childIndex: 2,
        offset: 18
    }
}

可以看到,“文本高亮”這四個字的首尾節(jié)點的 childIndex 都被記為 2,這是由于前一個高亮區(qū)域改變了

元素下的DOM結(jié)構(gòu)。如果此時“高興”選區(qū)的高亮被用戶取消,那么下次再訪問頁面就無法還原高亮了 —— “高興”選區(qū)的高亮被取消了,

下自然就不會出現(xiàn)第三個 childNode,那么 childIndex 為 2 就找不到對應(yīng)的節(jié)點了。這就導(dǎo)致存儲的數(shù)據(jù)在還原高亮選區(qū)時出現(xiàn)問題。

此外,還記得在第三部分末尾提到的高亮選取重合問題么?支持選取重合很容易出現(xiàn)如下的包裹元素嵌套情況:

非常 高興 今天能夠在這里和大家分享一下 文本 高亮 (在線筆記)的實現(xiàn)方式。

這也使得某個文本區(qū)域經(jīng)過多次高亮、取消高亮后,會出現(xiàn)與原 HTML 頁面不同的復(fù)雜嵌套結(jié)構(gòu)。可以預(yù)見,當(dāng)我們使用 xpath 或 CSS selector 作為 DOM 標識時,上面提到的問題也會出現(xiàn),同時也使其他需求的實現(xiàn)更加復(fù)雜。

到這里可以提一下其他開源庫或產(chǎn)品是如何處理選區(qū)重合問題的:

開源庫 Rangy 有一個 Highlighter 模塊可以實現(xiàn)文本高亮,但其對于選區(qū)重合的情況是將兩個選區(qū)直接合并了,這是不合符我們業(yè)務(wù)需求的。

付費產(chǎn)品 Diigo 直接不允許選區(qū)的重合。

Medium.com 是支持選區(qū)重合的,體驗非常不錯,這也是我們產(chǎn)品的目標。但它頁面的內(nèi)容區(qū)結(jié)構(gòu)相較我面對的情況會更簡單與更可控。

所以如何解決這些問題呢?

2)另一種序列化 / 反序列化方式

我會對第四部分提到的序列化方式進行改進。仍然記錄文本節(jié)點的父節(jié)點 tagName 與 index,但不再記錄文本節(jié)點在 childNodes 中的 index 與 offset,而是記錄開始(結(jié)束)位置在整個父元素節(jié)點中的文本偏移量。

例如下面這段 HTML:

非常 高興 今天能夠在這里和大家分享一下 文本高亮 (在線筆記)的實現(xiàn)方式。

對于“文本高亮”這個高亮選區(qū),之前用于標識文本起始位置的信息為childIndex = 2, offset = 14。而現(xiàn)在變?yōu)?b>offset = 18(從

元素下第一個文本“非”開始計算,經(jīng)過18個字符后是“文”)。可以看出,這樣表示的優(yōu)點是,不管

內(nèi)部原有的文本節(jié)點被(包裹)節(jié)點如何分割,都不會影響高亮選區(qū)還原時的節(jié)點定位。

據(jù)此,在序列化時,我們需要一個方法來將文本節(jié)點內(nèi)偏移量“翻譯”為其對應(yīng)的父節(jié)點內(nèi)部的總體文本偏移量:

function getTextPreOffset(root, text) {
    const nodeStack = [root];
    let curNode = null;
    let offset = 0;
    while (curNode = nodeStack.pop()) {
        const children = curNode.childNodes;
        for (let i = children.length - 1; i >= 0; i--) {
            nodeStack.push(children[i]);
        }

        if (curNode.nodeType === 3 && curNode !== text) {
            offset += curNode.textContent.length;
        }
        else if (curNode.nodeType === 3) {
            break;
        }
    }

    return offset;
}

而還原高亮選區(qū)時,需要一個對應(yīng)的逆過程:

function getTextChildByOffset(parent, offset) {
    const nodeStack = [parent];
    let curNode = null;
    let curOffset = 0;
    let startOffset = 0;
    while (curNode = nodeStack.pop()) {
        const children = curNode.childNodes;
        for (let i = children.length - 1; i >= 0; i--) {
            nodeStack.push(children[i]);
        }
        if (curNode.nodeType === 3) {
            startOffset = offset - curOffset;
            curOffset += curNode.textContent.length;
            if (curOffset >= offset) {
                break;
            }
        }
    }
    if (!curNode) {
        curNode = parent;
    }
    return {node: curNode, offset: startOffset};
}
3)支持高亮選區(qū)的重合

重合的高亮選區(qū)帶來的一個問題就是高亮包裹元素的嵌套,從而使得 DOM 結(jié)構(gòu)會有較復(fù)雜的變動,增加了其他功能(交互)實現(xiàn)與問題排查的復(fù)雜度。因此,我在 3.2. 節(jié)提到的包裹高亮元素時,會再進行一些稍復(fù)雜的處理(尤其是重合選區(qū)),以保證盡量復(fù)用已有的包裹元素,避免元素的嵌套。

在處理時,將需要包裹的各個文本片段(Text Node)分為三類情況:

完全未被包裹,則直接包裹該部分。

屬于被包裹過的文本節(jié)點的一部分,則使用.splitText()將其拆分。

是一段完全被包裹的文本段,不需要對節(jié)點進行處理。

于此同時,為每個選區(qū)生成唯一 ID,將該段文本幾點多對應(yīng)的 ID、以及其由于選區(qū)重合所涉及到的其他 ID,都附加包裹元素上。因此像上面的第三種情況,不需要變更 DOM 結(jié)構(gòu),只用更新包裹元素兩類 ID 所對應(yīng)的 dataset 屬性即可。

6. 其他問題

解決以上的一些問題后,“文本劃詞高亮”就基本可用了。還剩下一些“小修補”,簡單提一下。

6.1. 高亮選區(qū)的交互事件,例如 click、hover

首先,可以為每個高亮選區(qū)生成一個唯一 ID,然后在該選區(qū)內(nèi)所有的包裹元素上記錄該 ID 信息,例如用data-highlight-id屬性。而對于選取重合的部分可以在data-highlight-extra-id屬性中記錄重合的其他選區(qū)的 ID。

而監(jiān)聽到包裹元素的 click、hover 后,則觸發(fā) highlighter 的相應(yīng)事件,并帶上高亮 ID。

6.2. 取消高亮(高亮背景的刪除)

由于在包裹時支持選區(qū)重合(對應(yīng)會有上面提到的三種情況需要處理),因此,在刪除選取高亮?xí)r,也會有三種情況需要分別處理:

直接刪除包裹元素。即不存在選區(qū)重合。

更新data-highlight-id屬性和data-highlight-extra-id屬性。即刪除的高亮 ID 與 data-highlight-id 相同。

只更新data-highlight-extra-id屬性。即刪除的高亮 ID 只在 data-highlight-extra-id 中。

6.3. 對于前端生成的動態(tài)頁面怎么辦?

不難發(fā)現(xiàn),這種非耦合的文本高亮功能很依賴于頁面的 DOM 結(jié)構(gòu),需要保證做高亮?xí)r的 DOM 結(jié)構(gòu)和還原時的一致,否則無法正確還原出選區(qū)的起始節(jié)點位置。據(jù)此,對“劃詞”高亮最友好的應(yīng)該是純后端渲染的頁面,在onload監(jiān)聽中觸發(fā)高亮選區(qū)還原的方法即可。但目前越來越多的頁面(或頁面的一部分)是前端動態(tài)生成的,針對這個問題該怎么處理呢?

我在實際工作中也遇到了類似問題 —— 頁面的很多區(qū)域是 ajax 請求后前端渲染的。我的處理方式包括如下:

隔離變化范圍。將上述代碼中的“根節(jié)點”從documentElement換為另一個更具體的容器元素。例如我面對的業(yè)務(wù)會在 id 為 article-container

內(nèi)加載動態(tài)內(nèi)容,那么我就會指定這個 article-container 為“根節(jié)點”。這樣可以最大程度防止外部的 DOM 變動影響到高亮位置的定位,尤其是頁面改版。

確定高亮選區(qū)的還原時機。由于內(nèi)容可能是動態(tài)生成,所以需要等到該部分的 DOM 渲染完成后再調(diào)用還原方法。如果有暴露的監(jiān)聽事件可以在監(jiān)聽內(nèi)處理;或者通過 MutationObserver 監(jiān)聽標志性元素來判斷該部分是否加載完成。

記錄業(yè)務(wù)內(nèi)容信息,應(yīng)對內(nèi)容區(qū)改版。內(nèi)容區(qū)的 DOM 結(jié)構(gòu)更改算是“毀滅性打擊”。如何確實有該類情況,可以嘗試讓業(yè)務(wù)內(nèi)容展示方將段落信息等具體的內(nèi)容信息綁定在 DOM 元素上,而我在高亮?xí)r取出這些信息來冗余存儲,改版后可以通過這些內(nèi)容信息“刷”一遍存儲的數(shù)據(jù)。

6.4. 其他

篇幅問題,還有其他細節(jié)的問題就不在這篇文章里分享了。詳細內(nèi)容可以參考 web-highlighter 這個倉庫里的實現(xiàn)。

7. 總結(jié)

本文先從“劃詞高亮”功能的兩個核心問題(如何高亮用戶選區(qū)的文本、如何將高亮選區(qū)還原)切入,基于 Selection API、深度優(yōu)先遍歷和 DOM 節(jié)點標識的序列化這些手段實現(xiàn)了“劃詞高亮”的核心功能。然而,該方案仍然存在一些實際問題,因此在第 5 部分進一步給出了相應(yīng)的解決方案。

基于實際開發(fā)的經(jīng)驗,我發(fā)現(xiàn)解決上述幾個“劃詞高亮”核心問題的代碼具有一定通用性,因此把核心部分的源碼封裝成了獨立的庫 web-highlighter,托管在 github,也可以通過 npm 安裝。

其已服務(wù)于線上產(chǎn)品業(yè)務(wù),基本的高亮功能一行代碼即可開啟:

(new Highlighter()).run();

兼容IE 10/11、Edge、Firefox 52+、Chrome 15+、Safari 5.1+、Opera 15+。

感興趣的小伙伴可以 star 一下。感謝支持,歡迎交流

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/103845.html

相關(guān)文章

  • 學(xué)習(xí)實踐 - 收藏集 - 掘金

    摘要:官網(wǎng)地址聊天機器人插件開發(fā)實例教程一創(chuàng)建插件在系統(tǒng)技巧使你的更加專業(yè)前端掘金一個幫你提升技巧的收藏集。我會簡單基于的簡潔視頻播放器組件前端掘金使用和實現(xiàn)購物車場景前端掘金本文是上篇文章的序章,一直想有機會再次實踐下。 2道面試題:輸入URL按回車&HTTP2 - 掘金通過幾輪面試,我發(fā)現(xiàn)真正那種問答的技術(shù)面,寫一堆項目真不如去刷技術(shù)文章作用大,因此刷了一段時間的博客和掘金,整理下曾經(jīng)被...

    mikyou 評論0 收藏0
  • 何用輕量協(xié)作工具做bug管理

    摘要:秉持著是騾子是馬拉出來溜溜的心態(tài),我注冊賬號試用了一下他給我的第一印象是簡單和,這些團隊協(xié)作工具一樣,也是一款基于的在線管理工具,沒有在一開始就讓我的安裝包恐懼癥發(fā)作。如何做版本管理第一個要說的,就是目標功能了。 對于一個團隊來說,工作效率的高低很大程度上取決于團隊的管理。 而作為一名剛接觸測試職位的新人來說,如何把一堆堆雜亂不堪的bug管理得井井有條,無疑是最重要的。 我之前一直覺得...

    genefy 評論0 收藏0
  • 前端每日實戰(zhàn):116# 視頻演示何用 CSS 和原生 JS 開發(fā)一個監(jiān)控網(wǎng)絡(luò)連接狀態(tài)頁面

    摘要:定義在線狀態(tài)主題類似地,定義離線狀態(tài)主題創(chuàng)建一個函數(shù),用于根據(jù)在線離線狀態(tài)顯示不同的主題現(xiàn)在,關(guān)掉連接,然后刷新頁面,頁面會采用紅色主題再打開連接,然后刷新頁面,頁面會采用綠色主題。 showImg(https://segmentfault.com/img/bVbfQmV?w=400&h=305); 效果預(yù)覽 按下右側(cè)的點擊預(yù)覽按鈕可以在當(dāng)前頁面預(yù)覽,點擊鏈接可以全屏預(yù)覽。 https...

    LinkedME2016 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<