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?
javascript
reactjs
Fizer Khan
sumber
sumber
Jawaban:
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.
sumber
virtual dom
, tapi tidak mewah dan berlebihan.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.sumber
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.
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
sumber
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
sumber
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
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
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.
sumber
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.
sumber
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.
sumber
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.
sumber
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.)
sumber
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.
sumber
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/
sumber
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 :)
sumber