العثور على JS Framework لتكوين واجهة المستخدم


بطريقة ما أردت أن أحاول تنفيذ تطبيق خادم عميل صغير. كان التنفيذ في الفكرة هو: من جانب العميل ، نقوم برسم النوافذ باستخدام نوع من JS framework ، من جانب الخادم نقوم بمعالجة المكالمات من العميل باستخدام تطبيق مترجم مكتوب على سبيل المثال في Go.


بدأت في التقاط إطار يوفر واجهة تعريفية. في رأيي ، يجب أن تتلقى وصفًا لمحتويات النموذج بأبسط أشكال ممكنة (على سبيل المثال ، بالتنسيق YAML أو JSON أو BEMJSON أو XML أو حتى INF) ، وعند الإخراج ، ارسم نموذجًا جميلًا مع عناصر تحكم عاملة في المستعرض.


من الناحية المهنية ، لست مشتركًا في تطوير الويب ، وبالتالي لم أتوقع أن أكون عالقًا لفترة طويلة في هذه المرحلة.


لم أكن لأكتب مقالًا ، لكنني اعتقدت بعد ذلك أن عرضًا خارجيًا جديدًا لتقنيات الويب الحديثة ، حتى المبتدئين ، قد يكون مثيراً للاهتمام للمجتمع. فرصة للحصول على التعليقات مرة أخرى ...


HTML و CSS قوالب


كل ما وجدته لم ينجح كما أردت. لا أريد أن أعرف أي شيء عن التصميم والأساليب. لا أريد أيضًا ملء HTML ، حيث يتم ذلك عند تطبيق أطر عمل مثل Bootstrap ، Skeleton ، MDL ، إلخ.


نموذج التعليمة البرمجية باستخدام 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!' ] }) 

عندما قمت بالتمرير حول الشاشة العشرين للنص ، وكان شريط التمرير لا يزال في الجزء العلوي ، اعتقدت أن هذا المسار القصير كان طويلًا إلى حد ما. إنه لن ينجح.


بالمناسبة ، قرأت عن هذا BEM - أعجبني الجوهر ، وقد تم وصفه جيدًا وجيدًا. هناك العديد من أوراق الغش ، على سبيل المثال ، أعجبني هذا . لقد بحثت أيضًا عن معلومات ووجدت أن الجميع لا يحب التكنولوجيا (على سبيل المثال ، هنا وهنا ). وهنا ، في رأيي ، تم ذكر جوهر النقاط المثيرة للجدل.


الشيء المثير للاهتمام هو أن استخدام البحث ، بصرف النظر عن BEM ، لم أستطع العثور على مزيد من التقنيات البديلة لفترة طويلة. ومع ذلك ، فهي: OOCS ( يشبه نوع BEM نفسه ، أبسط فقط) ، SMACSS ، AtomicCSS ، CSSinJS (موجود هنا ).


نود.جي إس


ثم فكرت ، حسنًا ، يمكنك التخلي عن الفكرة الأصلية وتنفيذ جزء الخادم بلغة نصية ، أي ببساطة استخدام 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> 

العقدة ناقص فقط أنه من الممكن كتابة شيء أكثر إنتاجية ، وذلك باستخدام الذهاب.
لنفترض أنني أريد استخدام العقيدات. يوجد فهرس لحزم 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(); . خيار مثير للاهتمام ، ولكن ليس هذا.


هناك أيضًا عنصر Element و Riot و TotalJS و iView . يمكن إضافة هذا إلى القائمة من Bootstrap ، MDL ، إلخ.


مثال رمز الصفحة باستخدام العنصر:


 <!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


لقد وجدت أيضًا شيئًا مثيرًا للاهتمام على الويب: 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. في هذه الحالة ، تحتاج إلى البحث عن شيء مختلف تمامًا. ولكن إذا أردنا أن يعمل المستخدم معنا في نافذة متصفح واحدة ، وفي هذه النافذة ، انظر النوافذ الفرعية لتطبيق الويب ، فلن يكون من المنطقي تخزين رمز css / js على العميل في ذاكرة التخزين المؤقت ، والذي سيتلقى أوامر قصيرة من الخادم مع وصف النموذج التالي وسوف رسمها على حساب موارد العملاء؟


الزملاء ، أين تخفي إطار الواجهة التعريفي؟ )


يجب أن يكون! لماذا لا يمكنني العثور عليه؟

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


All Articles