javascript - que - ¿Es posible acceder a los elementos de Shadow DOM a través del documento principal?
shadow dom v1 (3)
Esta pregunta está más dirigida a los elementos DOM sombreados creados por el usuario, pero para la accesibilidad usaré el tipo de entrada de date
para esta pregunta:
Digamos, por ejemplo, que tengo una entrada de date
en mi página. Con un par de bits editados, el marcado DOM sombreado para esto (usando Chrome) se ve algo así como:
<input type="date">
#document-fragment
<div pseudo="-webkit-datetime-edit">
<div pseudo="-webkit-datetime-edit-fields-wrapper">
<span role="spinbutton">dd</span>
<div pseudo="-webkit-datetime-edit-text">/</div>
<span role="spinbutton">mm</span>
<div pseudo="-webkit-datetime-edit-text">/</div>
<span role="spinbutton">yyyy</span>
</div>
</div>
<div></div>
<div pseudo="-webkit-calendar-picker-indicator"></div>
Los métodos y propiedades asociados con la entrada de date
no parecen hacer referencia alguna al DOM sombreado ( JSFiddle ), así que me preguntaba cómo (si es que se puede) acceder a estos elementos de DOM sombreados.
No puede acceder al contenido de Shadow DOM desde secuencias de comandos fuera del DOM de Shadow. La encapsulación es el propósito de Shadow DOM.
int32_t
tiene razón en que Shadow DOM, por definición, es una forma de llenar un nodo con DOM que desea ocultar de fuentes externas ( Encapsulación ). El punto es que usted, como autor del componente, puede elegir exactamente qué partes estarán expuestas a CSS o JavaScript externos y cuáles no.
Desafortunadamente, no puede crear una interfaz pública de JavaScript para su DOM Shadow sin utilizar otra especificación de última generación llamada Elementos personalizados . Si elige hacer eso, es tan simple como agregar métodos públicos personalizados al prototipo de su elemento. A partir de estos, puede acceder a las partes internas de su DOM sombreado (vea el tercer ejemplo aquí ).
Sin embargo, puede exponer ganchos para que CSS acceda a las partes internas de su Shadow DOM sin utilizar elementos personalizados. Hay dos maneras de hacerlo:
- Pseudo-elementos
- Variables CSS
Pseudo-elementos
Chrome y Firefox exponen ciertas partes de su Shadow DOM a CSS a través de pseudo-elementos especiales. Aquí está el ejemplo de la entrada de date
con la adición de una regla de CSS que solo se aplica a la parte numérica del campo de fecha mediante el uso del pseudo-elemento proporcionado por Chrome -webkit-datetime-edit
.
Aquí hay una lista parcial de los pseudo-elementos WebKit disponibles. También puede habilitar la opción Show Shadow DOM
en DevTools y buscar atributos llamados pseudo
.
Los autores de los componentes también pueden crear sus propios pseudoelementos para exponer partes de su DOM sombreado (vea el segundo ejemplo aquí ).
Variables CSS
Una forma aún mejor es usar las Variables CSS, que puede habilitar con Enable experimental WebKit features
en about:flags
en Chrome. Luego mira este violín que usa Variables CSS para comunicar al DOM de Sombra qué color debe usar para su "tema".
Ahora (2016) puede acceder a los elementos DOM sombra abiertos creados por el usuario (¡pero no a un DOM sombreado creado por un agente de usuario!) Utilizando el método querySelector
en la raíz DOM de Shadow:
<body>
<div id="container"></div>
<script>
//Shadow Root
var root = container.createShadowRoot()
//new syntax:
var root = container.attachShadow( { mode: "open" } )
//Inside element
var span = document.createElement( "span" )
span.textContent = "i''m inside the Shadow DOM"
span.id = "inside"
root.appendChild( span )
//Access inside element
console.log( container.shadowRoot.querySelector( "#inside" ) )
</script>
</body>
//Shadow Root
var root = container.createShadowRoot()
//Inside element
var span = document.createElement( "span" )
span.textContent = "i''m inside the Shadow DOM"
span.id = "inside"
root.appendChild( span )
//Access inside element
function get()
{
alert( container.shadowRoot.querySelector( "#inside" ).id )
}
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
</head>
<body>
<div id="container"></div>
<button onclick="get()">Get</button>
<script>
</script>
</body>
</html>