Ryggradssyn og DOM Del 2

I den siste artikkelen dekket vi grunnleggende om Backbone Views og hvordan du aktiverer jQuery for å manipulere det samme DOM som Backbone manipulerer sømløst.

I denne artikkelen vil vi undersøke hvordan vi kan gjøre Backbone spille pent med d3.js. Konseptene i denne artikkelen bør gjelde for situasjoner der du har tenkt å bruke Backbone med de fleste andre biblioteker som også manipulerer DOM.

Backbone + d3.js Arbeider med samme DOM

d3.js, skrevet av Mike Bostock, er et annet mye brukt bibliotek som manipulerer Document Object Model, først og fremst for å visualisere data. Faktisk kan du bli veldig kreativ med måten dataene kan visualiseres på.

På det laveste nivået interagerer d3.js med HTML- og / eller SVG-elementer og manipulerer sine attributter ved å binde data til dokumentobjektmodellen.

Her er et raskt eksempel på hvordan d3 opererer:

var numericalData = [1,2,3,4,5,6]; d3.select ("body"). selectAll ("p") .data (numericalData) .enter () .append ("p") .text (funksjon (d) return "Jeg er nummer" + d + " ! ";); 

Ovennevnte kode gjør følgende:

  1. Velger og lager en referanse til kropp element
  2. Innenfor det aktuelle valget velges alle p elementer som for øyeblikket er i DOM
  3. Legger til hvert element i numericalData til en valgt p element
  4. For hver p element som har ennå ikke eksistert (dvs. noen elementer i numericalData som fortsatt må legges til), skaper en p element og legger til det DOM
  5. Setter inn tekstnoden i hver nyhet opprettet p element for å inneholde litt tekst (inkludert det aktuelle nummeret i numericalData)

En første forsøk på å lage ryggrad og d3.js Spill pent

Å utnytte det vi lærte i forrige artikkel, er her en implementering av en delt DOM-manipulasjon.

var CoolView = Backbone.View.extend (render: function () var html = "

Jeg er ikke et nummer!

"; dette. $ el.html (html); returner dette; renderVisualization: function (arrayOfData) d3.select (" body ") .selectAll (" p ") .data (arrayOfData) .enter () .append ("p") .text (funksjon (d) return "Jeg er nummer" + d + "!";;;); var coolView = ny CoolView (); coolView.render (); var myData = [10, 9, 4, 2, 1]; coolView.renderWithD3 (myData);

Houston, vi har et problem!

Forutsatt at vårt mål er å bevare det eksisterende p element og legg til den andre p elementer til DOM, når vi utfører ovennevnte kode, løper vi raskt inn i et stort problem.

De .render () innsatser en p element med teksten "Jeg er ikke et nummer" i DOM. Men .renderVisualization () velger alle eksisterende p elementer i DOM og legger inn innhold i disse elementene. Dette skriver teksten i originalen p element, til tross for vår føye til DOM bruker d3.append ().

Løsninger for å få d3.js og ryggraden til å leke pent sammen

I dette enkle eksempel eksisterer det minst to enkle løsninger.

  1. Bruk en mer spesifikk CSSvelger
  2. Bruk en annen kode helt

Cordoning av en del av DOM

For mer kompliserte eksempler kan vi trenge alternative strategier. En potensiell løsning er å koble av en del av DOM som skal betjenes av ett av bibliotekene. For eksempel:

var CoolView = Backbone.View.extend (... renderVisualization: function (arrayOfData) d3.select ("# visualisering") .selectAll ("p") .data (arrayOfData) .enter () .append ("p") .text (funksjon (d) return "Jeg er nummer" + d + "!";);); var coolView = ny CoolView (); var myData = [10, 9, 4, 2, 1]; coolView.renderVisualization (mydata); 

I det ovennevnte tilfellet fortsetter Backbone å administrere visningen som skal opprettes. Men la oss si at det er et element et sted i DOM (innsiden eller utenfor DOM som styres av ryggradssynet) hvis id er "visualisering". Vi kan kapitalisere på dette faktum ved å scoping alle våre d3-relaterte DOM manipulasjoner til dette elementet. Som et resultat, alle d3 kjedede metoder, inkludert .velger ( "p") og .føyer ( "p"), utføres i sammenheng med #visualization.

Encapsulate Differentiated DOM Manipulation With Sub-Views

Endelig er en annen tilnærming til å administrere tredjeparts visningsfunksjonalitet å bruke undervisninger. Her er hvordan det kan se ut.

var CoolView = Backbone.View.extend (render: function () var subViewA = ny SubViewA (); var subViewB = ny SubViewB (); // sett html innholdet for coolview dette. $ el.html (subViewA.render () .el); // legge til flere html-innhold for å se dette. $ el.append (subViewB.render (). el); returner dette;); // Andre steder, kanskje i ruteren din ... var coolView = ny CoolView (); $ ( 'App') html (coolView.render () el.).; 

I dette scenariet, subViewA kan inneholde ikke-visualiseringsinnhold, og subViewB kan inneholde visualiseringsinnhold.

En annen DOM-manipulasjonsmetode for Backbone + d3.js

Det er tider når du må sørge for at d3 DOM-manipulasjonen din oppstår i samme kontekst som selve ryggraden. For eksempel kan du bare koble av en del av DOM med #visualization gir ingen garanti for at elementet eksisterer innenfor eller utenfor delen av DOM som representeres av ryggraden.

Et alternativ er å sikre at ditt start-d3-utvalg refererer til det samme elementet som det som er pekt på dette. $ el. Men hvis du har en tendens til ikke å sette el eller noen av dens attributter direkte, ville det være vanskelig å målrette mot den nåværende visningen med CSS.

Heldigvis finnes det i d3.js-biblioteket en metode som gjør det mulig å velge direkte node. La meg introdusere deg til d3.select (node). Ifølge dokumentasjonen, denne metoden:

Velger den angitte noden. Dette er nyttig hvis du allerede har en referanse til en node, for eksempel d3.select (dette) innen en hendelselytter eller en global som document.body. Denne funksjonen går ikke gjennom DOM.

Denne metoden tillater oss å skrive følgende kode og sikre at d3-manipulasjoner forekommer i sammenheng med ryggradssyn.

var CoolView = Backbone.View.extend (// merk at "el" ikke er satt direkte gjengitt: funksjon () var html = "

Jeg er ikke et nummer!

"; dette. $ el.html (html); return dette;, renderVisualization: function (arrayOfData) d3.select (this); // vil ikke fungere," dette "refererer til en ryggradobjekt d3.select .el) // pass i en noden referanse .selectAll ("p") .data (arrayOfData) .enter () .append ("p") .text (funksjon (d) return "Jeg er nummer" + d + "!";););

Konklusjon

I sammendraget er det en rekke hensyn når Backbone spiller fint med andre DOM-manipulatorer.

  1. Pass på å velge riktig element for å manipulere. Å bruke bestemte CSS klasser og ids kan gjøre livet mye lettere.
  2. Enkel bruk av de ulike DOM-manipulasjonsmetodene i begge bibliotekene kan gå langt. Sørg for å avklare DOM-handlingen (legg til, prepend, sett inn, fjern) du virkelig trenger.
  3. Looping operasjoner i DOM kan være vanskelig. Sørg for at de riktige elementene er påvirket.

Det er også en rekke alternativer å vurdere, avhengig av utfallet du søker:

  1. Å skille ut en del av DOM
  2. Scoping det andre bibliotekets DOM-manipulasjon til ryggradssammenheng
  3. Bruke undervisninger for å inkapslere virkningen av andre DOM-manipulatorer