Crear componentes personalizados para Bootstrap 4


La opinión pública ha traducido Bootstrap a la categoría de marcos legendarios del pasado, pero aún vale la pena verlo. Bootstrap 4 es un excelente navegador para un diseño seguro, y lo más importante, una muestra de HTML sobre el enfoque JS para crear aplicaciones web, revela completamente las capacidades existentes de HTML para la descripción declarativa de la interfaz de usuario.


Y cómo se está desarrollando el código marco JavaScript también es útil para tener una idea. La arquitectura de los complementos de jQuery todavía está en uso, pero a partir de la versión 4 está incluida por Rollup en el paquete de clases ES6 transformadas con Babel6 . jQuery probablemente no llegará pronto, más sobre eso más adelante, pero por ahora, usando el ejemplo de crear su propio complemento BsMultiSelect , en la misma pila que Boostrap 4 , se revelarán las características de desarrollo del marco.


Por qué " cada programador debería escribir su propio ... "


" Mejorar lo bueno solo se echa a perder ". La necesidad de comprender qué obtuvo el nuevo Bootstrap fue la transferencia de sus componentes a la nueva pila, y cuánto más fácil ahora es crear componentes de alto orden. Todo parecía ser simple: combine .form-control , .badge y .dropdown-menu y puede obtener fácilmente una selección múltiple ...



Conflicto de arquitectura desde la puerta


El complemento resultante BsMultiSelect no usa directamente el código JS bootstrap.js , pero usa su dependencia, popper.js (marco emergente de vainilla). Esto se debe a que el componente desplegable de bootstrap.js necesita encontrar el llamado elemento de alternancia durante la inicialización en el DOM (en el caso particular es un botón que abre el menú), si no lo encuentra, se bloquea con un error (ya que creo directamente desde js, entonces tengo "botones" por supuesto que no). Conclusión: los componentes mejorados bajo "HTML sobre JS" no pueden (o desventajosamente) crearse directamente desde JS. Conclusión número dos: necesita programar componentes personalizados para que bajo el componente "HTML sobre JS", siempre haya un componente más ligero de "JS puro". Tengo este MulitSelect.js completamente borrado no solo del código sino también de los estilos Bootstrap. MulitSelect.js juega el mismo papel para BsMulitSelect.js, al igual que popper.js para dropdown.js.


Dos palabras sobre popper.js


Gran biblioteca: una función. DropDown.js se repite pero proporciona una interfaz completamente limitada (de nuevo, porque en "HTML sobre JS" no se necesita toda la API). Popper tiene un problema más abierto de lo que nos gustaría. Me decepcionó que bajo IE11 publique eventos que no son como Chrome .


Sobre la transición de IIFE a clases


El estándar estándar del plugin jQuery es definir la función del constructor dentro de IIFE . Ahora esta es una clase dentro de IIFE. Apertura: las viejas formas funcionales de hacer métodos privados entran en conflicto con el ES6 lambda, por lo que fueron "abandonadas" en Bootstrap. Todos los métodos son públicos, mientras que los métodos pseudo-privados tienen como prefijo _ i.e. undercrore. Entiendo que estoy equivocado, pero sigo mis convenciones: "métodos públicos con mayúscula". En todo lo demás, BsMultiSelect creó la adopción del acuerdo del DropDown.js "estándar", es decir. Me gustaría representarlo como una especie de repetitivo con carne.


Sin embargo, otra diferencia, ya que hay un paquete acumulativo, presioné los archivos ...
 import $ from 'jquery' import AddToJQueryPrototype from './AddToJQueryPrototype' import MultiSelect from './MultiSelect' // ... ( (window, $) => { AddToJQueryPrototype('BsMultiSelect', (element, optionsObject, onDispose) => { // ... return new MultiSelect(element, optionsObject, onDispose, facade, window, $); }, $); } )(window, $) 

Nuevo acuerdo: el complemento debe publicar el Constructor , para no perder el constructor dentro de IIFE. Sí, debe quedar un IIFE: nadie eliminó la tarea de definir las dependencias de ventana, $ y Popper (para aquellos que "no pueden acceder a los módulos") de manera estándar.


Configuraciones de Eslint y Stylelint Linter


No me sentí obligado a seguir las reglas draconianas para diseñar el código Bootstrap. Seguramente escriben en un entorno que los ayude a establecer espacios y, para controlar la fuente, la rigidez es muy buena, pero me resulta difícil escuchar cada segundo la tristeza de la trama en VS Code. Al escribir su propio complemento, las reglas pueden y deben ser muy relajadas.


Eslint, puede que la stylelint no salga con demasiada frecuencia, pero no hay deseo de mirar las nuevas reglas. En todos los aspectos, este logro me molesta más.


Código de organización y resumen


El código redistribuible ES6 de Bootstrap se empaqueta en dos versiones: bootstrap.js independiente y paquete bootstrap.bundle.js , este último incluye popper.js.


El autor de rollup.config.js tiene instintos ajenos a mí. Toda esta transformación de configuración a través de push y pop, dependiendo de la versión requerida de independiente o paquete, parece elaborada e intimidante, afortunadamente, para escribir un complemento solo necesita un tipo de paquete "independiente" y no tengo que demostrar que puedo hacerlo mejor.


La versión independiente de Bootstrap también se indica en el campo principal del paquete, es decir Las dependencias npm se resuelven en el mismo archivo que los usuarios cargan a través de <script> . Esta no es una solución inequívoca, pero mi complemento BsMultiSelect ha seguido el mismo camino. En este caso, los ayudantes de babel se pueden incluir en el complemento , a pesar de que también se incluyen en bootsrap.js. La duplicación de alguna manera no está bien ...


Lo interesante es que Bootstrap tiene una configuración paralela bajo jspm: el cargador del módulo ES del navegador nativo y su campo principal ya es un código remoto limpio, 12 componentes que no están agrupados, pero se almacenan por separado en el directorio js / dist. Aquí, cada archivo incluye ayuda de babel. Jspm ahora está en una encrucijada, por lo que al crear BsMultiselect, ignórelo.


Y sin embargo, es interesante preguntar a los entendidos, ¿jspm va a levantar los 12 ayudantes de ayuda duplicados al navegador?

Se ha descubierto una gran ventaja del paquete acumulativo: sus paquetes son legibles, a diferencia de los paquetes web.


Bootsrap 4 usa Babel 6 y el complemento BsMultiSelect Babel 7


BsMultiSelect migró fácilmente a la versión beta de Babel 7 utilizando el rollup-babel-plugin actualizado (también en versión beta). Vale la pena mudarse a Babel 7 ahora debido al nuevo @babel/preset-env (la configuración del transpilador "en qué navegadores se ejecutará el código"). Usando solo Internet, se hizo bastante difícil entender cómo funcionan los presets de ES6, pasaron por una larga evolución y se han acumulado muchas configuraciones obsoletas. Es mejor apostar Babel 7 + @babel/preset-env inmediato


Sin embargo, los errores beta de babel no tuvieron que esperar mucho: [... nodeList] se compiló en nodeList.concat (). No lo entendí durante mucho tiempo, traducir el código en llamadas jquery (esto todavía es necesario, pero más sobre eso más adelante) resolvió el problema. Pregunte: "¿Por qué entonces, en absoluto, Babel si no tratas con él?", La respuesta: "importaciones y lambda".


Aspectos prácticos


Bootstrap 4 y su complemento (como cualquier código js) tienen dos opciones para cargar en el navegador: a través de script / style (crear una "página"), y a través del nodo de ensamblaje / webpack (crear una "aplicación", así que continuaré estos dos en principio, situaciones muy diferentes y denotan: "página" y "aplicación").
Para la página y para la aplicación, se utilizará el mismo "archivo de distribución" de Bootstrap. Esta no es una solución obvia y no la única (como ejemplo, se usa un código diferente para jspm y para las pruebas de mocha ), pero al crear su propio plugin, no queda nada más que hacer que seguir esta convención, esperando su optimización.


Encontrar un equilibrio entre satisfacer dos necesidades utilizando el mismo código para dos opciones de descarga diferentes: "páginas" y "aplicaciones" es la principal tarea arquitectónica que enfrenta el desarrollador del complemento.


Después de todo, el complemento Bootstrap también se puede crear ad hoc , directamente en su aplicación. En este caso, puede escribir el código del complemento con todos los placeres: polífilos y acceso a las variables SASS del esquema. Sin embargo, cuando dependa de la reutilización, será necesario transferir el complemento a su propio paquete npm, los placeres anteriores entran en la categoría de problemas: pierde el acceso a las variables SASS y debe tener en cuenta a los creadores de las "páginas" que conectan el complemento a través de un script (¿dónde están mis polyfiles?).


Acceso a las variables de estilo de Bootstrap 4 de SASS


Me gustaría escribir Bootstrap css clases / selectores para escribir el complemento. En este caso, al personalizar el tema Bootstrap, puede esperar que el complemento se adapte sin esfuerzo adicional.


Para un complemento autopublicado, no hay acceso a las variables SASS.


Clases / selectores css existentes: no cubra todos los estilos necesarios para BsMutliSelect, por ejemplo, necesita min-height para ul.form-control , cuando en bootstrap.css solo hay un selector css con altura para input.form-control : no puede aplicarlo para ul . Otras clases / selectores existentes traen muchos estilos superfluos: ¿qué sucede si desea asignar, por ejemplo, el color de .form-control a un elemento sin asignar una clase .form-control ? Esto no funcionará porque no existe una clase como .input-color en la que la variable $ input-color se publicaría "por separado" de todo.


Además, no es posible seguir las decisiones del equipo de Bootstrap: si es necesario, no tienen ese problema: crean una clase / selector CSS con la variable deseada y lo operan. Si desea debatir, deberá explicar con Mark Otto , en el equipo de BS hay un nivel anormalmente alto de toma de decisiones, incluso para cambios cosméticos en los selectores CSS, si las solicitudes entran en la categoría de "oferta".


Propongo la siguiente solución.


Para una página (generar un complemento a través de un script ), debe soportar la inaccesibilidad de las variables. Pero no es necesario ofrecer tratar con CSS: se pueden ofrecer variables inaccesibles para personalizarlas a través de parámetros js, ya que no hay muchas (y ningún esquema cambia todas). Para BsMultiSelect, los problemáticos fueron: color deshabilitado, color de entrada, sombra de control enfocada (etc. solo 10 estilos, la mayoría de ellos rara vez cambian los esquemas) ...


Por un lado, esta es una declaración de todos los estilos de los que depende el complemento ...
 $("select[multiple='multiple']").bsMultiSelect({ selectedPanelDefMinHeight: 'calc(2.25rem + 2px)', // default size selectedPanelLgMinHeight: 'calc(2.875rem + 2px)', // LG size selectedPanelSmMinHeight: 'calc(1.8125rem + 2px)', // SM size selectedPanelDisabledBackgroundColor: '#e9ecef', // disabled background selectedPanelFocusBorderColor: '#80bdff', // focus border selectedPanelFocusBoxShadow: '0 0 0 0.2rem rgba(0, 123, 255, 0.25)', // foxus shadow selectedPanelFocusValidBoxShadow: '0 0 0 0.2rem rgba(40, 167, 69, 0.25)', // valid foxus shadow selectedPanelFocusInvalidBoxShadow: '0 0 0 0.2rem rgba(220, 53, 69, 0.25)', // invalid foxus shadow inputColor: '#495057', // color of keyboard entered text selectedItemContentDisabledOpacity: '.65' // btn disabled opacity used }); 

Pero para una aplicación que usa SASS y el recopilador, puede ofrecer copiar BsMultiSelect.scss y corregir la ruta a su _variables.scss en él. Por lo tanto, el complemento "recibirá" las variables variables.


Todo a través de CSS ...
  $("select[multiple='multiple']").bsMultiSelect({ useCss: true }); 

Estos dos métodos están escritos explícitamente en mi código JS, a través de dos "adaptadores". BsMultiSelect es en realidad dos complementos en uno. Uno que trabaja con estilos a través de variables js, el otro delega este trabajo css.


Al mismo tiempo, debo decir directamente que trabajar con CSS puede ser necesario incluso si se usó la transferencia de estilos personalizados a través de parámetros JS, simplemente porque los autores de los esquemas generalmente hacen su trabajo de manera aproximada. O extraño Por ejemplo, el esquema de Skethy por alguna razón decidió que el menú no necesita un efecto de desplazamiento. Las características tienen que ser archivadas.


Pero con el ejemplo incompleto, espero que pueda ver cómo el complemento se adaptó al circuito pesado con relativa facilidad (era necesario sobrecargar los valores de solo tres estilos a través de parámetros js).


adaptación al esquema a través de js
 $("select[multiple='multiple']").bsMultiSelect({ selectedPanelFocusBoxShadow:"0px 0px 0px 0.2rem rgba(51,51,51,0.25)", selectedPanelFocusBorderColor:"#333", selectedPanelDisabledBackgroundColor: "#f7f7f9" }); 


Este es el máximo que se puede lograr usando las clases CSS "estándar" .bage , .form-control , .close , etc. Casi todo se adaptó al esquema, pero no todo.


Es una pena, por supuesto, que no pueda alejarse de estos tres parámetros, no todas las variables de estilo de esquema son accesibles a través de selectores / clases css (estoy mintiendo, puede irse si puede copiar BsMultiSelect.scss a usted mismo y traerle las variables del circuito, pero esto no satisface completamente , como todas las decisiones que comienzan con las palabras "copia a ti mismo").


Haga clic aquí: https://dashboardcode.imtqy.com/BsMultiSelect/indexsketchy.html


Polyfill's


En el escenario "Estoy escribiendo un complemento ad hoc dentro de la aplicación", usará @babel/polyfill sin ningún problema y parcheará el polyfill.io DOM porque dentro de su aplicación ya está allí.


Cuando un complemento se mueve a un módulo npm externo, toda la alegría desaparece porque los usuarios de Bootstrap no han decidido complacer las largas listas de polyfills requeridos en la documentación.


Solución: todo ese babel no se transpondrá, sino que se irá a los polífilos, evitará que haga esto, rechinando los dientes, para convertirlo en llamadas jQuery (por ejemplo, Node.closest en $ .closest). Este enfoque se adopta en Bootstrap 4 y obviamente es una lucha contra la hinchazón. Sorpresa jQuery es un polyfill.


Estoy de acuerdo en que programar con Babel con la vista puesta en CanIUse.com y MDN.com no es divertido. Y el código es incómodo (para mí).


Aquí es necesario resaltar la situación desde arriba nuevamente. Bootstrap usa dos bibliotecas jQuery y popper.js. Popper.js es un marco doble vainilla, no tiene babel, jQuery o polyfills externos, todo por sí mismo. JQuery está empaquetado por gruñidos que ya usan babel, pero de alguna manera mágica sin sus polyfills y helper's. Un complemento de Bootstrap de terceros (como BsMultiSelct) usa Babel 7. Su producto aún puede usar otra cosa. No hay una única plataforma polifílica, se espera duplicación de código múltiple, hay cuatro implementaciones de la misma carga más cercana en el navegador. Pero no se puede hacer nada al respecto.


Sin embargo, si usó polyfiles al crear su propio complemento, debe recordar que si la aplicación tiene scripts en línea (es decir, <script>$( function() {/*..*/}) </script> ) entonces solo tendrá que descargar polyfiles sincrónicamente (de lo contrario, el código en línea puede comenzar a ejecutarse antes del momento en que se carga el complemento). Es decir por ejemplo, webpack-polyfill-injector (el inyector de polifilos más rico que conozco) necesito controlarlo para que no decida cargar polifilos de forma asincrónica (comportamiento predeterminado).


No jQuery


jQuery se siente algo tóxico, compitiendo y oscureciendo Babel / ES6, pero no es para siempre. Hay una rama v4-whithout-jquery , ya está en la solicitud del grupo, planea lanzar bootstrap-nojquery c versión 4.3 . Anteriormente, el espacio de nombres de los eventos se denominaba el mayor problema para rechazar jquery, aunque es obvio que puede escribir sin ellos (BsMultiSelect no lo hizo). Aparentemente decidido.


También se anunció que a partir de la versión 4.3 será posible cargar los componentes originales en el navegador por separado (solo para el escenario de "aplicación"). ¿Los componentes originales se convertirán en "como BsMultiSelect "? No Si el equipo de BS necesita algunas variables SASS, crearán clases / selectores CSS por sí mismos y operarán desde JS ("CSS funcional"). Los creadores de funciones personalizadas no están disponibles.


La posible transición de sass a post-css https://github.com/twbs/bootstrap/projects/11 en la quinta versión fundamentalmente no cambia nada. O cambia todo: "JS sobre HTML".


Bootstrap 5 tendrá que establecer recomendaciones sobre cómo integrarse en los polyfiles de Babel y cómo parchar el DOM. Aquí el pronóstico es más o menos claro: se ofrecerán ensamblajes completamente diferentes a los creadores de páginas y creadores de aplicaciones.


Resumen


Mientras escribes los componentes de Bootstrap 4 en Babel usando el método ad hoc sin pensar en la reutilización, lo que significa polífilos, y dónde obtener las variables de estilo, no sabes sobre el dolor.


Pero si convierte el complemento en un paquete npm separado, y con el deseo de tomar una decisión en el espíritu de Bootstrap 4, el placer se vuelve menos, piensa más a menudo y por más tiempo. Probablemente tenga que decidir de inmediato quiénes son sus usuarios y ofrecer diferentes compilaciones, una para aquellos que construirán la aplicación en paquetes, la otra para escribir páginas, es decir. cargando el script del complemento.

Source: https://habr.com/ru/post/es416235/


All Articles