paint-brush
फ़्लटर के लिए सर्वर संचालित UI इंजन कैसे बनाएंद्वारा@alphamikle
1,250 रीडिंग
1,250 रीडिंग

फ़्लटर के लिए सर्वर संचालित UI इंजन कैसे बनाएं

द्वारा Mike Alfa30m2024/06/13
Read on Terminal Reader

बहुत लंबा; पढ़ने के लिए

Nui के निर्माण के पीछे की कहानी - फ़्लटर के लिए सर्वर संचालित UI इंजन, जो एक बड़े प्रोजेक्ट - बैकएंडलेस CMS Nanc का हिस्सा है।
featured image - फ़्लटर के लिए सर्वर संचालित UI इंजन कैसे बनाएं
Mike Alfa HackerNoon profile picture
0-item
1-item

नमस्ते!

आज मैं आपको दिखाऊंगा कि फ़्लटर में सर्वर-ड्रिवेन UI के लिए एक सुपर-डुपर इंजन कैसे बनाया जाता है, जो एक सुपर-डुपर CMS का एक अभिन्न अंग है (इसी तरह इसका निर्माता, यानी मैं, इसे पोजिशन करता हूँ)। बेशक, आपकी राय अलग हो सकती है, और मुझे टिप्पणियों में इस पर चर्चा करने में खुशी होगी।


यह लेख श्रृंखला के दो (पहले से ही तीन) लेखों में से पहला है। इस लेख में हम सीधे Nui पर नज़र डालेंगे, और अगले लेख में - Nui को Nanc CMS के साथ कितनी गहराई से एकीकृत किया गया है, और इस लेख और अगले लेख के बीच एक और लेख होगा जिसमें Nui के प्रदर्शन के बारे में बहुत सारी जानकारी होगी।


इस लेख में सर्वर-ड्रिवेन यूआई, नुई (नैन्स सर्वर-ड्रिवेन यूआई) क्षमताओं, प्रोजेक्ट इतिहास, स्वार्थी हितों और डॉक्टर स्ट्रेंज के बारे में बहुत सारी रोचक बातें होंगी। अरे हाँ, GitHub और pub.dev के लिंक भी होंगे, इसलिए अगर आपको यह पसंद है और आप अपना 1-2 मिनट का समय देने में संकोच नहीं करते हैं - तो मुझे आपका स्टार और लाइक पाकर खुशी होगी।


विषयसूची

  1. पहचान
  2. विकास के कारण
  3. अवधारणा का सबूत
  4. वाक्य - विन्यास
  5. आईडीई संपादक
  6. प्रदर्शन
  7. घटक और UI निर्माण
  8. खेल का मैदान
  9. अन्तरक्रियाशीलता और तर्क
  10. डेटा स्थानांतरण
  11. प्रलेखन
  12. भविष्य की योजनाएं

एक छोटा सा परिचय

मैंने पहले ही नैनक के बारे में एक लेख लिखा है, लेकिन तब से, एक वर्ष से अधिक समय बीत चुका है और परियोजना ने क्षमताओं और "पूर्णता" के संदर्भ में काफी प्रगति की है, और सबसे महत्वपूर्ण बात - इसे तैयार दस्तावेज के साथ, और एमआईटी लाइसेंस के तहत जारी किया गया था।

तो नैन्सी क्या है?

यह एक सामान्य उद्देश्य वाला CMS है जो अपने बैकएंड को अपने साथ नहीं खींचता। साथ ही, यह React Admin जैसा कुछ नहीं है, जहाँ कुछ बनाने के लिए आपको ढेर सारा कोड लिखना पड़ता है।


Nanc का उपयोग शुरू करने के लिए यह पर्याप्त है:

  1. उन डेटा संरचनाओं का वर्णन करें जिन्हें आप Dart DSL का उपयोग करके CMS के माध्यम से प्रबंधित करना चाहते हैं
  2. एक API परत लिखें जो CMS और आपके बैकएंड के बीच संचार को क्रियान्वित करती है


इसके अलावा, पहला काम पूरी तरह से CMS के इंटरफ़ेस के ज़रिए ही किया जा सकता है - यानी, आप UI के ज़रिए डेटा संरचनाओं का प्रबंधन कर सकते हैं। दूसरे काम को छोड़ा जा सकता है अगर:

  1. आप फ़ायरबेस का उपयोग कर रहे हैं
  2. या आप सुपाबेस का उपयोग कर रहे हैं
  3. या फिर आप Nanc को वास्तविक बैकएंड से जोड़े बिना ही चलाना चाहते हैं - एक स्थानीय डेटाबेस के साथ (फिलहाल, यह भूमिका JSON फ़ाइल या लोकलस्टोरेज द्वारा निभाई जाती है)


इस प्रकार, कुछ परिदृश्यों में, आपको अपनी किसी भी सामग्री और डेटा को प्रबंधित करने के लिए CMS प्राप्त करने के लिए कोड की एक भी पंक्ति नहीं लिखनी होगी। भविष्य में, इन परिदृश्यों की संख्या में वृद्धि होगी, मान लीजिए - प्लस ग्राफ़क्यूएल और रेस्टएपीआई। यदि आपके पास इस बारे में कोई विचार है कि SDK को और किस तरह लागू किया जा सकता है - तो मुझे टिप्पणियों में सुझाव पढ़कर खुशी होगी।


नैनक इकाइयों - उर्फ मॉडल के साथ काम करता है, जिसे डेटा स्टोरेज लेयर स्तर पर एक टेबल (SQL) या एक दस्तावेज़ (No-SQL) के रूप में दर्शाया जा सकता है। प्रत्येक इकाई में फ़ील्ड होते हैं - SQL से कॉलम का प्रतिनिधित्व, या No-SQL से समान "फ़ील्ड"।


संभावित फ़ील्ड प्रकारों में से एक तथाकथित "स्क्रीन" प्रकार है। यानी, यह पूरा लेख CMS से सिर्फ़ एक फ़ील्ड का टेक्स्ट है। साथ ही, आर्किटेक्चरली यह इस तरह दिखता है - एक पूरी तरह से अलग लाइब्रेरी है ( वास्तव में कई लाइब्रेरीज़ ), जो एक साथ Nui नामक सर्वर-ड्रिवेन UI इंजन को लागू करती हैं। यह कार्यक्षमता CMS में एकीकृत है, जिसके ऊपर बहुत सारी अतिरिक्त सुविधाएँ शामिल हैं


इसके साथ, मैं नैनक को समर्पित परिचयात्मक भाग का समापन करता हूं और नुई के बारे में कहानी शुरू करता हूं।

ये सब कैसे शुरू हुआ

अस्वीकरण: सभी संयोग आकस्मिक हैं। यह कहानी काल्पनिक है। मैंने इसे सपने में देखा था।

मैंने एक बड़ी कंपनी में एक साथ कई एप्लीकेशन पर काम किया। वे काफी हद तक एक जैसे थे, लेकिन उनमें कई अंतर भी थे।

लेकिन उनमें जो पूरी तरह से समान था, उसे मैं आर्टिकल इंजन कह सकता हूँ। इसमें कई (5-10-15, मुझे अब ठीक से याद नहीं है) हज़ारों लाइनें थीं, जो कि कोड की तरह उखड़ी हुई थीं और बैकएंड से JSON को प्रोसेस करती थीं। इन JSON को अंततः UI में बदलना पड़ा, या यूँ कहें कि मोबाइल एप्लिकेशन में पढ़े जाने वाले आर्टिकल में।


लेख एडमिन पैनल का उपयोग करके बनाए और संपादित किए गए थे, और नए तत्वों को जोड़ने की प्रक्रिया बहुत, अविश्वसनीय रूप से, अत्यंत दर्दनाक और लंबी थी। इस भयावहता को देखते हुए, मैंने पहला अनुकूलन प्रस्तावित करने का फैसला किया - गरीब सामग्री प्रबंधकों पर दया करना और उनके लिए एडमिन पैनल में ब्राउज़र में ही वास्तविक समय में लेखों का पूर्वावलोकन करने की कार्यक्षमता लागू करना।


कहा और किया। कुछ समय बाद, एप्लिकेशन का एक छोटा सा हिस्सा एडमिन पैनल में घूम रहा था, जिससे कंटेंट मैनेजर्स को बदलावों का पूर्वावलोकन करने में बहुत समय की बचत हुई। यदि, पहले, उन्हें एक डीप लिंक बनाना पड़ता था, और फिर प्रत्येक बदलाव के लिए डेव बिल्ड खोलना पड़ता था, इस लिंक का अनुसरण करना पड़ता था, डाउनलोड होने का इंतज़ार करना पड़ता था, और फिर सब कुछ दोहराना पड़ता था, अब वे बस लेख बना सकते थे और उन्हें तुरंत देख सकते थे।


लेकिन मेरा विचार यहीं नहीं रुका - मैं इस इंजन से और अन्य डेवलपर्स से बहुत परेशान था क्योंकि यह निर्धारित करना संभव था कि उन्हें इसमें कुछ जोड़ने की जरूरत है या सिर्फ ऑगियन अस्तबल को साफ करना है।


यदि यह बाद वाला था, तो डेवलपर हमेशा बैठकों में अच्छे मूड में रहता था - हालांकि गंध... कैमरा उसे कैप्चर नहीं कर सकता।

यदि यह पहला मामला था, तो डेवलपर अक्सर बीमार रहता था, भूकंपों का सामना करता था, कंप्यूटर खराब रहता था, सिरदर्द, उल्कापिंडों के प्रभाव, अंतिम चरण के अवसाद या उदासीनता की अधिकता से ग्रस्त रहता था।


इंजन की कार्यक्षमता का विस्तार करने के लिए एडमिन पैनल में कई नए फ़ील्ड जोड़ने की भी आवश्यकता थी ताकि सामग्री प्रबंधक नई सुविधाओं का उपयोग कर सकें।


यह सब देखते हुए, मेरे मन में एक अविश्वसनीय विचार आया: क्यों न इस समस्या का एक सामान्य समाधान बनाया जाए? एक ऐसा समाधान जो हमें प्रत्येक नए तत्व के लिए एडमिन पैनल और एप्लिकेशन को लगातार बदलने और विस्तारित करने से रोकेगा। एक ऐसा समाधान जो इस समस्या को हमेशा के लिए हल कर देगा! और यहाँ आता है...

धूर्त लालची छोटी योजना

मैंने सोचा - "मैं इस समस्या को हल कर सकता हूँ। मैं कंपनी को कई दसियों, यदि सैकड़ों हजारों नहीं तो बचा सकता हूँ; लेकिन यह विचार कंपनी के लिए इतना मूल्यवान हो सकता है कि वह इसे उपहार के रूप में न दे सके ।"


उपहार से मेरा मतलब है कि कंपनी के लिए संभावित मूल्य का अनुपात उस राशि से भिन्न होता है जो कंपनी मुझे वेतन के रूप में देगी। यह ऐसा है जैसे कि आप किसी स्टार्टअप में शुरुआती चरण में काम करने गए लेकिन किसी बड़ी कंपनी में आपको दिए जाने वाले वेतन से कम वेतन पर और कंपनी में कोई शेयर नहीं। और फिर स्टार्टअप एक यूनिकॉर्न बन जाता है, और वे आपसे कहते हैं - "अच्छा, यार, हमने तुम्हें वेतन दिया।" और वे सही होंगे!


मुझे समानताएँ पसंद हैं, लेकिन मुझे अक्सर कहा जाता है कि वे मेरी खासियत नहीं हैं। यह ऐसा है जैसे आप एक मछली हैं जो समुद्र में तैरना पसंद करती है, लेकिन आप एक मीठे पानी की मछली हैं।


और फिर - मैंने अपने खाली समय में, अवधारणा का प्रमाण (पीओसी) बनाने का निर्णय लिया, ताकि कुछ ऐसे विचार प्रस्तुत करके कोई गलती न हो जाए, जिन्हें क्रियान्वित करना भी संभव न हो।

अवधारणा का सबूत

मूल योजना मार्कडाउन रेंडरिंग के लिए मौजूदा तैयार लाइब्रेरी का उपयोग करने की थी, लेकिन इसकी क्षमताओं का विस्तार किया ताकि यह न केवल मार्कडाउन सूची से मानक तत्वों को प्रस्तुत कर सके, बल्कि कुछ और अधिक जटिल चीजों को भी प्रस्तुत कर सके। लेख केवल चित्रों के साथ पाठ नहीं थे। इसमें एक सुंदर दृश्य डिजाइन, अंतर्निहित ऑडियो प्लेयर और बहुत कुछ भी था।


मैंने इस परिकल्पना का परीक्षण करने के लिए शुक्रवार शाम से सोमवार सुबह तक 40 घंटे बिताए - यह लाइब्रेरी नई सुविधाओं के लिए कितनी विस्तार योग्य है, सामान्य रूप से सब कुछ कितना अच्छा काम करता है, और सबसे महत्वपूर्ण बात - क्या यह समाधान कुख्यात इंजन को सिंहासन से उखाड़ फेंक सकता है। परिकल्पना की पुष्टि हुई - लाइब्रेरी को हड्डियों तक अलग करने और थोड़ा पैचिंग करने के बाद, कीवर्ड या विशेष सिंटैक्स निर्माण द्वारा किसी भी UI तत्व को पंजीकृत करना संभव हो गया, यह सब आसानी से विस्तारित किया जा सकता था, और सबसे महत्वपूर्ण बात - यह वास्तव में लेख इंजन को बदल सकता है। मैं कहीं 15 घंटे में आया। शेष 25 मैंने POC को अंतिम रूप देने में बिताए।


विचार केवल एक इंजन को दूसरे से बदलने का नहीं था - नहीं। विचार पूरी प्रक्रिया को बदलने का था! एडमिन पैनल न केवल आपको लेख बनाने की अनुमति देता है बल्कि एप्लिकेशन में दिखाई देने वाली सामग्री को भी प्रबंधित करता है। मूल विचार एक पूर्ण प्रतिस्थापन बनाने का था जो किसी विशिष्ट परियोजना से बंधा नहीं होगा बल्कि इसे प्रबंधित करने की अनुमति देगा। सबसे महत्वपूर्ण बात - इस प्रतिस्थापन को इन लेखों के लिए एक सुविधाजनक संपादक भी प्रदान करना चाहिए ताकि उन्हें बनाया जा सके और तुरंत परिणाम देखा जा सके।


POC के लिए, मैंने सोचा कि सिर्फ़ एक संपादक बनाना ही काफ़ी होगा। यह कुछ इस तरह दिखता था:

यूआई संपादक

40 घंटों के बाद, मेरे पास एक काम करने वाला कोड एडिटर था जिसमें मार्कडाउन और कस्टम XML टैग्स (उदाहरण के लिए, <container> ) का एक अशांत मिश्रण था, इस कोड से वास्तविक समय में UI प्रदर्शित करने वाला एक पूर्वावलोकन, और साथ ही इस दुनिया में अब तक का सबसे बड़ा आई बैग भी था। यह भी ध्यान देने योग्य है कि इस्तेमाल किया गया "कोड एडिटर" सिंटैक्स हाइलाइटिंग में सक्षम एक और लाइब्रेरी है, लेकिन परेशानी यह है कि यह मार्कडाउन को हाइलाइट कर सकता है, यह XML को भी हाइलाइट कर सकता है, लेकिन एक होजपॉज की हाइलाइटिंग लगातार टूटती रहती है। तो 40 घंटों के लिए, आप एक चिमेरा के बंदर-कोडिंग के लिए कुछ और जोड़ सकते हैं जो एक बोतल में दोनों की हाइलाइटिंग प्रदान करेगा। यह पूछने का समय है - आगे क्या हुआ?


पहला डेमो

अगला डेमो था। मैंने कुछ वरिष्ठ प्रबंधकों को इकट्ठा किया, उन्हें समस्या को हल करने के लिए अपना दृष्टिकोण समझाया, तथ्य यह है कि मैंने इस दृष्टिकोण की व्यवहार में पुष्टि की, और दिखाया कि क्या काम करता है और कैसे, और इसकी क्या संभावनाएं हैं।


लोगों को काम पसंद आया। और इसे इस्तेमाल करने की इच्छा भी थी। लेकिन एक लालच भी था। मेरा लालच। क्या मैं इसे ऐसे ही कंपनी को नहीं दे सकता था? बिल्कुल नहीं। लेकिन मैंने ऐसा करने की योजना भी नहीं बनाई थी। डेमो एक साहसी योजना का हिस्सा था जहाँ मैंने उन्हें अपने हुनर से चौंका दिया, वे बस विरोध नहीं कर सके और इस अविश्वसनीय, विशिष्ट और अद्भुत विकास का उपयोग करने के लिए किसी भी शर्त को पूरा करने के लिए तैयार थे। मैं इस काल्पनिक (!) कहानी के सभी विवरणों का खुलासा नहीं करूँगा, लेकिन मैं केवल इतना कहूँगा कि मुझे पैसे चाहिए थे। पैसे और छुट्टी। एक महीने की छुट्टी, साथ ही पैसे भी। कितना पैसा इतना महत्वपूर्ण नहीं है, यह केवल इतना महत्वपूर्ण है कि राशि मेरे वेतन और संख्या 6 से मेल खाती हो।

लेकिन मैं पूरी तरह से लापरवाह साहसी व्यक्ति नहीं था।


डोरमामु, मैं सौदेबाजी करने आया हूँ। और सौदा इस प्रकार था - मैं अपने मोड में दो पूरे सप्ताह काम करता हूँ ( 4 घंटे सोता हूँ, 20 घंटे काम करता हूँ ), POC को "हमारे ऐप उद्देश्यों के लिए इस्तेमाल किया जा सकता है" की स्थिति में पूरा करता हूँ, और इसके समानांतर, मैं एप्लिकेशन में एक नई सुविधा लागू करता हूँ - एक पूरी स्क्रीन, इस अल्ट्रा-चीज़ का उपयोग करके (जिसके लिए ये दो सप्ताह मूल रूप से आवंटित किए गए थे)। और दो सप्ताह के अंत में, हम एक और डेमो आयोजित करते हैं। केवल इस बार हम अधिक लोगों को इकट्ठा करते हैं, यहाँ तक कि कंपनी के शीर्ष प्रबंधन को भी, और यदि वे जो देखते हैं वह उन्हें प्रभावित करता है, और वे इसका उपयोग करना चाहते हैं - सौदा हो जाता है, मैं अपनी इच्छाएँ पूरी करता हूँ, और कंपनी को एक सुपर गन मिलती है। यदि वे इनमें से कुछ भी नहीं चाहते हैं - तो मैं इस तथ्य को स्वीकार करने के लिए तैयार हूँ कि मैंने इन दो हफ्तों में मुफ्त में काम किया है।


पेड्रा फुराडा (उरुबिसी के पास)

खैर, उरुबिसी की यात्रा, जिसकी मैंने अपनी महीने भर की छुट्टी के लिए पहले से ही योजना बनाई थी, दुर्भाग्य से, कभी नहीं हुई। प्रबंधक लोगों ने इस तरह की दुस्साहस के लिए सहमत होने की हिम्मत नहीं की। और मैं, अपनी निगाहें जमीन पर झुकाते हुए, "क्लासिक तरीके" से एक नई स्क्रीन को काटने चला गया। लेकिन ऐसी कोई कहानी नहीं है जिसमें मुख्य पात्र, भाग्य से पराजित होकर, अपने घुटनों से उठकर अपने जानवर को फिर से वश में करने की कोशिश न करे।


हालाँकि नहीं... ऐसा लगता है कि ये हैं: 1 , 2 , 3 , 4 , 5


इन सभी फिल्मों को देखने के बाद, मैंने फैसला किया कि यह एक संकेत था! और यह इस तरह से और भी बेहतर है - कुछ अच्छे सामानों के लिए इस तरह के आशाजनक विकास को बेचना अफ़सोस की बात है ( मैं किससे मजाक कर रहा हूँ??? ), और मैं अपनी परियोजना को आगे भी विकसित करना जारी रखूँगा। और मैंने जारी रखा। लेकिन अब सप्ताहांत पर 40 घंटे नहीं, बल्कि सप्ताह में केवल 15-20 घंटे, अपेक्षाकृत शांत गति से।

कोड करना है या नहीं करना है?

चौथी दीवार को तोड़ना कोई आसान काम नहीं है। ठीक वैसे ही जैसे दिलचस्प शीर्षकों के साथ आने की कोशिश करना जो पाठक को पढ़ना जारी रखने और कंपनी के साथ कहानी के अंत का इंतज़ार करने के लिए मजबूर कर दे। मैं कहानी को दूसरे लेख में समाप्त करूँगा। और अब, ऐसा लगता है, कार्यान्वयन, कार्यात्मक क्षमताओं और उन सभी पर स्विच करने का समय आ गया है, जो सिद्धांत रूप में, इस लेख को तकनीकी और HackerNoon को और बेहतर बनाना चाहिए!

वाक्य - विन्यास

पहली बात जिसके बारे में हम बात करेंगे वह है सिंटैक्स। मूल हॉजपॉज-आइडिया POC के लिए उपयुक्त था, लेकिन जैसा कि अभ्यास से पता चला है, मार्कडाउन इतना सरल नहीं है। साथ ही, कुछ मूल मार्कडाउन तत्वों को पूरी तरह से फ़्लटर वाले तत्वों के साथ संयोजित करना हमेशा सुसंगत नहीं होता है।


सबसे पहला सवाल यह है - क्या छवि ![Description](Link) या <image> होगी?


यदि पहला - तो मैं पैरामीटर्स का समूह कहां रखूं?

यदि दूसरा - तो फिर, हमारे पास पहला क्यों है?


दूसरा सवाल टेक्स्ट का है। टेक्स्ट को स्टाइल करने के लिए फ़्लटर की संभावनाएँ असीमित हैं। मार्कडाउन की संभावनाएँ "सो-सो" हैं। हाँ, आप टेक्स्ट को बोल्ड या इटैलिक में मार्क कर सकते हैं, और स्टाइलिंग के लिए इन निर्माणों ** / __ का उपयोग करने के बारे में भी विचार थे। फिर बीच में <color="red"> text </color> टैग को धकेलने के विचार थे, लेकिन यह इतना घुमावदार और रेंगने वाला है कि आँखों से खून बहने लगता है। किसी तरह का HTML प्राप्त करना, अपने स्वयं के सीमांत सिंटैक्स के साथ, बिल्कुल भी वांछनीय नहीं था। साथ ही, विचार यह था कि यह कोड तकनीकी ज्ञान के बिना भी प्रबंधकों द्वारा लिखा जा सकता है।


चरण दर चरण, मैंने चिमेरा का हिस्सा हटा दिया और एक मार्कडाउन सुपर-म्यूटेंट प्राप्त किया। यानी, हमें मार्कडाउन रेंडर करने के लिए एक पैच की गई लाइब्रेरी मिली, लेकिन कस्टम टैग से भरी हुई और मार्कडाउन सपोर्ट के बिना। यानी, जैसे कि हमें XML मिल गया हो।


मैं सोचने और प्रयोग करने के लिए बैठ गया कि अन्य सरल वाक्यविन्यास क्या हैं। JSON स्लैग है। किसी व्यक्ति को कुटिल फ़्लटर संपादक में JSON लिखने के लिए कहना एक पागल व्यक्ति को प्राप्त करना है जो आपको मारना चाहेगा। और यह केवल इतना ही नहीं है, मुझे ऐसा नहीं लगता कि JSON सामान्य रूप से किसी व्यक्ति द्वारा टाइप करने के लिए उपयुक्त है, विशेष रूप से UI के लिए - यह लगातार दाईं ओर बढ़ रहा है, अनिवार्य "" का एक गुच्छा, कोई टिप्पणी नहीं है। YAML? अच्छा, हो सकता है। लेकिन कोड साइडवेज भी क्रॉल करेगा। दिलचस्प लिंक हैं, लेकिन आप अकेले उनकी मदद से बहुत कुछ हासिल नहीं कर सकते। TOML? Pf-ff।


ठीक है, मैंने आखिरकार XML पर ही फैसला किया। मुझे लगा, और अब भी लगता है, कि यह एक "घना" वाक्यविन्यास है, जो UI के लिए बहुत उपयुक्त है। आखिरकार, HTML लेआउट डिज़ाइनर अभी भी मौजूद हैं, और यहाँ सब कुछ वेब की तुलना में और भी सरल होगा ( शायद )।


इसके बाद, सवाल उठा - कुछ हाइलाइटिंग/कोड पूर्णता की संभावना प्राप्त करना अच्छा होगा। साथ ही तार्किक निर्माण, कुछ हद तक {{ user.name }} फिर मैंने ट्विग, लिक्विड के साथ प्रयोग करना शुरू किया, कुछ अन्य टेम्पलेट इंजनों को देखा जो मुझे अब याद नहीं हैं। लेकिन मैं एक और समस्या में पड़ गया - मानक इंजन, जैसे कि ट्विग पर जो योजना बनाई गई थी, उसका कुछ हिस्सा लागू करना काफी संभव है, लेकिन यह निश्चित रूप से सब कुछ लागू करने के लिए काम नहीं करेगा। और हाँ, यह अच्छा है कि ऑटो-पूर्णता और हाइलाइटिंग होगी, लेकिन वे केवल तभी हस्तक्षेप करेंगे जब आप मानक ट्विग सिंटैक्स के शीर्ष पर अपनी खुद की नई सुविधाएँ रोल करेंगे, जो फ़्लटर के लिए आवश्यक होगी। नतीजतन, XML के साथ, सब कुछ बहुत अच्छा निकला, ट्विग/लिक्विड के साथ प्रयोगों ने कोई उत्कृष्ट परिणाम नहीं दिए, और कुछ बिंदुओं पर, मैं कुछ सुविधाओं को लागू करने की असंभवता में भी भाग गया। इसलिए, विकल्प अभी भी XML के पास ही रहा। हम सुविधाओं के बारे में अधिक बात करेंगे, लेकिन अभी के लिए, आइए ऑटो-पूर्णता और हाइलाइटिंग पर ध्यान केंद्रित करें, जो ट्विग/लिक्विड में बहुत आकर्षक थे।


आईडीई

अगली बात जो मैं कहना चाहता हूँ वह यह है कि फ़्लटर में टेढ़े-मेढ़े टेक्स्ट इनपुट हैं। वे मोबाइल फ़ॉर्मेट में अच्छे से काम करते हैं। डेस्कटॉप फ़ॉर्मेट में भी अच्छे हैं, जब किसी चीज़ की बात आती है, तो ठीक है, अधिकतम 5-10 लाइन की ऊँचाई। लेकिन जब एक पूर्ण कोड संपादक की बात आती है, जहाँ यह संपादक फ़्लटर में लागू किया जाता है - तो आप इसे बिना आँसू के नहीं देख सकते। ट्रेलो में, जहाँ मैं सभी कार्यों पर नज़र रखता हूँ, और नोट्स और विचार लिखता हूँ, वहाँ ऐसा "कार्य" है:


UI कोड संपादक को बदलने का कार्य


वास्तव में, परियोजना पर काम करने की शुरुआत से ही, मैंने Nui कोड संपादक को किसी और अधिक उपयुक्त चीज़ से बदलने का विचार मन में रखा। मान लीजिए - VS कोड से ओपन सोर्स भाग के साथ एक वेब दृश्य एम्बेड करें। लेकिन अभी तक, मेरे हाथ इस तक नहीं पहुँच पाए हैं, इसके अलावा, इस संपादक की वक्रता की समस्या का एक बैसाखी लेकिन अभी भी काम करने वाला समाधान मेरे दिमाग में आया - इसके बजाय अपने स्वयं के विकास वातावरण का उपयोग करें।


यह इस प्रकार प्राप्त किया जाता है - यूआई-कोड (एक्सएमएल) के साथ एक फ़ाइल बनाएं, आदर्श रूप से एक्सटेंशन .html / .twig के साथ, उसी फ़ाइल को CMS - वेब / डेस्कटॉप / लोकल / डिप्लॉयड के माध्यम से खोलें - इससे कोई फर्क नहीं पड़ता। और उसी फ़ाइल को किसी भी IDE के माध्यम से खोलें, यहाँ तक कि VS कोड के वेब संस्करण के माध्यम से भी। और वोइला - आप इस फ़ाइल को अपने पसंदीदा टूल में संपादित कर सकते हैं, और ब्राउज़र या कहीं भी वास्तविक समय का पूर्वावलोकन कर सकते हैं।


नैन्सी + आईडीई सिंक


ऐसे परिदृश्य में, आप पूर्ण-विकसित ऑटो-कम्प्लीशन पर भी शिकंजा कस सकते हैं। VS कोड में, कस्टम HTML टैग के माध्यम से इसे लागू करने की संभावना है। हालाँकि, मैं VS कोड का उपयोग नहीं करता, मेरी पसंद IntelliJ IDEA है और इस IDE के लिए अब ऐसा कोई सरल समाधान नहीं है (ठीक है, कम से कम ऐसा नहीं था, या कम से कम मुझे यह नहीं मिला)। लेकिन एक अधिक सामान्य समाधान है जो वहाँ और वहाँ दोनों जगह काम करेगा - XML स्कीमा परिभाषा (XSD)। मैंने इस राक्षस को समझने की कोशिश में लगभग 3 शामें बिताईं, लेकिन सफलता कभी नहीं मिली, और अंत में, मैंने इस मामले को छोड़ दिया, इसे बेहतर समय के लिए छोड़ दिया।


यह भी दिलचस्प है कि अंत में, प्रयोगों, अपडेट्स, मान लीजिए, XML को विजेट में बदलने के लिए जिम्मेदार इंजन के कई पुनरावृत्तियों के बाद, हमें ऐसा समाधान मिला जिसके लिए भाषा विशेष रूप से महत्वपूर्ण नहीं है। आपके UI की संरचना के बारे में जानकारी के वाहक के रूप में, अंततः विकल्प XML पर आ गया, लेकिन साथ ही, आप इसे JSON, और यहां तक कि एक बाइनरी फॉर्म - संकलित प्रोटोबफ भी सुरक्षित रूप से खिला सकते हैं। और यह हमें अगले विषय पर लाता है।


प्रदर्शन

इस वाक्य में, इस लेख का आकार 3218 शब्दों का होगा। जब मैंने इस खंड को लिखना शुरू किया, तो सब कुछ गुणात्मक रूप से करने के लिए - नुई और नियमित फ़्लटर के रेंडरिंग के प्रदर्शन की तुलना करते हुए बहुत सारे परीक्षण मामले लिखना आवश्यक था। चूँकि मेरे पास पहले से ही एक डेमो स्क्रीन लागू थी, जो पूरी तरह से नुई पर बनाई गई थी:


नलमार्ट स्क्रीन डेमो


स्क्रीन का मूल रूप से सटीक मिलान बनाना आवश्यक था (फ्लटर के संदर्भ में, निश्चित रूप से)। नतीजतन, इसमें 3 सप्ताह से अधिक समय लगा, एक ही चीज़ को फिर से लिखना, परीक्षण प्रक्रिया में सुधार करना और अधिक से अधिक दिलचस्प संख्याएँ प्राप्त करना। और अकेले इस खंड का आकार 3500 शब्दों से अधिक था। इसलिए, मुझे यह विचार आया कि एक अलग लेख लिखना समझदारी है जो पूरी तरह से और पूरी तरह से Nui के प्रदर्शन के लिए समर्पित होगा, एक विशेष मामले के रूप में, और अतिरिक्त कीमत के लिए जो आपको भुगतान करना होगा यदि आप एक दृष्टिकोण के रूप में सर्वर-संचालित UI का उपयोग करने का निर्णय लेते हैं।


लेकिन मैं एक छोटा सा स्पॉइलर बनाऊंगा: प्रदर्शन के मूल्यांकन के लिए दो मुख्य परिदृश्य थे जिन पर मैंने विचार किया - प्रारंभिक रेंडरिंग का समय । यह महत्वपूर्ण है यदि आप सर्वर-संचालित यूआई पर पूरी स्क्रीन को लागू करने का निर्णय लेते हैं, और यह स्क्रीन आपके एप्लिकेशन में कहीं खुलेगी।


इसलिए यदि यह स्क्रीन बहुत भारी है, तो एक मूल फ़्लटर स्क्रीन को भी रेंडर होने में लंबा समय लगेगा, इसलिए ऐसी स्क्रीन पर स्विच करते समय, खासकर यदि यह संक्रमण एनीमेशन के साथ होता है, तो लैग दिखाई देंगे। दूसरा परिदृश्य गतिशील UI परिवर्तनों के साथ फ़्रेम समय (FPS) है। डेटा बदल गया है - आपको कुछ घटक को फिर से बनाना होगा। सवाल यह है कि यह रेंडरिंग समय को कितना प्रभावित करेगा, क्या यह इतना प्रभावित करेगा कि जब स्क्रीन अपडेट होगी, तो उपयोगकर्ता को लैग दिखाई देगा। और यहाँ एक और स्पॉइलर है - ज्यादातर मामलों में, आप यह नहीं बता पाएंगे कि जो स्क्रीन आप देख रहे हैं वह पूरी तरह से Nui पर लागू है। यदि आप एक नियमित, मूल फ़्लटर स्क्रीन में एक Nui विजेट एम्बेड करते हैं (मान लीजिए, स्क्रीन का कुछ क्षेत्र जिसे एप्लिकेशन में बहुत गतिशील रूप से बदलना चाहिए) - तो आपको 8ms पहचानने में सक्षम नहीं होने की गारंटी है। पहले वाले के लिए - यह सब स्क्रीन की जटिलता के स्तर पर निर्भर करता है। लेकिन यहां भी, अंतर ऐसा होगा कि यह धारणा को प्रभावित नहीं करेगा और आपके एप्लिकेशन को उपयोगकर्ता स्मार्टफ़ोन के लिए बेंचमार्क नहीं बनाएगा।


नीचे Pixel 7a (Tensor G2, स्क्रीन रिफ्रेश रेट 90 फ्रेम (इस डिवाइस के लिए अधिकतम), 60 फ्रेम प्रति सेकंड की वीडियो रिकॉर्डिंग दर (रिकॉर्डिंग सेटिंग्स के लिए अधिकतम) पर सेट की गई तीन स्क्रीन रिकॉर्डिंग हैं। प्रत्येक 500ms, सूची में तत्वों की स्थिति यादृच्छिक होती है, जिसके डेटा से पहले 3 कार्ड बनाए जाते हैं, और एक और 500ms के बाद, ऑर्डर की स्थिति अगले पर स्विच हो जाती है। क्या आप अनुमान लगा पाएंगे कि इनमें से कौन सी स्क्रीन पूरी तरह से Nui पर लागू की गई है?


PS छवियों का लोडिंग समय कार्यान्वयन पर निर्भर नहीं करता है क्योंकि इस स्क्रीन पर, किसी भी कार्यान्वयन के साथ, बहुत सारी Svg छवियां हैं - सभी आइकन, साथ ही ब्रांड लोगो। सभी svg (साथ ही नियमित चित्र) GitHub पर होस्टिंग के रूप में संग्रहीत हैं, इसलिए वे काफी धीरे-धीरे लोड हो सकते हैं, जो कुछ प्रयोगों में देखा गया है।


यूट्यूब:


उपलब्ध घटक - UI कैसे बनाएं

नुई बनाते समय, मैंने निम्नलिखित अवधारणा का पालन किया - ऐसा उपकरण बनाना आवश्यक है जो, सबसे पहले, फ़्लटर डेवलपर्स को नियमित फ़्लटर एप्लिकेशन बनाने जितना ही उपयोग में आसान लगे। इसलिए, सभी घटकों को नाम देने का तरीका सरल था - उन्हें उसी तरह नाम देना जैसे फ़्लटर में उनका नाम रखा जाता है।


यही बात विजेट पैरामीटर्स पर भी लागू होती है - स्केलर, जैसे String , int , double , enum , आदि, जो एक पैरामीटर के रूप में, स्वयं कॉन्फ़िगर नहीं होते हैं। Nui के भीतर इस प्रकार के पैरामीटर्स को तर्क कहा जाता है। और जटिल क्लास पैरामीटर्स, जैसे Container विजेट में decoration , को property कहा जाता है। यह नियम निरपेक्ष नहीं है क्योंकि कुछ प्रॉपर्टीज़ बहुत अधिक वर्बोज़ हैं, इसलिए उनके नामों को सरल बनाया गया है। साथ ही, कुछ विजेट्स के लिए, उपलब्ध पैरामीटर्स की सूची को विस्तारित किया गया है। उदाहरण के लिए - एक वर्गाकार SizedBox या Container बनाने के लिए, आप दो समान width + height के बजाय केवल एक कस्टम तर्क size पास कर सकते हैं।


मैं कार्यान्वित विजेट्स की पूरी सूची नहीं दूंगा, क्योंकि उनमें से काफी संख्या में हैं (फिलहाल 53)। संक्षेप में - आप लगभग किसी भी UI को कार्यान्वित कर सकते हैं जिसके लिए सिद्धांत रूप में सर्वर-संचालित UI का उपयोग करना समझदारी होगी। इसमें Slivers से जुड़े जटिल स्क्रॉलिंग प्रभाव शामिल हैं।


कार्यान्वित विजेट



इसके अलावा, घटकों के संबंध में, यह ध्यान देने योग्य है कि प्रवेश बिंदु या विजेट जिस पर आपको क्लाउड XML-कोड पास करना होगा। फिलहाल ऐसे दो विजेट हैं - NuiListWidget और NuiStackWidget


डिज़ाइन के अनुसार, यदि आपको पूरी स्क्रीन को लागू करने की आवश्यकता है, तो पहले वाले का उपयोग किया जाना चाहिए। हुड के नीचे, यह एक CustomScrollView है जिसमें सभी विजेट शामिल हैं जिन्हें मूल मार्कअप कोड से पार्स किया जाएगा। इसके अलावा, पार्सिंग, कोई कह सकता है, "बुद्धिमान" है: चूंकि CustomScrollView की सामग्री slivers होनी चाहिए, तो एक संभावित समाधान स्ट्रीम में प्रत्येक विजेट को SliverToBoxAdapter में लपेटना होगा, लेकिन इसका प्रदर्शन पर अत्यधिक नकारात्मक प्रभाव पड़ेगा। इसलिए, विजेट को उनके पैरेंट में इस प्रकार एम्बेड किया जाता है - सबसे पहले से शुरू करते हुए, हम सूची में नीचे जाते हैं जब तक कि हम एक वास्तविक sliver से नहीं मिलते। जैसे ही हम एक sliver से मिलते हैं - हम पिछले सभी विजेट को SliverList में जोड़ते हैं, और इसे पैरेंट CustomScrollView में जोड़ते हैं। इस प्रकार, पूरे UI को रेंडर करने का प्रदर्शन जितना संभव हो उतना उच्च होगा, क्योंकि slivers की संख्या न्यूनतम होगी। CustomScrollView में बहुत सारे slivers होना क्यों बुरा है? इसका उत्तर यहाँ है।


दूसरा विजेट - NuiStackWidget पूर्ण स्क्रीन के रूप में भी इस्तेमाल किया जा सकता है - इस मामले में, यह ध्यान में रखना उचित है कि आप जो कुछ भी बनाते हैं वह उसी क्रम में Stack में एम्बेड किया जाएगा। और slivers स्पष्ट रूप से उपयोग करना भी आवश्यक होगा - यानी, यदि आप slivers की सूची चाहते हैं - तो आपको CustomScrollView जोड़ना होगा और इसके अंदर पहले से ही सूची को लागू करना होगा।


दूसरा परिदृश्य एक छोटे विजेट का कार्यान्वयन है जिसे मूल घटकों में एम्बेड किया जा सकता है। मान लीजिए - एक उत्पाद कार्ड बनाना जो सर्वर की पहल पर पूरी तरह से अनुकूलन योग्य होगा। यह एक बहुत ही दिलचस्प परिदृश्य लगता है जिसमें आप Nui का उपयोग करके घटक लाइब्रेरी में सभी घटकों को लागू कर सकते हैं, और उन्हें नियमित विजेट के रूप में उपयोग कर सकते हैं। साथ ही, एप्लिकेशन को अपडेट किए बिना उन्हें पूरी तरह से बदलने का अवसर हमेशा रहेगा।


यह ध्यान देने योग्य है कि NuiListWidget स्थानीय विजेट के रूप में भी इस्तेमाल किया जा सकता है, न कि पूरी स्क्रीन के रूप में, लेकिन इस विजेट के लिए, आपको उचित प्रतिबंध लागू करने की आवश्यकता होगी, जैसे कि पैरेंट विजेट के लिए स्पष्ट ऊंचाई निर्धारित करना।


यदि counter app फ़्लटर का उपयोग करके बनाया जाए तो वह इस प्रकार दिखाई देगा:

 import 'package:flutter/material.dart'; import 'package:nui/nui.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Nui App', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), home: const MyHomePage(title: 'Nui Demo App'), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({ required this.title, super.key, }); final String title; @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { int _counter = 0; void _incrementCounter() { setState(() { _counter++; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(widget.title), ), body: Center( child: NuiStackWidget( renderers: const [], imageErrorBuilder: null, imageFrameBuilder: null, imageLoadingBuilder: null, binary: null, nodes: null, xmlContent: ''' <center> <column mainAxisSize="min"> <text size="18" align="center"> You have pushed the button\nthis many times: </text> <text size="32"> {{ page.counter }} </text> </column> </center> ''', pageData: { 'counter': _counter, }, ), ), floatingActionButton: FloatingActionButton( onPressed: _incrementCounter, tooltip: 'Increment', child: const Icon(Icons.add), ), ); } }


और यहाँ एक और उदाहरण है, केवल पूरी तरह से नुई पर (तर्क सहित):

 import 'package:flutter/material.dart'; import 'package:nui/nui.dart'; void main() { runApp(const MyApp()); } final DataStorage globalDataStorage = DataStorage(data: {'counter': 0}); final EventHandler counterHandler = EventHandler( test: (BuildContext context, Event event) => event.event == 'increment', handler: (BuildContext context, Event event) => globalDataStorage.updateValue( 'counter', (globalDataStorage.getTypedValue<int>(query: 'counter') ?? 0) + 1, ), ); class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return DataStorageProvider( dataStorage: globalDataStorage, child: EventDelegate( handlers: [ counterHandler, ], child: MaterialApp( title: 'Nui App', theme: ThemeData( colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), useMaterial3: true, ), home: const MyHomePage(title: 'Nui Counter'), ), ), ); } } class MyHomePage extends StatefulWidget { const MyHomePage({ required this.title, super.key, }); final String title; @override State<MyHomePage> createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( backgroundColor: Theme.of(context).colorScheme.inversePrimary, title: Text(widget.title), ), body: Center( child: NuiStackWidget( renderers: const [], imageErrorBuilder: null, imageFrameBuilder: null, imageLoadingBuilder: null, binary: null, nodes: null, xmlContent: ''' <center> <column mainAxisSize="min"> <text size="18" align="center"> You have pushed the button\nthis many times: </text> <dataBuilder buildWhen="counter"> <text size="32"> {{ data.counter }} </text> </dataBuilder> </column> </center> <positioned right="16" bottom="16"> <physicalModel elevation="8" shadowColor="FF000000" clip="antiAliasWithSaveLayer"> <prop:borderRadius all="16"/> <material type="button" color="EBDEFF"> <prop:borderRadius all="16"/> <inkWell onPressed="increment"> <prop:borderRadius all="16"/> <tooltip text="Increment"> <sizedBox size="56"> <center> <icon icon="mdi_plus" color="21103E"/> </center> </sizedBox> </tooltip> </inkWell> </material> </physicalModel> </positioned> ''', pageData: {}, ), ), ); } }


UI कोड को अलग करें ताकि हाइलाइटिंग हो सके:

 <center> <column mainAxisSize="min"> <text size="18" align="center"> You have pushed the button\nthis many times: </text> <dataBuilder buildWhen="counter"> <text size="32"> {{ data.counter }} </text> </dataBuilder> </column> </center> <positioned right="16" bottom="16"> <physicalModel elevation="8" shadowColor="black" clip="antiAliasWithSaveLayer"> <prop:borderRadius all="16"/> <material type="button" color="EBDEFF"> <prop:borderRadius all="16"/> <inkWell onPressed="increment"> <prop:borderRadius all="16"/> <tooltip text="Increment"> <sizedBox size="56"> <center> <icon icon="mdi_plus" color="21103E"/> </center> </sizedBox> </tooltip> </inkWell> </material> </physicalModel> </positioned> 

Nui तर्क के साथ Nui काउंटर ऐप


इसमें इंटरैक्टिव और व्यापक दस्तावेज़ भी है जो प्रत्येक विजेट में क्या तर्क और गुण हैं, साथ ही उनके सभी संभावित मूल्यों के बारे में विस्तृत जानकारी दिखाता है। प्रत्येक गुण के लिए, जिसमें तर्क और अन्य गुण दोनों हो सकते हैं, सभी उपलब्ध मूल्यों के पूर्ण प्रदर्शन के साथ दस्तावेज़ीकरण भी है। इसके अलावा, प्रत्येक घटक में एक इंटरैक्टिव उदाहरण होता है जिसमें आप इस विजेट के कार्यान्वयन को लाइव देख सकते हैं और इसे अपनी इच्छानुसार बदलकर इसके साथ खेल सकते हैं।

नैन्सी खेल का मैदान

Nui को Nanc CMS में बहुत मजबूती से एकीकृत किया गया है। आपको Nui का उपयोग करने के लिए Nanc का उपयोग करने की आवश्यकता नहीं है, लेकिन Nanc का उपयोग करने से आपको लाभ मिल सकते हैं, अर्थात् - वही इंटरैक्टिव दस्तावेज़, साथ ही Playground, जहाँ आप वास्तविक समय में लेआउट के परिणाम देख सकते हैं, उसमें उपयोग किए जाने वाले डेटा के साथ खेल सकते हैं। इसके अलावा, CMS का अपना स्थानीय निर्माण बनाना आवश्यक नहीं है, आप प्रकाशित डेमो के साथ काफी प्रबंधन कर सकते हैं, जिसमें आप अपनी ज़रूरत की हर चीज़ कर सकते हैं।


आप लिंक का अनुसरण करके ऐसा कर सकते हैं, और फिर Page Interface / Screen फ़ील्ड पर क्लिक कर सकते हैं। खुली हुई स्क्रीन को प्लेग्राउंड के रूप में इस्तेमाल किया जा सकता है, और सिंक बटन पर क्लिक करके, आप स्रोतों के साथ एक फ़ाइल के माध्यम से अपने IDE के साथ Nanc को सिंक्रनाइज़ कर सकते हैं, और सभी दस्तावेज़ सहायता बटन पर क्लिक करके उपलब्ध हैं।


पी.एस. ये जटिलताएं इसलिए मौजूद हैं क्योंकि मुझे नैन्सी में घटकों पर दस्तावेज़ीकरण के साथ एक स्पष्ट अलग पृष्ठ बनाने का समय नहीं मिला, साथ ही इस पृष्ठ पर सीधा लिंक डालने में असमर्थता भी थी।


अन्तरक्रियाशीलता और तर्क

XML से विजेट तक एक साधारण मैपर बनाना बहुत ही बेकार होगा। बेशक, यह भी उपयोगी हो सकता है, लेकिन इसके उपयोग के मामले बहुत कम होंगे। एक ही चीज़ नहीं - पूरी तरह से इंटरैक्टिव घटक और स्क्रीन जिनके साथ आप बातचीत कर सकते हैं, जिन्हें आप बारीक रूप से अपडेट कर सकते हैं (यानी, एक साथ नहीं - लेकिन उन हिस्सों में जिन्हें अपडेट करने की आवश्यकता है)। साथ ही, इस UI को डेटा की आवश्यकता होती है। जिसे, सर्वर-संचालित UI वाक्यांश में अक्षर S की उपस्थिति को ध्यान में रखते हुए, सर्वर पर लेआउट में सीधे प्रतिस्थापित किया जा सकता है, लेकिन आप इसे और भी खूबसूरती से कर सकते हैं। और UI में हर बदलाव के लिए बैकएंड से लेआउट के एक नए हिस्से को खींचने के लिए नहीं (Nui कोई टाइम मशीन नहीं है जो jQuery के सर्वोत्तम अभ्यासों को फ़्लटर में लाती है)।


आइए तर्क से शुरू करें: चर और गणना की गई अभिव्यक्तियों को लेआउट में प्रतिस्थापित किया जा सकता है। मान लें कि एक विजेट को इस प्रकार परिभाषित किया गया है <container color="{{ page.background }}"> background चर में संग्रहीत "पैरेंट संदर्भ" को दिए गए डेटा से सीधे अपना रंग निकालेगा। और <aspectRatio ratio="{{ 3 / 4}}"> अपने वंशजों के लिए संबंधित पहलू अनुपात मान सेट करेगा। कुछ तर्क के साथ UI बनाने के लिए बिल्ट-इन फ़ंक्शन, तुलनाएँ और बहुत कुछ इस्तेमाल किया जा सकता है।


दूसरा बिंदु टेम्प्लेटिंग है । आप <template id="your_component_name"/> टैग का उपयोग करके सीधे UI कोड में अपना खुद का विजेट परिभाषित कर सकते हैं। साथ ही, इस टेम्पलेट के सभी आंतरिक घटकों के पास इस टेम्पलेट को दिए गए तर्कों तक पहुंच होगी, जो कस्टम घटकों के लचीले पैरामीटराइजेशन की अनुमति देगा और फिर <component id="your_component_name"/> टैग का उपयोग करके उनका पुन: उपयोग करेगा। टेम्पलेट्स के अंदर, आप न केवल विशेषताएँ बल्कि अन्य टैग/विजेट भी पास कर सकते हैं, जिससे किसी भी जटिलता के पुन: प्रयोज्य घटक बनाना संभव हो जाता है।


बिंदु तीन - "फॉर लूप्स"। Nui में, एक अंतर्निहित <for> टैग है जो आपको एक ही (या एकाधिक) घटकों को कई बार रेंडर करने के लिए पुनरावृत्तियों का उपयोग करने की अनुमति देता है। यह तब सुविधाजनक होता है जब डेटा का एक सेट होता है जिससे आपको विजेट की सूची/पंक्ति/स्तंभ बनाने की आवश्यकता होती है।


चौथा - सशर्त रेंडरिंग। लेआउट स्तर पर, <show> टैग लागू किया जाता है (इसे <if> कहने का विचार था), जो आपको नेस्टेड घटकों को ड्रा करने की अनुमति देता है, या विभिन्न स्थितियों के तहत उन्हें पेड़ में एम्बेड नहीं करने देता है।


बिंदु पाँच - क्रियाएँ। कुछ घटक जिनसे उपयोगकर्ता इंटरैक्ट कर सकता है, वे ईवेंट भेज सकते हैं । जिसे आप अपनी इच्छानुसार पूरी तरह से नियंत्रित कर सकते हैं। मान लीजिए, <inkWell onPressed="something"> - इस तरह की घोषणा के साथ, यह विजेट क्लिक करने योग्य हो जाता है, और आपका एप्लिकेशन, या बल्कि, कुछ EventHandler , इस ईवेंट को हैंडल करने और कुछ करने में सक्षम हो जाएगा। विचार यह है कि तर्क से संबंधित सब कुछ सीधे एप्लिकेशन में लागू किया जाना चाहिए, लेकिन आप कुछ भी लागू कर सकते हैं। कुछ सामान्य हैंडलर बनाएं जो क्रियाओं के समूहों को संभाल सकें, जैसे "स्क्रीन पर जाएं" / "कॉल विधि" / "विश्लेषण ईवेंट भेजें"। डायनेमिक कोड को लागू करने की भी योजना है, लेकिन यहाँ बारीकियाँ हैं। डार्ट के लिए, मनमाने कोड को निष्पादित करने के तरीके हैं, लेकिन यह प्रदर्शन को प्रभावित करता है, और इसके अलावा, एप्लिकेशन कोड के साथ इस कोड की इंटरऑपरेबिलिटी मुश्किल से 100% है। यानी, इस डायनेमिक कोड में लॉजिक बनाकर, आपको लगातार कुछ सीमाओं का सामना करना पड़ेगा। इसलिए, वास्तव में लागू और उपयोगी होने के लिए इस तंत्र को बहुत सावधानी से काम करने की आवश्यकता है।


छठा बिंदु स्थानीय UI अपडेट है। यह <dataBuilder> टैग की बदौलत संभव है। यह टैग (ब्लॉक अंडर द हुड) किसी विशिष्ट फ़ील्ड को "देख" सकता है, और जब यह बदलता है, तो यह अपने सबट्री को फिर से बना देगा।


डेटा

शुरू में, मैंने डेटा के लिए दो स्टोर का रास्ता अपनाया - ऊपर वर्णित "पैरेंट कॉन्टेक्स्ट"। साथ ही "डेटा" - डेटा जिसे <data> टैग का उपयोग करके सीधे UI में परिभाषित किया जा सकता है। ईमानदारी से कहूँ तो, मुझे अब यह तर्क याद नहीं है कि UI में डेटा को संग्रहीत करने और स्थानांतरित करने के दो तरीकों को लागू करना क्यों आवश्यक था, लेकिन मैं किसी भी तरह से इस तरह के निर्णय के लिए खुद की कड़ी आलोचना नहीं कर सकता।


वे इस प्रकार काम करते हैं - "पैरेंट संदर्भ" Map<String, dynamic> प्रकार का एक ऑब्जेक्ट है, जिसे सीधे NuiListWidget / NuiStackWidget विजेट में पास किया जाता है। इस डेटा तक पहुँच उपसर्ग page द्वारा संभव है:

 <someWidget value="{{ page.your.field }}"/>

आप किसी भी चीज़ को, किसी भी गहराई तक संदर्भित कर सकते हैं, जिसमें सरणियाँ भी शामिल हैं - {{ page.some.array.0.users.35.age }} । यदि ऐसी कोई कुंजी/मान नहीं है, तो आपको null मिलेगा। सूचियों को <for> उपयोग करके दोहराया जा सकता है।


दूसरा तरीका - "डेटा" एक वैश्विक डेटा स्टोर है। व्यवहार में, यह एक निश्चित Bloc है जो NuiListWidget / NuiStackWidget की तुलना में पेड़ में उच्चतर स्थित है। साथ ही, DataStorageProvider के माध्यम से DataStorage के अपने स्वयं के उदाहरण को पारित करके, स्थानीय शैली में उनके उपयोग को व्यवस्थित करने से कुछ भी नहीं रोकता है।


साथ ही, पहली विधि प्रतिक्रियाशील नहीं है - यानी, जब page में डेटा बदलता है, तो कोई भी UI खुद को अपडेट नहीं करेगा। चूंकि यह वास्तव में, आपके StatelessWidget के तर्क मात्र हैं। यदि page के लिए डेटा स्रोत, मान लें, आपका अपना Bloc है, जो Nui...Widget को मानों का एक सेट देगा - तो, एक नियमित StatelessWidget की तरह, इसे newdata के साथ पूरी तरह से फिर से तैयार किया जाएगा।


डेटा के साथ काम करने का दूसरा तरीका प्रतिक्रियाशील है। यदि आप इस क्लास के API - updateValue विधि का उपयोग करके DataStorage में डेटा बदलते हैं, तो यह Bloc क्लास की emit विधि को कॉल करेगा, और यदि आपके UI में इस डेटा के सक्रिय श्रोता हैं - <dataBuilder> टैग, तो उनकी सामग्री तदनुसार बदल दी जाएगी, लेकिन UI के बाकी हिस्सों को छुआ नहीं जाएगा।


इस प्रकार, हमें दो संभावित डेटा स्रोत मिलते हैं - एक बहुत ही सरल page , और एक प्रतिक्रियाशील data । इन स्रोतों में डेटा अपडेट करने के तर्क और इन अपडेट के लिए यूआई की प्रतिक्रिया को छोड़कर, उनके बीच कोई अंतर नहीं है।

प्रलेखन

मैंने जानबूझकर काम की सभी बारीकियों और पहलुओं का वर्णन नहीं किया, क्योंकि यह पहले से मौजूद दस्तावेज़ों की एक प्रति बन जाएगा। इसलिए, यदि आप प्रयास करने या बस अधिक जानने में रुचि रखते हैं - तो कृपया यहाँ स्वागत करें। यदि कार्य का कोई पहलू स्पष्ट नहीं है या दस्तावेज़ीकरण कुछ को कवर नहीं करता है, तो मैं समस्या को इंगित करने वाले आपके संदेश से खुश हो जाऊंगा:


मैं संक्षेप में कुछ ऐसी विशेषताओं की सूची दूंगा जो इस लेख में शामिल नहीं हैं, लेकिन आपके लिए उपलब्ध हैं:

  • अपने खुद के टैग/घटक बनाना, उनके लिए बिल्कुल वैसा ही इंटरैक्टिव डॉक्यूमेंटेशन बनाने की क्षमता के साथ, जैसे कि उनके तर्कों और गुणों के लिए लाइव पूर्वावलोकन के साथ। इस तरह, उदाहरण के लिए, SVG छवियों को प्रस्तुत करने के लिए घटक को लागू किया जाता है। इसे इंजन के मूल में धकेलने का कोई मतलब नहीं है, क्योंकि हर किसी को इसकी ज़रूरत नहीं है, लेकिन एक एक्सटेंशन के रूप में केवल एक चर को पास करके उपयोग के लिए उपलब्ध है - आसान और सरल। सीधे -कार्यान्वयन का एक उदाहरण


  • आइकन की एक विशाल अंतर्निहित लाइब्रेरी जिसे आप अपने खुद के जोड़कर विस्तारित कर सकते हैं (यहां मैं असंगत निकला, और "धकेल दिया", तर्क यह था कि जितना संभव हो उतने आइकन तुरंत उपयोग के लिए उपलब्ध कराए जाएं और नए आइकन का उपयोग करने के लिए एप्लिकेशन को अपडेट करने की कोई आवश्यकता नहीं थी)। बॉक्स से बाहर उपलब्ध हैं: fluentui_system_icons , material_design_icons_flutter और remixicon । आप Nanc , Page Interface / Screen -> Icons उपयोग करके सभी उपलब्ध आइकन देख सकते हैं

  • कस्टम फ़ॉन्ट, जिसमें Google फ़ॉन्ट भी शामिल है


  • XML को JSON/protobuf में परिवर्तित करना और उन्हें UI के लिए "स्रोत" के रूप में उपयोग करना


यह सब और बहुत कुछ दस्तावेज़ीकरण में अध्ययन किया जा सकता है।


आगे क्या होगा?

मुख्य बात यह है कि तर्क के साथ कोड को गतिशील रूप से निष्पादित करने की संभावना पर काम करना है। यह एक बहुत ही शानदार सुविधा है जो आपको Nui की क्षमताओं का बहुत गंभीरता से विस्तार करने की अनुमति देगी। साथ ही, आप मानक फ़्लटर लाइब्रेरी से शेष शायद ही कभी इस्तेमाल किए जाने वाले, लेकिन कभी-कभी बहुत महत्वपूर्ण विजेट जोड़ सकते हैं (और आपको ऐसा करना चाहिए)। XSD में महारत हासिल करने के लिए, ताकि सभी टैग के लिए ऑटो-कम्प्लीशन IDE में दिखाई दे (टैग डॉक्यूमेंटेशन से सीधे इस योजना को उत्पन्न करने का एक विचार है, फिर इसे कस्टम विजेट के लिए बनाना आसान होगा और यह हमेशा अप-टू-डेट रहेगा, और डार्ट में एक जेनरेटेड DSL बनाने का भी विचार है, जिसे फिर XML / JSON / Protobuf में परिवर्तित किया जा सकता है)। खैर, और अतिरिक्त प्रदर्शन अनुकूलन - यह अभी बुरा नहीं है, बहुत बुरा नहीं है, लेकिन यह और भी बेहतर हो सकता है, यहां तक कि मूल फ़्लटर के करीब भी।


मेरे पास बस इतना ही है। अगले लेख में, मैं Nui के प्रदर्शन के बारे में विस्तार से बताऊंगा, कि मैंने कैसे टेस्ट केस बनाए, इस प्रक्रिया में मैंने कितने दर्जनों रेक का इस्तेमाल किया, और किन परिदृश्यों में कौन सी संख्याएँ प्राप्त की जा सकती हैं।


यदि आप नुई को आजमाने या इसे बेहतर तरीके से जानने में रुचि रखते हैं - तो कृपया प्रलेखन डेस्क पर जाएं। इसके अलावा, अगर यह मुश्किल नहीं है, तो कृपया GitHub पर एक स्टार और pub.dev पर लाइक डालें - यह आपके लिए मुश्किल नहीं है, लेकिन मेरे लिए, इस विशाल नाव पर एक अकेला नाविक - यह अविश्वसनीय रूप से उपयोगी है।