Web技巧(13)

任何一門語言都有本身的小技巧和新特性,好比Web的三大基石HTML、CSS和JavaScript,在各自的社區中老是有同窗在不一樣的時候梳理一些相關的新特性和小技巧。讓這些特性更好的服務於社區,儘可能的讓你們更好的理解和掌握。另一個目的是,讓更多的同窗能把這些新特性運用於本身的項目中。在這一期中,將圍繞着JavaScript的一些新特性來展開。但願對你們有所幫助。javascript

ES2019中的新特性

在即將發佈的ES2019中,會發布一些新特性,好比Object.fromEntries()trimStart()trimEnd()flat()flatMap()symbol等。在這一節中,使用一些小示例來向你們展現一下這些小特性的使用。css

下面幾個ES2019新特性來自@Faraz Kelhini的《5 ES2019 features you can use today》一文。html

Object.fromEntries()

在JavaScript中會碰到數據格式之間的轉換,前幾天整理的《使用JavaScript的一些小技巧》一文中就有提到一些數據之間的相互轉換。在ES2019中,若是想讓Object轉換成Arrays可使用Object.fromEntries()java

在ES2017中使用Object.entries()方法將一個對象轉換成數組,好比:web

const obj = {
    one: 1,
    two: 2,
    three: 3
}

console.log(Object.entries(obj))
// ⇒ [["one", 1], ["two", 2], ["three", 3]]
複製代碼

obj傳遞給Object.entries(),返回objectenumerablestring-keyed屬性匹配的[key,value]。在ES2019中推薦使用Object.fromEntries()來實現相似的功能。該靜態方法能夠很容易地實現一列[key, value]轉換成Object。好比:正則表達式

const Array = [['one',1],['two',2],['three',3]]

console.log(Object.fromEntries(Array))
// ⇒ {one: 1, two: 2, three: 3}
複製代碼

若是不使用Object.fromEntries()方法要實現反轉Object.entries()操做,事情會稍微複雜一些:算法

const myArray = [['one', 1], ['two', 2], ['three', 3]]
const obj = Array.from(myArray).reduce((acc, [key, val]) => Object.assign(acc, {[key]:val}), {})

console.log(obj)
// ⇒ {one: 1, two: 2, three: 3}
複製代碼

在使用Object.fromEntries()時有一點須要注意,入參能夠是任何具備可迭代屬性的對象,而且返回兩個元素的數組對象。好比下面這個示例:windows

const map = new Map()
map.set('one', 1)
map.set('two', 2)
map.set('three', 3)

const obj = Object.fromEntries(map)

console.log(obj)
// ⇒ {one: 1, two: 2, three: 3}
複製代碼

使用Object.fromEntries()方法來轉換對象一樣頗有用:跨域

const obj = {
    'one': 2,
    'two': 4,
    'three': 9
}

// 將對象轉換爲數組(ES2017中的特性)
const arr = Object.entries(obj)
console.log(arr)
// ⇒ [["one", 2], ["two", 4], ["three", 9]]

// 求這些數的平方根
const map = arr.map(([key, val]) => [key, Math.sqrt(val)])
console.log(map)
// ⇒ [["one", 1.4142135623730951], ["two", 2], ["three", 3]]

// 將數組轉換回對象
const newObj = Object.fromEntries(map)
console.log(newObj);
// ⇒ {one: 1.4142135623730951, two: 2, three: 3}
複製代碼

該方法還有一個方便的用途,處理urlquery查詢參數的時候:數組

const paramsString = '?&userName="damo"&userId="98409189"';
const searchParams = new URLSearchParams(paramsString);
console.log(searchParams);
// ⇒ URLSearchParams {}

const urlQueryObj = Object.fromEntries(searchParams);
console.log(urlQueryObj);
// ⇒ {userName: ""damo"", userId: ""98409189""}
複製代碼

Object.fromEntries()Object.entries()的反向操做,可用於克隆對象

另外,Object.fromEntries()方法嵌入式對象和數組都只是引用:

const obj = {
    name: '大漠',
    blog: 'W3cplus',
    age: 30,
    deepCopy: {
        mutateMe: true
    }
}

const entries = Object.entries(obj)
console.log(entries)
// ⇒ [["name", "大漠"], ["blog", "W3cplus"], ["age", 30], ["deepCopy", {mutateMe: false}]]

const fromEntries = Object.fromEntries(entries)
console.log(fromEntries)
// ⇒ {name: "大漠", blog: "W3cplus", age: 30, deepCopy: {mutateMe: false}}

console.log(obj.deepCopy.mutateMe)
// ⇒ true

fromEntries.deepCopy.mutateMe = false
console.log(obj.deepCopy.mutateMe)
// ⇒ false
複製代碼

trimStart()和trimEnd()

trimStart()trimEnd()方法從技術角度上看與trimLeft()trimRight()類似,而且將會與padStart()padEnd()具備一致標準:

const str = '      string        '

console.log(str.trimStart())    // ⇒ 'string        '
console.log(str.trimEnd())      // ⇒ '      string'

console.log(str.trimLeft())     // ⇒ 'string        '
console.log(str.trimRight())    // ⇒ '      string'
複製代碼

爲了與padStart()padEnd()標準一致性,ES2019提出trimStart()trimEnd()trimStart()trimEnd()是做爲trimLeft()trimRight()的別名。

flat()和flatMap()

flat()方法能夠把一個多維數組拍平轉換爲一個新的一維數組:

const arr = [
    ['one', 1],
    ['two', 2],
    ['three', 3],
    4,
    [
        'five',
        [
            'six',
            6
        ],
        5
    ]
]

const flatArray = arr.flat()
console.log(flatArray)
// ⇒ ["one", 1, "two", 2, "three", 3, 4, "five", ["six", 6], 5]
複製代碼

flat()能夠接受一個可選的參數,用來指定解構嵌套層級數,其默認值爲1,好比說上面的arr數組,要徹底拍平成一個一維數組,能夠給flat()傳一個2

const flatArray2 = arr.flat(2)
console.log(flatArray2)
// ⇒ ["one", 1, "two", 2, "three", 3, 4, "five", "six", 6, 5]
複製代碼

在這以前,要把一個多維數組拍平成一個一維數組,可能須要使用reduce()concat()兩個方法:

[].concat.apply([], arr);
// ⇒ ["one", 1, "two", 2, "three", 3, 4, "five", ["six", 6], 5]

[].concat.apply([], [].concat.apply([], arr))
// ⇒ ["one", 1, "two", 2, "three", 3, 4, "five", "six", 6, 5]
複製代碼

在JavaScript中,若是要把一個二維數組拍平成一個一維數組,還可使用...運算符,好比:

[].concat(...arr)
// ⇒ ["one", 1, "two", 2, "three", 3, 4, "five", ["six", 6], 5]

const arr2 = [].concat(...arr)
[].concat(...arr2)
// ⇒ ["one", 1, "two", 2, "three", 3, 4, "five", "six", 6, 5]
複製代碼

注意,在使用flat()方法時有一點要注意,若是數組中有多個空值時,使用flat()來轉換數組時,將會把空值丟棄:

const arr = ['a', , , , 'b', ['c', , , 'd'], 'e']
const flatArray = arr.flat()
console.log(flatArray)
// ⇒ ["a", "b", "c", "d", "e"]
複製代碼

flatMap()方法組合了map()flat()兩個方法,可是它的回調是返回一個數組,而且最終結果將會被展現爲一個一維數組,而不是嵌套數組。

const scattered = ['my favorite', 'hamburger', 'is a', 'chicken sandwich']

// 使用map()來轉換數組
const huh = scattered.map(chunk => chunk.split(' '))
console.log(huh);
// ⇒ [["my", "favorite"], ["hamburger"], ["is", "a"], ["chicken", "sandwich"]]

// 使用flat()來拍平數組
const flatHuh = huh.flat()
console.log(flatHuh)
// ⇒ ["my", "favorite", "hamburger", "is", "a", "chicken", "sandwich"]

// 使用flatMap能夠一步到位實現map()和flat()的效果
const flatMapScattered = scattered.flatMap(chunk => chunk.split(' '))
console.log(flatMapScattered)
// ⇒ ["my", "favorite", "hamburger", "is", "a", "chicken", "sandwich"]
複製代碼

Symbol對象的描述屬性

當建立一個Symbol對象時,爲了方便調試,ES2019給Symbol對象增長了一個只讀描述屬性。

let sym = Symbol('foo')
console.log(sym.description)
// ⇒ foo

sym = Symbol()
console.log(sym.description)
// ⇒ undefined

// 建立一個全局的Symbol
sym = Symbol.for('bar')
console.log(sym.description)
// ⇒ bar
複製代碼

可選的catch()

catch()綁定在try...catch()方法塊中將不會被使用:

try {
    // 使用瀏覽器可能沒有實現的功能
} catch (unused) {
    // 回到已經實現的特性
}
複製代碼

unused在這段代碼中並無被使用到。在ES2019中,開發者能夠忽略catch()綁定:

try {
    // 使用瀏覽器可能沒有實現的功能
} catch {
    // 作一些與拋出的值無關的事情
}
複製代碼

下面幾個ES2019新特性來自@David Neal的《What's New in JavaScript for 2019》一文。

對JavaScript類的更改

ES2019對於類有不少建議的更改,包括字段聲明私有方法和字段靜態方法和字段。下面是關於這些更改的示例:

class Truck extends Automobile {
    model = "Heavy Duty";   // public field declaration
    #numberOfSeats = 5;     // private field declaration
    #isCrewCab = true;
    static #name = "Truck"; // static private field declaration

    // static method
    static formattedName() {
        // Notice that the Truck class name is used
        // to access the static field instead of "this"
        return `This vehicle is a ${ Truck.#name }.`;
    }

    constructor( model, seats = 2 ) {
        super();
        this.seats = seats;
    }

    // Private method
    #getBodyType() {
        return this.#isCrewCab ? "Crew Cab" : "Standard Cab";
    }

    bodyType() {
        return `${ this.#numberOfSeats }-passenger ${ this.model } ${ this.#getBodyType() }`;
    }

    get seats() { 
        return this.#numberOfSeats; 
    }

    set seats( value ) {
        if ( value >= 1 && value < 7 ) {
            this.#numberOfSeats = value;
            this.#isCrewCab = value > 3;
        }
    }
}
複製代碼

用BigInt來表示更大的數值

在ES2019中可使用BigInt來表示比253次方更大的數值。BigInt能夠用一些不一樣的方式來聲明:

const theBiggestIntegerToday = Number.MAX_SAFE_INTEGER // ⇒ 9007199254740991

// 使用n語法聲明一個BigInt
const ABiggerInteger = 9100000000000001n               // ⇒ 9100000000000001n

// 使用BigInt()構造函數聲明一個BigInt
const EventBiggerInteger = BigInt(9100000000000002)    // ⇒ 9100000000000002n

// 使用BigInt()構建函數聲明一個BigInt,並傳一個字符串
const SuchBiggerInteger = BigInt('9100000000000003')   // ⇒ 9100000000000003n
複製代碼

有關於BigInt更多的用例和陷阱相關的信息能夠點擊這裏查閱

function.toString()

這個ES2019特性來自於@satansdeer的《What's New in ES10? Javascript Features ES2019》一文。

ES2019修改了function.toString()的返回值,能夠返回精確的字符串,包括空格和註釋。

ES2019前,使用function.toString():

function App() {/* var */}

App.toString();
// ⇒ function App() {}
複製代碼

在ES2019中,則變成:

function App() {
/* var */
var h = 'hello';
}

App.toString();
// ⇒ "function App() {
// ⇒   /* var */
// ⇒   var h = 'hello';
// ⇒ }"
複製代碼

下面幾個ES2019特性來自@Rienz Otiong的《8 NEW FEATURES in JavaScript ES2019》一文。

JSON超集

JSON字符串能夠包含未轉義的U + 2028行分隔符 和 U + 2029段落分隔符,而 ECMAScript 字符串則不能。在 ES2019 以前,它會產生錯誤SyntaxError: Invalid or unexpected token

const LS = eval('"\u2028"');
const PS = eval("'\u2029'");
複製代碼

格式良好的JSON.stringify

ES2019 不是將未配對的代理代碼點做爲單個 UTF-16 代碼單元返回,而是用 JSON 轉義序列表示它們:

// Before
console.log(JSON.stringify("\uD800")); // ⇒ "�"

// Now ES2019
console.log(JSON.stringify("\uD800")); // ⇒ "\ud800"
複製代碼

下面幾個ES2019特性來自@Sergey Podgornyy的《ECMAScript 10 - JavaScript this year》一文。

string.prototype.matchAll()

.matchAll()將返回全部匹配,而不是單個匹配。在.matchAll()以前,要返回多個匹配則會使用String.match正則表達式帶上/g標籤。

const searchString = 'olololo'

searchString.match(/o/)
// ⇒ ["o", index: 0, input: "olololo", groups: undefined]

searchString.match(/o/g)
// ⇒ ["o", "o", "o", "o"]

searchString.matchAll(/o/)
// ⇒ {_r: /o/g, _s: "olololo"}
複製代碼

.matchAll()返回了iterator,因此咱們用for ... of處理它:

for (const item of searchString.matchAll(/o/)) {
    console.log(item);
}
// ⇒ ["o", index: 0, input: "olololo", groups: undefined]
// ⇒ ["o", index: 2, input: "olololo", groups: undefined]
// ⇒ ["o", index: 4, input: "olololo", groups: undefined]
// ⇒ ["o", index: 6, input: "olololo", groups: undefined]
複製代碼

.matchAll()已經隱含了/g。使用.matchAll()不須要再帶上/g

.matchAll()的參數必須是正則表達式,不然會拋出異常:

searchString.matchAll('o')
// ⇒ Uncaught TypeError: o is not a regexp!
複製代碼

RegExp特性

JavaScript中不推薦RegExp特性,即構造函數的靜態屬性,如RegExp.$1以及RegExp.prototype.compile方法。在ES2019中,對於適當的RegExp的子類以及跨域RegExp的實例,禁用RegExp靜態屬性和RegExp.prototype.compile

動態 import

如今能夠將導入分配給一個變量:

import(`./language-packs/${navigator.language}.js`);
複製代碼

動態import是一個異步操做。它返回一個Promise,即在加載一個模塊以後,將它返回給回調函數。所以,新的綁定只能在async函數中:

element.addEventListener('click', async () => {
    const module = await import(`./eventsScripts/buttonClickEvent.js`);
    module.clickEvent();
});
複製代碼

它看起來像對import()函數的調用,但不是從Function.prototype中繼承的。這意味着它將不可能經過callapply來調用:

import.call("example this", "argument")
// ⇒ Uncaught SyntaxError: Unexpected identifier
複製代碼

穩定的Array.prototype.sort()

一個穩定的排序算法是當兩個具備相等鍵的對象在排序輸出中以與未排序輸入中出現的順序相同的順序出現時。ES2019提供穩定的陣列排序:

var fruit = [
    { name: "Apple",      count: 13, },
    { name: "Pear",       count: 12, },
    { name: "Banana",     count: 12, },
    { name: "Strawberry", count: 11, },
    { name: "Cherry",     count: 11, },
    { name: "Blackberry", count: 10, },
    { name: "Pineapple",  count: 10, }
];

// Create our own sort criteria function:
let my_sort = (a, b) => a.count - b.count;

// Perform stable ES10 sort:
let sorted = fruit.sort(my_sort);
console.log(sorted);
複製代碼

標準化的 globalThis 對象

ES2019以前全局this沒有標準化。生產代碼中,你必須手動添加以下代碼來標準化多個平臺的全局對象。

var getGlobal = function () {
    if (typeof self !== 'undefined') { return self; }
    if (typeof window !== 'undefined') { return window; }
    if (typeof global !== 'undefined') { return global; }
    throw new Error('unable to locate global object');
};
複製代碼

但即便這樣也並不老是奏效。

在ES2019中添加了globalThis對象,從如今開始應該在任何平臺上訪問全局做用域:

// Access global array constructor
globalThis.Array(0, 1, 2);
// ⇒ [0, 1, 2]

// Similar to window.v = { flag: true } in <= ES5
globalThis.v = { flag: true };

console.log(globalThis.v);
// ⇒ { flag: true }
複製代碼

你不知道的DOM特性

@Louis Lazaris在他的教程《8 DOM features you didn’t know existed》中整理了8個有關於DOM操做方面的相關特性。

你確定像下面這樣給元素綁定事件:

element.addEventListener('click', doSomething, false);
複製代碼
  • click是監聽的事件
  • doSomething是一個回調函數,它將在事件發生時執行
  • false是一個名爲useCapture的布爾值,用於指示是否要使用事件冒泡和捕獲

可能你們都知道怎麼給元素綁定事件,可是,你可能不知道addEventListener()也接受第三個布爾值類型的參數替換爲另外一個新參數。這個新參數是一個看起來像這樣的options對象:

element.addEventListener('click', doSomething, {
    capture: false,
    once: true,
    passive: false
});
複製代碼

這裏定義了三個不一樣的屬性:

  • capture:一個布爾值和useCapture參數同樣
  • once:一個布爾值,若是爲true,表示事件只在目標元素上運行一次,而後被刪除
  • passive:一個布爾值,若是爲true,表示函數不會調用preventDefault(),即便它包含在函數體中

其中最有趣的是once。在不少狀況下都很是有用,能夠避免使用removeEventListener()或其餘複雜的技術來強制觸發單個事件。有點相似於jQuery中的.one()方法。

好比下面這個示例中就使用了options對象:

上面示例中的按鈕只會追回文本一次(點擊按鈕,只會觸發一次click事件)。若是將once的值設置爲false,而後屢次單擊該按鈕,則每次單擊按鈕時都會附加文本(每點一次都會觸發click事件)。

scrollTo()在窗口或元素中平滑滾動

點擊Web頁面底部「回到頂部」的按鈕,而後滾動到視窗頂部。這樣的需求常常見。但平滑的滾動會讓用戶的體驗更佳。

在《改變用戶體驗的滾動新特性》和 《滾動的特性》中探討過怎麼改善滾動體驗。

在JavaScript中,只須要使用windows.scrollTo()就能夠告訴瀏覽器滾動到頁面上指定的位置。若是爲了讓滾動具備平滑滾動的效果,能夠給window.scrollTo()設置ScrollToOptions對象,像下面這樣:

window.scrollTo({
    top: 0,
    left: 1000,
    behavior: 'smooth'
})
複製代碼

好比像下面這個Demo:

See the Pen Using Options with window.ScrollTo() by Louis Lazaris ( @impressivewebs) on CodePen.

setTimeout()和setInterval()

在不少狀況下,使用window.setTimeout()window.setInterval()執行基於時間的動畫如今已經被性能更友好的window.requestAnimationFrame()所取代。但在某些狀況下,setTimeout()setInterval()是更好的選擇。

一般,你會看到使用他們的語法是這樣的;

let timer = window.setInterval(doSomething, 3000);
function doSomething () {
    // Something happens here...
}
複製代碼

這裏setInterval()調用傳入兩個參數:回調函數時間間隔。對於setTimeout(),它將運行一次,而在本例中,它將無限期地運行,直到我傳入計時器ID,調用window.clearTimeout()清除定時器。

使用起來很簡單。 可是,若是我但願個人回調函數接受參數呢? 最近這些計時器方法容許添加如下內容:

let timer = window.setInterval(doSomething, 3000, 10, 20);
function doSomething (a, b) {
    // Something happens here…
}
複製代碼

注意,我在setInterval()調用中以添加了兩個參數。而後,doSomething()函數接受這些參數並根據須要操做它們。來看一個示例:

擴展閱讀:

單選按鈕和複選框的defaultChecked屬性

對於單選按鈕和複選框,若是但願獲取或設置checked屬性,可使用checked屬性,以下所示:

console.log(radioButton.checked); // ⇒ true
radioButton.checked = false;
console.log(radioButton.checked); // ⇒ false
複製代碼

但還有一個名爲defaultChecked的屬性,它能夠應用於單選按鈕或複選框組,來得到組中最初設置爲checked的元素是哪一個:

<form id="form">
    <input type="radio" value="one" name="setOne"> One
    <input type="radio" value="two" name="setOne" checked> Two<br />
    <input type="radio" value="three" name="setOne"> Three
</form>
複製代碼

有了這個,即便在更改了選中的單選按鈕以後,我也能夠遍歷單選框並找出初始爲checked是哪個,以下所示:

for (i of myForm.setOne) {
    if (i.defaultChecked === true) {
        console.log(‘i.value’);
    }
}
複製代碼
See the Pen defaultChecked on Radio Buttons by Louis Lazaris ( @impressivewebs) on CodePen.

該示例中的 defaultChecked 始終是單選框Two。如前所述,這也能夠經過複選框組來完成。嘗試更改HTML中的默認選中選項,而後再次嘗試點擊按鈕。

See the Pen defaultChecked on Checkboxes by Louis Lazaris ( @impressivewebs) on CodePen.

在本例中,你將注意到默認狀況下選中了兩個複選框,所以當使用 defaultChecked 查詢時,這兩個複選框都將返回 true

使用 normalize() 和 wholeText() 操做文本節點

HTML文檔中的文本節點可能比較複雜,特別是在動態插入或建立節點時。例如,若是我有如下HTML:

<p id="el">This is the initial text.</p>
複製代碼

能夠給p元素增長一個文本節點:

let el = document.getElementById('el');
el.appendChild(document.createTextNode(' Some more text.'));
console.log(el.childNodes.length); // 2
複製代碼

注意,在添加文本節點以後,我將記錄該段中子節點的長度,它表示有兩個節點。這些節點是一個文本字符串,可是由於文本是動態附加的,因此它們被視爲單獨的節點。

在某些狀況下,若是將文本做爲單個文本節點處理將會更有幫助,這使得文本更容易操做。這就是 normalize()wholeText() 發揮做用的地方。

normalize() 方法可用於合併單獨的文本節點:

el.normalize();
console.log(el.childNodes.length); // 1
複製代碼

對元素調用 normalize() 將合併該元素內的任何相鄰文本節點。若是剛好有一些HTML穿插在相鄰的文本節點中,HTML將保持原樣,而全部相鄰的文本節點將被合併。

可是,若是因爲某種緣由我想保持文本節點分開,但我仍然但願可以將文本做爲單個單元抓取,那麼這就是 wholeText() 有用的地方。 所以,我能夠在相鄰的文本節點上執行此操做,而不是調用 normalize()

console.log(el.childNodes[0].wholeText);
// This is the initial text. Some more text.
console.log(el.childNodes.length); // 2
複製代碼

只要我沒有調用 normalize(),文本節點的長度將保持爲2,而且我可使用 wholeText() 記錄整個文本。可是請注意幾點:

  • 我必須在一個文本節點上調用 wholeText,而不是元素( el.childNodes[0] 或者 el.childNodes[1])
  • 文本節點必須相鄰,中間沒有HTML分隔它們

insertAdjacentElement() 和 insertAdjacentText()

insertAdjacentHTML()容許您輕鬆地將一串文本或HTML添加到頁面中與其餘元素相關的特定位置。可是,可能您沒有注意到該規範還包含兩個相關的方法,它們以相似的方式工做: insertAdjacentElement()insertAdjacentText()

insertAdjacentHTML() 的一個缺點是插入的內容必須是字符串的形式。 所以,若是您包含HTML,則必須將其聲明爲:

el.insertAdjacentHTML('beforebegin', '<p><b>Some example</b> text goes here.</p>');
複製代碼

可是,使用 insertAdjacentElement(),第二個參數能夠是一個元素的引用,以下:

let el = document.getElementById('example'),
addEl = document.getElementById('other');
el.insertAdjacentElement('beforebegin', addEl);
複製代碼

insertAdjacentText() 方法的工做原理相似,可是所提供的文本字符串將僅做爲文本插入,即便它包含HTML。

insertAdjacentHTML() , insertAdjacentElement(), 和 insertAdjacentText() 的第一個參數相同,可取值爲:

  • beforebegin
  • afterbegin
  • beforeend
  • afterend

event.detail 屬性

當使用 addEventListener() 時,您可能須要防止函數調用中的默認瀏覽器行爲。例如,您可能想攔截 <a> 元素上的單擊,並使用JavaScript處理這些單擊。你會這樣作:

btn.addEventListener('click', function (e) {
    // do something here...
    e.preventDefault();
}, false);
複製代碼

preventDefault(),和之前的 return false 效果是同樣的。這須要將事件對象傳遞到函數中,由於該對象會調用 preventDefault() 方法。

scrollHeight 和 scrollWidth 屬性

scrollHeightscrollWidth 屬性可能聽起來很熟悉,由於您可能會將它們與其餘與寬度和高度相關的DOM功能混淆。 例如,offsetWidthoffsetHeight 屬性將返回元素的高度或寬度,而不會考慮溢出。

左邊列的 overflow 設置爲 auto,右邊列的 overflow 設置爲 hiddenoffsetHeight 屬性爲每一個屬性返回相同的值,由於它不考慮可滾動區域或隱藏區域;它只測量元素的實際高度,包括任何垂直填充和邊框。

另外一方面,名稱恰當的 scrollHeight 屬性將計算元素的所有高度,包括可滾動(或隱藏)區域:

上面的示例只是它使用了 scrollHeightto 獲取每一個列的高度。再次注意,這兩列的值是相同的。但這一次,它是一個更高的數字,由於溢出面積也被算做高度的一部分。

上面的示例主要關注元素高度,這是最多見的用例,但您也可使用 offsetWidthscrollWidth,它們將以相同的方式應用於水平滾動。

HTML能夠作什麼?

Web技巧系列第八期,主要向你們展現了CSS能作什麼?或者換句話說,如何使用純CSS的特性實現一些以往須要JavaScript才能實現的交互效果。

@ananyaneogi在《HTML can do that?》一文中向你們展現了HTML能夠作些什麼?同時她還整理了一篇有關於CSS能作什麼?但這裏不表,主要聊聊HTML能夠作什麼?

帶有可搜索文本的下拉菜單

input[type="text"]中的list值和datalist中的id綁定,能夠實現帶有可搜索文本的下拉菜單效果:

對話框

使用dialog實現對話框(模態框)效果:

See the Pen HTML only - Dialog by Ananya Neogi ( @ananyaneogi) on CodePen.

進度條

使用progressmeter製做進度條的效果:

See the Pen HTML - Progress and Meter by Ananya Neogi ( @ananyaneogi) on CodePen.

手風琴

使用detailssummary實現手風琴效果:

See the Pen HTML only - Detail & Summary by Ananya Neogi ( @ananyaneogi) on CodePen.

在移動端根據input類型喚起正確的鍵盤類型

移動端上,能夠經過inputtype類型來喚起正確的鍵盤類型:

也可使用inputinputmode屬性來喚起鍵盤類型。

在Web技巧第7期中有作過相關的介紹

高亮文本

在HTML中使用mark標籤,能夠設置文本的高亮模式:

See the Pen HTML - Highlight text by Airen ( @airen) on CodePen.

編輯頁面內容

若是給div設置contenteditable屬性,用戶能夠直接編譯div元素的內容:

See the Pen HTML - contenteditable by Ananya Neogi ( @ananyaneogi) on CodePen.

小結

在這一期中主要圍繞着一些新特性或者說很多同窗不瞭解的特性。在第一部分中主要收集了ES2019中的一些新特性,在第二部分主要圍繞着DOM操做的一些鮮爲人知的特性,第三部分是一些HTML中的特性。若是結合第7期的內容,那麼有關於JavaScript、HTML和CSS的一些特性都涉及了。但願這些整理你會感興趣,若是你在這方面有相關的經驗或收集,歡迎在下面的評論中與咱們一塊兒共享。

相關文章
相關標籤/搜索