Apa itu DOM Virtual?

156

Baru-baru ini, saya melihat kerangka React Facebook . Ini menggunakan konsep yang disebut "DOM Virtual", yang tidak terlalu saya mengerti.

Apa itu DOM Virtual? Apa kelebihannya?

Fizer Khan
sumber
2
Saya yakin Virtual DOM berbicara tentang node yang tidak ada di DOM normal.
Derek 朕 會 功夫
8
Saya setuju dengan sentimen di atas sehubungan dengan moderasi. Selain itu, saya yakin ini adalah pertanyaan yang sangat valid dan berguna. "DOM Virtual" sering kali direferensikan, tetapi jarang ditentukan.
btiernay
@Rachael: Sumber daya yang Anda tautkan tidak berisi kata "DOM Virtual" dan tidak menjelaskan manfaatnya. Jadi ini tidak terlalu membantu menjawab pertanyaan OP.
blerontin

Jawaban:

214

React membuat pohon objek khusus yang mewakili bagian dari DOM. Misalnya, alih-alih membuat elemen DIV aktual yang berisi elemen UL, ia membuat objek React.div yang berisi objek React.ul. Itu dapat memanipulasi objek ini dengan sangat cepat tanpa benar-benar menyentuh DOM asli atau melalui API DOM. Kemudian, saat merender komponen, ia menggunakan DOM virtual ini untuk mencari tahu apa yang perlu dilakukan dengan DOM asli untuk mencocokkan kedua pohon.

Anda dapat menganggap DOM virtual seperti cetak biru. Ini berisi semua detail yang diperlukan untuk membangun DOM, tetapi karena tidak memerlukan semua bagian kelas berat yang masuk ke DOM asli, itu dapat dibuat dan diubah dengan lebih mudah.

Membuang
sumber
2
Bisakah ini digunakan untuk seluruh DOM, bukan hanya sebagian saja?
hipkiss
8
Ini pada dasarnya abstraksi atas abstraksi yang pada akhirnya bereaksi apa itu mencari referensi di pohon model objeknya, pilih node nyata di html dan bermain-main dengannya. Suaranya bagus virtual dom, tapi tidak mewah dan berlebihan.
syarul
2
Apa yang Anda maksud dengan "tidak memerlukan semua komponen kelas berat yang masuk ke DOM asli" - komponen kelas berat?
Ajay S
2
@AjayS memanipulasi DOM asli sangat tidak efisien, itulah mengapa disebut API berat. Memanipulasi objek dalam memori jauh lebih cepat dan lebih efisien, memperbarui bagian DOM yang berubah juga lebih efisien dan lebih cepat.
jcubic
46

Mari kita ambil contoh - meskipun sangat naif: Jika Anda memiliki sesuatu yang kacau di sebuah ruangan di rumah Anda dan Anda perlu membersihkannya, apa langkah pertama Anda? Apakah Anda akan membersihkan kamar Anda yang berantakan atau seluruh rumah? Jawabannya pasti bahwa Anda hanya akan membersihkan ruangan yang membutuhkan pembersihan. Itulah yang dilakukan DOM virtual.

JS biasa melintasi atau merender seluruh DOM alih-alih hanya merender bagian yang memerlukan perubahan.

Jadi setiap kali Anda memiliki perubahan, seperti jika Anda ingin menambahkan yang lain <div>ke DOM Anda, maka DOM virtual akan dibuat yang sebenarnya tidak melakukan perubahan apa pun pada DOM yang sebenarnya. Sekarang dengan DOM virtual ini, Anda akan memeriksa perbedaan antara DOM ini dan DOM Anda saat ini. Dan hanya bagian yang berbeda (dalam hal ini yang baru <div>) yang akan ditambahkan alih-alih merender ulang seluruh DOM.

pengguna5341372
sumber
23

Apa itu DOM virtual?

DOM virtual adalah representasi dalam memori dari elemen DOM asli yang dihasilkan oleh komponen React sebelum perubahan apa pun dilakukan pada halaman.

masukkan deskripsi gambar di sini

Ini adalah langkah yang terjadi antara fungsi render yang dipanggil dan tampilan elemen di layar.

Metode render komponen mengembalikan beberapa markup, tetapi ini belum menjadi HTML final. Ini adalah representasi dalam memori dari apa yang akan menjadi elemen nyata (ini adalah langkah 1). Kemudian output itu akan diubah menjadi HTML nyata, yang akan ditampilkan di browser (Ini adalah langkah 2).

Jadi mengapa melalui semua ini untuk menghasilkan DOM virtual? Jawaban sederhana - Inilah yang memungkinkan bereaksi menjadi cepat. Ini dilakukan dengan menggunakan DOM virtual diffing. Membandingkan dua pohon virtual - lama dan baru - dan hanya membuat perubahan yang diperlukan ke DOM asli.

Sumber dari Intro To React # 2

Neri Barakat
sumber
19

A virtual DOM(VDOM) bukanlah konsep baru: https://github.com/Matt-Esch/virtual-dom .

VDOM secara strategis memperbarui DOM tanpa menggambar ulang semua node dalam satu aplikasi halaman. Menemukan simpul dalam struktur pohon itu mudah tetapi pohon DOM untuk aplikasi SPA bisa sangat besar. Menemukan dan memperbarui node / node jika terjadi suatu peristiwa tidak efisien waktu.

VDOM memecahkan masalah ini dengan membuat abstraksi tingkat tinggi dari dom aktual. VDOM adalah representasi pohon dalam memori ringan tingkat tinggi dari DOM sebenarnya.

Misalnya, pertimbangkan untuk menambahkan node di DOM; react, simpan salinan VDOM di memori

  1. Buat VDOM dengan status baru
  2. Bandingkan dengan VDOM lama yang menggunakan diffing.
  3. Perbarui hanya node yang berbeda di DOM nyata.
  4. Tetapkan VDOM baru sebagai VDOM lama.
Hitesh Sahu
sumber
label tinggi atau tingkat tinggi?
Dushman
8

Ini adalah deskripsi singkat dan pengulangan dari Virtual DOM yang sering disebutkan bersama ReactJS.

DOM (Document Object Model) merupakan abstraksi dari teks terstruktur, artinya terbuat dari kode HTML dan css. Elemen HTML ini menjadi node di DOM. Ada batasan pada metode manipulasi DOM sebelumnya. Virtual DOM adalah abstraksi dari DOM HTML literal yang dibuat dengan baik sebelum React dibuat atau digunakan, tetapi untuk tujuan kami, kami akan menggunakannya bersama dengan ReactJS. Virtual DOM ringan dan terlepas dari implementasi DOM di browser. Virtual DOM pada dasarnya adalah tangkapan layar (atau salinan) DOM pada waktu tertentu. Cara untuk melihatnya dari perspektif pengembang adalah DOM adalah lingkungan produksi dan DOM Virtual adalah lingkungan lokal (dev). Setiap kali data berubah dalam aplikasi React, representasi DOM Virtual baru dari antarmuka pengguna dibuat.

Metode paling dasar yang diperlukan untuk membuat komponen statis di ReactJS adalah:

Anda harus mengembalikan kode dari metode render. Anda harus mengonversi setiap kelas menjadi className karena kelas merupakan kata yang dipesan dalam JavaScript. Selain perubahan yang lebih besar, ada perbedaan kecil antara kedua DOM termasuk tiga atribut yang muncul di Virtual DOM tetapi tidak di HTML DOM (key, ref dan hazardouslySetInnerHTML).

Satu hal penting untuk dipahami saat bekerja dengan DOM Virtual adalah perbedaan antara ReactElement dan ReactComponent.

ReactElement

  • ReactElement adalah representasi virtual dari Elemen DOM yang ringan, tanpa kewarganegaraan, tidak dapat diubah.
  • ReactElement - Ini adalah tipe utama di React dan berada di Virtual DOM.
  • ReactElements dapat dirender menjadi HTML DOM

    var root = React.createElement('div'); ReactDOM.render(root, document.getElementById('example'));

  • JSX mengkompilasi tag HTML ke dalam ReactElements

    var root = <div/>; ReactDOM.render(root, document.getElementById('example'));

ReactComponent

  • ReactComponent - ReactComponent adalah komponen stateful.
  • React.createClass dianggap sebagai ReactComponent.
  • Setiap kali status berubah, komponen dirender ulang.

Setiap kali ReactComponent mengalami perubahan status, kami ingin perubahan sesedikit mungkin pada HTML DOM sehingga ReactComponent diubah menjadi ReactElement yang kemudian dapat dimasukkan ke Virtual DOM, dibandingkan dan diperbarui dengan cepat dan mudah.

Ketika React mengetahui perbedaannya - itu diubah menjadi kode level rendah (HTML DOM), yang dieksekusi di DOM.

esewalson
sumber
4

Ini adalah konsep yang rapi: alih-alih memanipulasi DOM secara langsung, yang rawan kesalahan dan bergantung pada keadaan yang bisa berubah, Anda malah mengeluarkan nilai yang disebut DOM Virtual. The Virtual DOM kemudian diff dengan keadaan saat DOM, yang menghasilkan daftar operasi DOM yang akan membuat DOM terlihat saat ini seperti yang baru. Operasi tersebut diterapkan dengan cepat dalam satu batch.

Diambil dari sini.

laksys
sumber
2

Virtual DOM adalah abstraksi dari DOM HTML yang secara selektif membuat subpohon node berdasarkan perubahan status. Itu melakukan manipulasi DOM sesedikit mungkin untuk menjaga komponen Anda tetap mutakhir.

Nikhil
sumber
Apa hubungannya dengan abstraksi? kata abstraksi tidak relevan di sini
eladcm
0

Virtual Dom membuat satu salinan Dom. Dom virtual dibandingkan dengan dom, dan dom virtual hanya memperbarui bagian dalam dom yang berubah. itu tidak merender seluruh dom itu hanya mengubah bagian terbaru dari dom in dom. Ini sangat memakan waktu dan dari fungsi ini, aplikasi kami bekerja dengan cepat.

mansi joshi
sumber
0

Semua jawabannya bagus. Saya baru saja datang dengan sebuah analogi yang mungkin bisa memberikan metafora dunia nyata.

DOM yang sebenarnya seperti kamar Anda, node adalah furnitur di kamar Anda. DOM virtual seperti kita menggambar cetak biru ruangan saat ini.

Kita semua memiliki pengalaman memindahkan furnitur, itu sangat melelahkan (Konsepnya sama seperti memperbarui tampilan di komputer). Oleh karena itu, setiap kali kami ingin mengubah posisi / menambah furnitur (node), kami hanya ingin melakukan perubahan yang sangat diperlukan.

Cetak biru datang untuk menyelamatkan untuk mencapainya. Kami menggambar cetak biru baru dan membandingkan perbedaannya dengan yang asli. Ini memberi tahu kami bagian mana yang telah diubah dan bagian mana yang tetap sama. Kami kemudian melakukan perubahan yang diperlukan ke ruang nyata (memperbarui node yang diubah pada DOM asli). Hore.

(Beberapa mungkin berpikir, mengapa kita harus mengandalkan yang virtual dan tidak langsung membandingkan DOM asli? Nah, dalam analogi, membandingkan DOM asli berarti Anda harus membuat ruang nyata lain dan membandingkannya dengan yang asli . Itu terlalu mahal.)

KunYu Tsai
sumber
0

Unit struktural React adalah komponen. Setiap komponen memiliki status. Setiap kali status komponen diubah, React mengubah pohon V-DOM. Setelah itu, versi terbaru V-DOM dibandingkan dengan versi V-DOM sebelumnya. Setelah perhitungan ini (berbeda), ketika React mengetahui objek V-DOM mana yang telah diubah, React hanya memodifikasi objek-objek tersebut di R-DOM.

Dalam istilah awam,

Katakanlah saya telah menambahkan elemen div di DOM, React membuat salinan V-DOM tanpa mengubah seluruh R-DOM. V-DOM yang baru dibuat ini dibandingkan dengan V-DOM yang lebih lama. Itu hanya memperbarui node yang berbeda di DOM nyata. Sekarang V-DOM yang baru dibuat dianggap sebagai versi sebelumnya untuk V-DOM mendatang.

PS 1. Jadi Tidak seperti js biasa Seluruh versi baru dari V-DOM dibuat dan R-DOM sebagian diperbarui. 2. React tidak mengupdate setiap perubahan status, melainkan update ke R-DOM dikirim dalam batch.

Koushik Pan
sumber
0

Menurut dokumen React: https://reactjs.org/docs/faq-internals.html#what-is-the-virtual-dom

'Di dunia React, istilah "DOM virtual" biasanya dikaitkan dengan elemen React karena mereka adalah objek yang mewakili antarmuka pengguna. '

import React, { Component } from 'react'; //You need to do this inside a module to import

class App extends Component{
   render(){
       return (
       <button>Hi</button> //This returns a virtual DOM
       )
   }
}

Kode di dalam return sebenarnya adalah panggilan ke fungsi React.createElement:

//render can be rewritten like this:
render(){
   return [
            React.createElement(
                'button',
                {
                    key: null,
                    ref: null,           
                },
                'Hi',
            )
   ]
}

yang mengembalikan sesuatu seperti ini:

{
  $$typeof: Symbol.for('react.element'), 
  type: "button", 
  key: null, 
  ref: null, 
  props: { 
     children: 'Hi',
  }
}

dan ini DOM virtual. Ini adalah objek JavaScript yang biayanya jauh lebih murah untuk dimanipulasi daripada elemen DOM sebenarnya yang dibuat oleh

document.createElement('button');

yang juga merupakan objek JavaScript terlihat seperti ini:

accessKey: ""
ariaAtomic: null
ariaAutoComplete: null
ariaBusy: null
ariaChecked: null
ariaColCount: null
ariaColIndex: null
ariaColSpan: null
ariaCurrent: null
ariaDescription: null
ariaDisabled: null
ariaExpanded: null
ariaHasPopup: null
ariaHidden: null
ariaKeyShortcuts: null
ariaLabel: null
ariaLevel: null
ariaLive: null
ariaModal: null
ariaMultiLine: null
ariaMultiSelectable: null
ariaOrientation: null
ariaPlaceholder: null
ariaPosInSet: null
ariaPressed: null
ariaReadOnly: null
ariaRelevant: null
ariaRequired: null
ariaRoleDescription: null
ariaRowCount: null
ariaRowIndex: null
ariaRowSpan: null
ariaSelected: null
ariaSetSize: null
ariaSort: null
ariaValueMax: null
ariaValueMin: null
ariaValueNow: null
ariaValueText: null
assignedSlot: null
attributeStyleMap: StylePropertyMap {size: 0}
attributes: NamedNodeMap {length: 0}
autocapitalize: ""
autofocus: false
baseURI: "http://localhost:3000/"
childElementCount: 0
childNodes: NodeList []
children: HTMLCollection []
classList: DOMTokenList [value: ""]
className: ""
clientHeight: 0
clientLeft: 0
clientTop: 0
clientWidth: 0
contentEditable: "inherit"
dataset: DOMStringMap {}
dir: ""
disabled: false
draggable: false
elementTiming: ""
enterKeyHint: ""
firstChild: null
firstElementChild: null
form: null
formAction: "http://localhost:3000/"
formEnctype: ""
formMethod: ""
formNoValidate: false
formTarget: ""
hidden: false
id: ""
innerHTML: ""
innerText: ""
inputMode: ""
isConnected: false
isContentEditable: false
labels: NodeList []
lang: ""
lastChild: null
lastElementChild: null
localName: "button"
name: ""
namespaceURI: "http://www.w3.org/1999/xhtml"
nextElementSibling: null
nextSibling: null
nodeName: "BUTTON"
nodeType: 1
nodeValue: null
nonce: ""
offsetHeight: 0
offsetLeft: 0
offsetParent: null
offsetTop: 0
offsetWidth: 0
onabort: null
onanimationend: null
onanimationiteration: null
onanimationstart: null
onauxclick: null
onbeforecopy: null
onbeforecut: null
onbeforepaste: null
onbeforexrselect: null
onblur: null
oncancel: null
oncanplay: null
oncanplaythrough: null
onchange: null
onclick: null
onclose: null
oncontextmenu: null
oncopy: null
oncuechange: null
oncut: null
ondblclick: null
ondrag: null
ondragend: null
ondragenter: null
ondragleave: null
ondragover: null
ondragstart: null
ondrop: null
ondurationchange: null
onemptied: null
onended: null
onerror: null
onfocus: null
onformdata: null
onfullscreenchange: null
onfullscreenerror: null
ongotpointercapture: null
oninput: null
oninvalid: null
onkeydown: null
onkeypress: null
onkeyup: null
onload: null
onloadeddata: null
onloadedmetadata: null
onloadstart: null
onlostpointercapture: null
onmousedown: null
onmouseenter: null
onmouseleave: null
onmousemove: null
onmouseout: null
onmouseover: null
onmouseup: null
onmousewheel: null
onpaste: null
onpause: null
onplay: null
onplaying: null
onpointercancel: null
onpointerdown: null
onpointerenter: null
onpointerleave: null
onpointermove: null
onpointerout: null
onpointerover: null
onpointerrawupdate: null
onpointerup: null
onprogress: null
onratechange: null
onreset: null
onresize: null
onscroll: null
onsearch: null
onseeked: null
onseeking: null
onselect: null
onselectionchange: null
onselectstart: null
onstalled: null
onsubmit: null
onsuspend: null
ontimeupdate: null
ontoggle: null
ontransitionend: null
onvolumechange: null
onwaiting: null
onwebkitanimationend: null
onwebkitanimationiteration: null
onwebkitanimationstart: null
onwebkitfullscreenchange: null
onwebkitfullscreenerror: null
onwebkittransitionend: null
onwheel: null
outerHTML: "<button></button>"
outerText: ""
ownerDocument: document
parentElement: null
parentNode: null
part: DOMTokenList [value: ""]
prefix: null
previousElementSibling: null
previousSibling: null
scrollHeight: 0
scrollLeft: 0
scrollTop: 0
scrollWidth: 0
shadowRoot: null
slot: ""
spellcheck: true
style: CSSStyleDeclaration {alignContent: "", alignItems: "", alignSelf: "", alignmentBaseline: "", all: "", …}
tabIndex: 0
tagName: "BUTTON"
textContent: ""
title: ""
translate: true
type: "submit"
validationMessage: ""
validity: ValidityState {valueMissing: false, typeMismatch: false, patternMismatch: false, tooLong: false, tooShort: false, …}
value: ""
willValidate: true

Anda dapat mempelajari lebih lanjut tentang DOM virtual dan React di https://indepth.dev/inside-fiber-in-depth-overview-of-the-new-reconciliation-algorithm-in-react/

Toffee Conmigo
sumber
-1

mari kita membuat ketertiban dan masuk akal dalam masalah ini. React (atau library lainnya) adalah "layer" pada javascript.

Tidak ada yang namanya dom virtual, ada dom yang tidak terikat.

izinkan saya menjelaskan dalam javascript sederhana:

 let vDom = {};     // this is a object that will be used to hold the elements

 let d = document.createElement('div');
 d.innerHTML = 'hi, i am a new div';

 vDom['newDiv'] = d;

pada titik ini kami telah membuat Div yang tidak ditampilkan di dom, karena belum terpasang

tetapi kita dapat mengaksesnya, menambahkan atribut, nilai, mengubah dll.

setelah kami memanggil: (misalnya, tambahkan ke tubuh)

    document.body.appendChild(vDom['newDiv'])

maka kita akan melihatnya;

 for one how saw javascript libs come and go , i suggest to any one 
 to do one simple thing : master JAVAscript, not layers :)
eladcm.dll
sumber
1
"Tidak ada yang namanya dom virtual" - Ada. Ini adalah fitur inti dari cara kerja React. Jawaban yang diterima atas pertanyaan ini menjelaskannya dengan cukup baik.
Quentin
Jawaban Anda sebenarnya mendeskripsikan DOM asli. DOM asli ada setelah Anda memanggil document.createElement, tidak peduli apakah itu telah ditambahkan.
Toffee Conmigo