查找用于UI生成的JS框架


我想以某种方式尝试实现一个小型客户端服务器应用程序。 这个想法的实现是这样的:在客户端,我们使用某种JS框架绘制窗口,在服务器端,我们使用例如用Go编写的已编译应用程序处理来自客户端的调用。


我开始选择一个提供声明性接口的框架。 在我看来,它应该尽可能简单地接收对表单内容的描述(例如,以YAML,JSON, BEMJSON ,XML甚至是INF格式),并在输出端使用有效的控件在浏览器中绘制漂亮的表单。


专业上,我没有参与Web开发,因此在此阶段没想到会长时间停留。


我不打算写文章,但后来我认为,即使对于初学者来说,现代Web技术的崭新面貌也可能使社区感兴趣。 有机会再次获得反馈...


HTML和CSS模板


我发现的所有内容都无法正常运行。 我不想对布局和样式一无所知。 我也不想填写HTML,因为在应用诸如BootstrapSkeletonMDL等框架时就完成了。


使用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> 

我要应用于输入的所有内容都应该像这样:


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

好吧,这样就可以将元素组合成组并指出元素应如何在组内定位:垂直还是水平。 那里的设计是什么,对我来说不是特别重要。 我期望找到某种可视窗口编辑器,但没有找到。


技术组装


然后,我尝试寻找一些技术组件-某人必须已经为很长一段时间铺了很长一段路,而且不止一次。


而且我发现了与我需要的东西类似的东西:一个从头开始使用全套BEM技术的站点


BEMJSON示例:


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

当我滚动文本的第20个屏幕时,并且滑块仍在顶部时,我认为这条短路径有些长。 它不起作用。


顺便说一句,我读到了有关BEM的信息 -我喜欢其中的本质,并且描述得很好。 有各种各样的备忘单,例如,我喜欢这个备忘单。 我还查找了信息,发现并不是每个人都喜欢这项技术(例如, 在这里这里 )。 我认为在这里,提出了有争议的观点的实质。


有趣的是,很长时间以来,除了BEM之外,使用搜索都找不到更多替代技术。 但是,它们是: OOCS (有点像相同的BEM,更简单), SMACSSAtomicCSSCSSinJS (在此处找到)。


Node.js


然后,我想,好的,您可以放弃最初的想法,并以脚本语言实现服务器部分,即仅使用nodejs。 它不仅时尚,时尚,年轻,而且是用一种语言在所有层次上书写的机会。 再次有很多文章(我喜欢这篇关于快速入门的文章)。 如果我理解正确,几乎可以完成所有任务的NPM软件包。 在这项业务下,还有像电子公司这样的严肃事情。


使用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> 

使用Go可以编写出更有生产力的东西的唯一的减法nodejs。
假设我要使用nodejs。 有NPM软件包的目录,以便您可以自己选择合适的东西。


有一个叫做表格的包。 这是一个示例代码:


 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() }); 

通过reg_form.toHTML();命令将其组装为表单reg_form.toHTML(); 。 一个有趣的选择,但不是那样。


还有ElementRiotTotalJSiView 。 可以从Bootstrap,MDL等将其添加到列表中。


使用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> 

也有Blueprintsjs 。 这也许与我所寻找的最相似。 可以将控件彼此分开配置。


代码看起来像这样:


使用蓝图的大量代码
 /* * 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> ); } } 

结果看起来像这样:


即使我们仅考虑最后一部分:都是一样的,但还是不太简洁。


metadata.js


我还在Web上发现了一件有趣的事情: metadatajs 。 快速入门在这里 。 该库具有冗余功能,在我看来,本文中最重要的不是-库本身的描述。 在这里


我们提供如下形式来描述:


使用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": {} } 

这与您所需要的非常相似。 但是,出现了一些问题:按钮设置似乎是默认设置的吗? 我可以改变吗? 语法描述在哪里(“ enm”,“ cat”等是什么)?
可以看出,该项目已经付出了很多努力,但是库仍然很潮湿。


结论


让我们推测一下。 表单可以在服务器上预先绘制,编译并提交给客户端,准备好html / css / js-code。 在这种情况下,您需要寻找完全不同的东西。 但是,如果我们希望用户在一个浏览器窗口中与我们一起工作,并且在此窗口中看到Web应用程序的子窗口,则在客户端上缓存css / js代码是不合逻辑的,该代码将从服务器接收简短的命令并提供下一种形式的说明。并会以牺牲客户资源为代价来吸引他们吗?


同事,您在哪里隐藏了声明性接口框架? )


他一定是! 我为什么找不到他?

Source: https://habr.com/ru/post/zh-CN445854/


All Articles