Encontrar un marco JS para la generación de UI


De alguna manera, quería intentar implementar una pequeña aplicación cliente-servidor. La implementación de la idea fue la siguiente: en el lado del cliente dibujamos ventanas usando algún tipo de marco JS, en el lado del servidor procesamos las llamadas del cliente usando una aplicación compilada escrita, por ejemplo, en Go.


Empecé a elegir un marco que proporciona una interfaz declarativa. En mi opinión, debería recibir la descripción del contenido del formulario en la forma más simplificada posible (por ejemplo, en el formato YAML, JSON, BEMJSON , XML o incluso INF), y en la salida, dibuje un formulario hermoso en el navegador con controles de trabajo.


Profesionalmente, no estoy involucrado en el desarrollo web y, por lo tanto, no esperaba estar atrapado durante mucho tiempo en esta etapa.


Y no iba a escribir un artículo, pero luego pensé que una nueva visión externa de las tecnologías web modernas, incluso un principiante, podría ser interesante para la comunidad. Una oportunidad para recibir comentarios nuevamente ...


Plantillas HTML y CSS


Todo lo que encontré no funcionó como quería. No quiero saber nada sobre diseño y estilos. Tampoco quiero completar el HTML, ya que se hace al aplicar marcos como Bootstrap , Skeleton , MDL , etc.


Código de muestra usando Bootstrap:


<div class="input-group mb-3"> <div class="input-group-prepend"> <div class="input-group-text"> <input type="checkbox" aria-label="Checkbox for following text input"> </div> </div> <input type="text" class="form-control" aria-label="Text input with checkbox"> </div> <button type="button" class="btn btn-primary btn-lg btn-block">Block level button</button> 

Todo lo que quiero aplicar a la entrada debería ser algo como esto:


 { "main": { "prop":{}, "elements": [ { "type":"checkbox", "name":" -", "style":"classic", "checked": true }, { "type":"button", "name":"", "style":"outline", "onclick":"btnsave_onclick" } } } 

Bueno, para que sea posible combinar elementos en grupos e indicar cómo deben ubicarse los elementos dentro del grupo: vertical u horizontalmente. Cuál será el diseño allí, no es especialmente importante para mí. Esperaba encontrar incluso algún tipo de editor de ventana visual, pero no.


Asamblea tecnológica


Luego traté de buscar algunos conjuntos de tecnología: alguien debe haber pavimentado un largo camino durante mucho tiempo y más de una vez.


Y encontré algo similar a lo que necesito: un sitio desde cero en una pila completa de tecnologías BEM .


Ejemplo de BEMJSON:


 ({ block: 'page', title: 'Hello, World!', styles: [ { elem: 'css', url: 'index.min.css' } ], scripts: [ { elem: 'js', url: 'index.min.js' } ], content: [ 'Hello, World!' ] }) 

Cuando me desplacé por la vigésima pantalla del texto, y el control deslizante todavía estaba en la parte superior, pensé que este camino corto era de alguna manera largo. No funcionará


Por cierto, leí sobre este BEM : me gustó la esencia y se describe muy bien. Hay varias hojas de trucos, por ejemplo, me gustó esta . También busqué información y descubrí que no a todos les gusta la tecnología (por ejemplo, aquí y aquí ). Y aquí, en mi opinión, se expone la esencia de los puntos controvertidos.


Lo interesante es que usando la búsqueda, aparte de BEM, durante mucho tiempo no pude encontrar más tecnologías alternativas. Sin embargo, son: OOCS (algo así como el mismo BEM, simplemente más simple), SMACSS , AtomicCSS , CSSinJS (que se encuentra aquí ).


Node.js


Entonces pensé, ok, puedes abandonar la idea original e implementar la parte del servidor en un lenguaje de script, es decir, simplemente usar nodejs. No solo está de moda, es elegante, juvenil, también es una oportunidad para escribir en todas las capas en un idioma. Muchos artículos nuevamente (me gustó este sobre el inicio rápido). Si entiendo correctamente, se escriben innumerables paquetes de NPM para casi cualquier tarea. Todavía hay algo tan serio como Electron en este negocio.


Código de página de muestra usando Electron:


 <head> <meta charset="utf-8"> <link rel="stylesheet" href="assets/css/variables.css"> <link rel="import" href="sections/about.html"> </head> <body> <nav class="nav js-nav"> <header class="nav-header"> <h1 class="nav-title">Electron <strong>API Demos</strong></h1> </header> <div class="nav-item u-category-windows"> </div> <footer class="nav-footer"> <button type="button" id="button-about" data-modal="about" class="nav-footer-button">About</button> </footer> </nav> <main class="content js-content"></main> <script> require('./assets/normalize-shortcuts') </script> </body> </html> 

El único signo negativo es que es posible escribir cosas más productivas, usando Go.
Supongamos que quiero usar nodejs. Hay un catálogo de paquetes NPM para que pueda elegir algo adecuado.


Hay un paquete llamado formularios . Aquí hay un código de muestra:


 var forms = require('forms'); var fields = forms.fields; var validators = forms.validators; var reg_form = forms.create({ username: fields.string({ required: true }), password: fields.password({ required: validators.required('You definitely want a password') }), confirm: fields.password({ required: validators.required('don\'t you know your own password?'), validators: [validators.matchField('password')] }), email: fields.email() }); 

Esto se ensambla en el formulario mediante el comando reg_form.toHTML(); . Una opción interesante, pero no eso.


También hay Element , Riot , TotalJS e iView . Esto se puede agregar a la lista desde Bootstrap, MDL, etc.


Ejemplo de código de página usando Element:


 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <!-- import CSS --> <link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css"> </head> <body> <div id="app"> <el-button @click="visible = true">Button</el-button> <el-dialog :visible.sync="visible" title="Hello world"> <p>Try Element</p> </el-dialog> </div> </body> <!-- import Vue before Element --> <script src="https://unpkg.com/vue/dist/vue.js"></script> <!-- import JavaScript --> <script src="https://unpkg.com/element-ui/lib/index.js"></script> <script> new Vue({ el: '#app', data: function() { return { visible: false } } }) </script> </html> 

También hay Blueprintsjs . Este es quizás el más similar a lo que estaba buscando. Es posible configurar los controles por separado uno del otro.


El código se parece a esto:


Mucho código usando planos
 /* * Copyright 2018 Palantir Technologies, Inc. All rights reserved. * * Licensed under the terms of the LICENSE file distributed with this project. */ import * as React from "react"; import { FormGroup, H5, InputGroup, Intent, Switch } from "@blueprintjs/core"; import { Example, handleBooleanChange, handleStringChange, IExampleProps } from "@blueprintjs/docs-theme"; import { IntentSelect } from "./common/intentSelect"; export interface IFormGroupExampleState { disabled: boolean; helperText: boolean; inline: boolean; intent: Intent; label: boolean; requiredLabel: boolean; } export class FormGroupExample extends React.PureComponent<IExampleProps, IFormGroupExampleState> { public state: IFormGroupExampleState = { disabled: false, helperText: false, inline: false, intent: Intent.NONE, label: true, requiredLabel: true, }; private handleDisabledChange = handleBooleanChange(disabled => this.setState({ disabled })); private handleHelperTextChange = handleBooleanChange(helperText => this.setState({ helperText })); private handleInlineChange = handleBooleanChange(inline => this.setState({ inline })); private handleLabelChange = handleBooleanChange(label => this.setState({ label })); private handleRequiredLabelChange = handleBooleanChange(requiredLabel => this.setState({ requiredLabel })); private handleIntentChange = handleStringChange((intent: Intent) => this.setState({ intent })); public render() { const { disabled, helperText, inline, intent, label, requiredLabel } = this.state; const options = ( <> <H5>Props</H5> <Switch label="Disabled" checked={disabled} onChange={this.handleDisabledChange} /> <Switch label="Inline" checked={inline} onChange={this.handleInlineChange} /> <Switch label="Show helper text" checked={helperText} onChange= {this.handleHelperTextChange} /> <Switch label="Show label" checked={label} onChange={this.handleLabelChange} /> <Switch label="Show label info" checked={requiredLabel} onChange= {this.handleRequiredLabelChange} /> <IntentSelect intent={intent} onChange={this.handleIntentChange} /> </> ); return ( <Example options={options} {...this.props}> <FormGroup disabled={disabled} helperText={helperText && "Helper text with details..."} inline={inline} intent={intent} label={label && "Label"} labelFor="text-input" labelInfo={requiredLabel && "(required)"} > <InputGroup id="text-input" placeholder="Placeholder text" disabled={disabled} intent={intent} /> </FormGroup> <FormGroup disabled={disabled} helperText={helperText && "Helper text with details..."} inline={inline} intent={intent} label={label && "Label"} labelFor="text-input" labelInfo={requiredLabel && "(required)"} > <Switch id="text-input" label="Engage the hyperdrive" disabled={disabled} /> <Switch id="text-input" label="Initiate thrusters" disabled={disabled} /> </FormGroup> </Example> ); } } 

El resultado se ve así:


Incluso si tenemos en cuenta solo la última parte: de todos modos, de alguna manera no es muy conciso.


metadata.js


También encontré algo interesante en la Web: metadatajs . Un comienzo rápido está aquí . Esta biblioteca tiene una funcionalidad redundante, y en el artículo, en mi opinión, lo más importante no es: la descripción de la biblioteca en sí. Esta aqui


Se nos ofrece describir el formulario de la siguiente manera:


Descripción del formulario usando metadata.js
 { "enm": {}, "cat": { "": { "form": { "selection": { "fields": [ "is_folder", "id", "", "_t_.name as presentation", "`cat_`.name as ``", "`cat_`.name as ``" ], "cols": [ {"id": "id", "width": "120", "type": "ro", "align": "left", "sort": "server", "caption": ""}, {"id": "", "width": "150", "type": "ro", "align": "left", "sort": "server", "caption": ""}, {"id": "presentation", "width": "*", "type": "ro", "align": "left", "sort": "server", "caption": ""}, {"id": "", "width": "70", "type": "ro", "align": "left", "sort": "server", "caption": ""}, {"id": "", "width": "170", "type": "ro", "align": "left", "sort": "server", "caption": " "} ] } } }, "": { "form": { "selection": { "fields": [ "is_folder", "id", "_t_.name as presentation", "`enm_`.synonym as ``", "`cat_`.name as ``" ], "cols": [ {"id": "presentation", "width": "*", "type": "ro", "align": "left", "sort": "server", "caption": ""}, {"id": "", "width": "150", "type": "ro", "align": "left", "sort": "server", "caption": " "}, {"id": "", "width": "150", "type": "ro", "align": "left", "sort": "server", "caption": ""} ] } } } }, "doc": { "": { "form": { "selection": { "fields": [ "date", "number_doc", "", "", "posted", "", "" ], "cols": [ {"id": "date", "width": "120", "type": "ro", "align": "left", "sort": "server", "caption": ""}, {"id": "number_doc", "width": "120", "type": "ro", "align": "left", "sort": "server", "caption": ""}, {"id": "", "width": "170", "type": "ro", "align": "left", "sort": "server", "caption": ""}, {"id": "", "width": "120", "type": "ron", "align": "right", "sort": "server", "caption": ""}, {"id": "", "width": "100", "type": "ro", "align": "left", "sort": "server", "caption": ""}, {"id": "", "width": "*", "type": "ro", "align": "left", "sort": "server", "caption": ""} ] }, "obj": { "head": { " ": ["number_doc", "date", "", "", "", ""], "": ["", "", ""], "": ["", "", "", "", "", "", "", {"id": "", "path": "o.", "synonym": " ", "type": "ro"} ] }, "tabular_sections": { "": { "fields": ["row","","","","","","","","","","","","",""], "headers": "№,,,.,,,% ,,% ,,,.,,", "widths": "40,*,*,70,50,70,70,70,70,70,70,70,70,80", "min_widths": "40,200,140,70,50,70,70,70,70,70,70,70,70,80", "aligns": "", "sortings": "na,na,na,na,na,na,na,na,na,na,na,na,na,na", "types": "cntr,ref,ref,calck,refc,calck,calck,ron,refc,ron,ron,dhxCalendar,ref,txt" } } } } } }, "ireg": {}, "areg": {}, "dp": {}, "rep": {}, "cch": {}, "cacc": {} } 

Esto es muy similar a lo que necesitas. Sin embargo, surgen preguntas: ¿el conjunto de botones parece ser el predeterminado? ¿Puedo cambiarlo? ¿Dónde está la descripción de la sintaxis (qué es "enm", "cat", etc.)?
Se puede ver que se ha puesto mucho esfuerzo en el proyecto, pero la biblioteca todavía está húmeda.


Conclusión


Vamos a especular Los formularios pueden dibujarse previamente en el servidor, compilarse y enviarse al código html / css / js del lado del cliente. En este caso, debe buscar algo completamente diferente. Pero si queremos que el usuario trabaje con nosotros en una ventana del navegador, y en esta ventana vea las ventanas secundarias de la aplicación web, no sería lógico almacenar en caché el código css / js en el cliente, que recibirá comandos breves del servidor con una descripción del siguiente formulario y los dibujará a expensas de los recursos del cliente?


Colegas, ¿dónde esconden el marco de interfaz declarativo? )


Él debe ser! ¿Por qué no puedo encontrarlo?

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


All Articles