ekstrak semua konten teks di htmlcollection ke array dengan javascript

Sep 08 2020

Ini data mentahnya

anycasestr = "<div style="color: rgb(51, 51, 51); background-color: rgb(253, 246, 227); font-family: Menlo, Monaco, &quot;Courier New&quot;, monospace; font-size: 12px; line-height: 18px;"><div>refinement</div><div>decent</div><div>elegant</div></div>";

untuk mengekstrak semua konten teks menjadi larik seperti ["refinement", "decent", "elegant"]

Saya menulis kode ini (jquery telah dimasukkan)

htmlObject = $(anycasestr);
arr = Array.prototype.slice.call(htmlObject[0].getElementsByTagName("div"));
arr_page = [];
for (i = 0; i < 3; i++) {
    arr_page.push(arr[i].textContent);
}

Itu menghasilkan apa yang saya inginkan.

Saya hanya prihatin jika itu diterapkan dengan cara yang elegan. Bisakah seseorang melihatnya?

Misalnya, haruskah saya menggunakan xpath atau sesuatu, dalam hal komputasi?

Jawaban

3 CertainPerformance Sep 08 2020 at 08:12

Deklarasikan variabel Anda - setiap kali Anda menetapkan atau mereferensikan variabel tanpa mendefinisikannya terlebih dahulu, Anda akan (1) secara implisit membuat properti pada objek global (yang dapat mengakibatkan bug aneh), atau (2) membuat kesalahan, jika Anda sedang berjalan dalam mode ketat. Saat ini Anda tidak menentukan variabel Anda. Perbaiki dengan meletakkan const(atau, bila perlu, let) di depan mereka saat menugaskan untuk pertama kali, mis const htmlObject = $(anycasestr);.

jQuery atau metode DOM? Anda menggunakan jQuery untuk mengubah string menjadi kumpulan elemen jQuery, tetapi kemudian Anda menggunakan getElementsByTagNameuntuk memilih turunan. Jika Anda menggunakan jQuery, Anda dapat ringkas dan konsisten untuk menggunakannya untuk memilih <div>turunan .. Untuk menemukan turunan dari elemen yang cocok dengan nama tag tertentu, panggil .findkoleksi jQuery - kemudian, Anda dapat menggunakan .mapuntuk mengubah ditemukan elemen jQuery menjadi kumpulan teks dari elemen:

const $parent = $(anycasestr); const arr = $parent.find('div')
  .map((_, child) => child.textContent)
  .get(); // turn the jQuery collection of strings into an array of strings

const anycasestr = `<div style="color: rgb(51, 51, 51); background-color: rgb(253, 246, 227); font-family: Menlo, Monaco, &quot;Courier New&quot;, monospace; font-size: 12px; line-height: 18px;"><div>refinement</div><div>decent</div><div>elegant</div></div>`;
const $parent = $(anycasestr);
const arr = $parent.find('div')
  .map((_, child) => child.textContent)
  .get(); // turn the jQuery collection of strings into an array of strings
console.log(arr);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Atau, Anda dapat menggunakan DOMParser sebagai gantinya. Menggunakan DOMParser daripada jQuery untuk mengubah teks menjadi kumpulan elemen dapat menghindari eksekusi skrip berbahaya yang tidak disengaja. Contoh eksploitasi menggunakan jQuery:

const anycasestr = `<img src="" onerror="alert('evil')">`;
const $parent = $(anycasestr);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Dengan DOMParser:

const anycasestr = `<div style="color: rgb(51, 51, 51); background-color: rgb(253, 246, 227); font-family: Menlo, Monaco, &quot;Courier New&quot;, monospace; font-size: 12px; line-height: 18px;"><div>refinement</div><div>decent</div><div>elegant</div></div>`;
const doc = new DOMParser().parseFromString(anycasestr, 'text/html');
const arr = [...doc.querySelectorAll('div > div')]
  .map(div => div.textContent);
console.log(arr);

String kueri div > divmemilih <div>elemen yang merupakan turunan langsung dari yang lain <div>. Ini bekerja dengan cara yang persis sama seperti pemilih CSS. querySelectorAlladalah alat yang hebat untuk pemilihan elemen yang ringkas - ini bisa lebih mudah untuk ditulis dan dipahami dalam sekejap daripada metode lain (seperti yang asli htmlObject[0].getElementsByTagName("div")).

Array.prototype.slice.callagak bertele-tele - di lingkungan non-kuno, Anda dapat menggunakan sintaks penyebaran sebagai gantinya, seperti yang saya lakukan di atas. Membuat sebuah array sekaligus dengan pemetaan juga lebih elegan daripada mendeklarasikan sebuah array kemudian .pushmemasukkannya ke dalamnya.

Jika Anda memiliki lebih banyak <div>anak dan hanya ingin mengambil teks dari 3 yang pertama, itu akan lebih berfungsi .slicepada larik elemen daripada menempatkan jumlah iterasi dalam satu forlingkaran:

const anycasestr = `<div style="color: rgb(51, 51, 51); background-color: rgb(253, 246, 227); font-family: Menlo, Monaco, &quot;Courier New&quot;, monospace; font-size: 12px; line-height: 18px;">
  <div>refinement</div>
  <div>decent</div>
  <div>elegant</div>
  <div>don't include me</div>
  <div>don't include me</div>
  <div>don't include me</div>
</div>`;
const doc = new DOMParser().parseFromString(anycasestr, 'text/html');
const arr = [...doc.querySelectorAll('div > div')]
  .slice(0, 3)
  .map(div => div.textContent);
console.log(arr);

dalam hal komputasi?

Kecuali jika hal-hal yang perlu diurai terlalu besar , kinerja untuk hal semacam ini tidak menjadi perhatian; lebih baik menulis kode yang bersih, dapat dibaca, dan dapat dipelihara. Jika kemudian Anda menemukan bahwa sesuatu membutuhkan waktu lebih lama untuk dijalankan daripada yang ideal, Anda dapat mengidentifikasi kemacetan lalu mencari cara untuk memperbaikinya. (Tapi ini hampir pasti tidak akan menjadi hambatan.)