Khi bạn sử dụng các phương thức như getElementsByClassName
hoặc querySelectorAll
, chúng sẽ trả về một HTMLCollection hoặc NodeList tương ứng thay vì một Mảng
HTMLCollection chứa các phần tử HTML trong khi NodeList tiến xa hơn một vài bước, nó không chỉ trả về danh sách các phần tử HTML mà còn có thể trả về các Nút như TextNode và có thêm các phương thức list NodeList. cho mỗi
Để thảo luận chi tiết hơn về chủ đề này, bạn có thể đọc bài đăng stackoverflow này có tên. Sự khác biệt giữa HTMLCollection, NodeList và Array
Tại sao chuyển đổi chúng thành một Mảng?
Lý do duy nhất để chuyển đổi HTMLCollection và NodeList thành Array là nếu bạn muốn sử dụng các hàm bậc cao hơn như forEach, map, filter và reduce
Chẳng hạn, có rất nhiều trường hợp sử dụng, giả sử bạn có các phần tử chứa thuộc tính data-src
cùng với lớp lazy-load
. Nếu bạn muốn truy cập vào data-src
và lọc ra tất cả các phần tử không có data-src
hoặc trống, bạn có thể làm như sau
Trường hợp sử dụng
var lazyLoadables = [...document.querySelectorAll['.lazy-load']]
.filter[[element] => element.getAttribute['data-src'].trim[]];
lazyLoadImages[lazyLoadables];
Vào chế độ toàn màn hình Thoát chế độ toàn màn hình
Bằng cách này, bạn đảm bảo chỉ chuyển các phần tử có nguồn cần được tải khi được yêu cầu
Giả sử DOM được mô tả trong đoạn mã bên dưới, yêu cầu của tôi là lấy một mảng javascript của tất cả các nút con của container
div
...
...
...
...
Trong những ngày jQuery tốt, bạn chỉ có thể làm $['.divy']
hoặc $['#container'].children[]
Tôi đã cố gắng làm điều tương tự bằng cách sử dụng API bộ chọn DOM gốc và thật bất ngờ
const childDivs = tài liệu. truy vấnSelectorAll['. divy']
Mảng. isArray[childDivs] //=> falsechildDivs. người xây dựng. tên //=> NodeList
Được rồi, hãy thử một trong các phương thức của getElementsByClassName
0 và kiểm tra những gì được trả về
const childDivsAgain = tài liệu. getElementsByClassName['divy']
Mảng. isArray[childDivs] //=> falsechildDivs. người xây dựng. tên //=> HTMLCollection
Bây giờ các đối tượng getElementsByClassName
1 và getElementsByClassName
2 là gì và tại sao chúng ta không nhận được mảng javascript đơn giản từ các phương thức này?
Trước tiên, hãy cố gắng hiểu sự khác biệt giữa HTMLCollection và NodeList
Một HTMLCollection là một danh sách các nút. Một nút riêng lẻ có thể được truy cập bằng chỉ mục thứ tự hoặc tên của nút hoặc thuộc tính id
Các bộ sưu tập trong HTML DOM được giả định là đang hoạt động, nghĩa là chúng được tự động cập nhật khi tài liệu cơ bản thay đổi
Bộ sưu tập HTML luôn ở “trong DOM”, trong khi NodeList là một cấu trúc chung hơn có thể có hoặc không có trong DOM
Một đối tượng NodeList là một tập hợp các nút. Giao diện NodeList cung cấp sự trừu tượng của một tập hợp các nút được sắp xếp theo thứ tự, mà không xác định hoặc hạn chế cách thực hiện tập hợp này. Các đối tượng NodeList trong DOM đang hoạt động hoặc tĩnh dựa trên giao diện được sử dụng để truy xuất chúng
Hãy kiểm tra đặc tả với mã có liên quan để hiểu thêm
hãy để parentDiv = tài liệu. getElementById['vùng chứa']
hãy để nodeListDivs = tài liệu. truy vấnSelectorAll['. divy']hãy để htmlCollectionDivs = tài liệu. getElementsByClassName['divy']
nútListDivs. chiều dài //=> 4htmlBộ sưu tậpDivs. chiều dài //=> 4
// nối con mới vào containervar newDiv = document. createElement['div'];newDiv. className = 'divy'parentDiv. appendChild[newDiv]
nútListDivs. chiều dài //=> 4htmlBộ sưu tậpDivs. chiều dài //=> 5
Chúng ta có thể thấy rằng HTMLCollection đang hoạt động theo đúng nghĩa đen, theo nghĩa là mọi thay đổi đối với DOM đều được cập nhật tự động và có sẵn trong bộ sưu tập
Không phải tất cả các đối tượng NodeList đều tĩnh. Ví dụ: getElementsByClassName
3 sẽ trả về một NodeList trực tiếp
Nhưng hãy nhớ rằng cả getElementsByClassName
2 và getElementsByClassName
1 đều không hỗ trợ các phương thức nguyên mẫu mảng như phương thức getElementsByClassName
6 $['.divy']
0 hoặc $['.divy']
1. Mặc dù vậy, các phương thức trình lặp như $['.divy']
2 đã được thêm vào gần đây và các trình duyệt mới nhất có thể hỗ trợ chúng
Tôi đã biết về sự khác biệt này, khi tôi đang cố gắng sử dụng thư viện kéo và thả dragula để thêm các thành phần đã chọn vào thư viện
hãy để draggableLists = tài liệu. querySelectorAll['div. có thể kéo được']dragula[dragableLists];
Điều này sẽ không hoạt động như mong đợi vì hàm tạo $['.divy']
3 mong đợi một mảng javascript và chúng tôi đang chuyển một NodeList cho nó
Để chuyển đổi đối tượng NodeList hoặc HTMLCollection thành mảng javascript, bạn có thể thực hiện một trong các thao tác sau
Sử dụng mảng. từ phương pháp
const nodelist = tài liệu. querySelectorAll[‘. divy']const divyArray = Mảng. từ[nodelist]
Sử dụng mảng. nguyên mẫu. lát cắt
const nodelist = tài liệu. querySelectorAll[‘. divy']const divyArray = Mảng. nguyên mẫu. lát cắt. cuộc gọi [nodelist]
cách ES6
Và tôi thích cái này. Nếu bạn đang sử dụng ES6, bạn chỉ cần sử dụng toán tử trải rộng
const divyArray = […tài liệu. querySelectorAll[‘. divy’]]
Bây giờ, hãy áp dụng điều đó cho api dragula để làm cho nó hoạt động
dragula[[. tài liệu. querySelectorAll['div. có thể kéo được']]]
Vậy khi nào bạn thực sự chuyển đổi NodeList thành một mảng? . Nếu bạn thực sự muốn một trình vòng lặp tới DOM được cập nhật mới nhất mọi lúc, bạn nên sử dụng getElementsByClassName
1 hoặc getElementsByClassName
2 mà không cần chuyển đổi nó thành một mảng