नाकआउट पर एक जटिल आवेदन लिखना

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

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

बिल्ली के नीचे, मैं अपने जटिल आवेदन का आधार दे दूंगा। यह स्वयं बिल्कुल जटिल नहीं है, लेकिन मॉड्यूलर और विस्तार योग्य है, और टेम्पलेट और मॉडल गतिशील रूप से लोड किए जाते हैं। इस प्रस्तुति में इस विचार की जासूसी की गई थी - http://www.knockmeout.net/2012/08/thatconference-2012-session.html , प्रस्तुति कोड github पर उपलब्ध है - https://github.com/rniemeyer/SamplePresentation - इस पर आधारित हम अपना कोड लिखेंगे।

पीछे हटना

सबसे पहले, मैंने एक पृष्ठ पर कई रूपों को लपेटने का उल्लेख किया है - यह हमारी विधि नहीं है, बल्कि एक बिल्कुल सामान्य समाधान है। दो बदली जाने वाली टेम्पलेट्स के एक छोटे से सिंगल पेज एप्लिकेशन का एक उदाहरण आपके होम साइट पर ट्यूटोरियल में पाया जा सकता है - http://learn.knockoutjs.com/#/?tutorial=webmail

एक और पीछे हटना

डेटा-बाइंड = "..." विशेषताओं में सीधे HTML टेम्पलेट में लिंक घोषित करने के विचार के लिए, इसके सिंटैक्स के लिए कुछ डांट। जैसे कि 90 के दशक में जावास्क्रिप्ट कोड आवेषण के साथ लौटने पर ऐसा है जैसे कि onclick = ".." में। हाँ, सब कुछ eval के माध्यम से काम करता है। दावे न्यायोचित हैं - आप समस्या निवारण प्रकार बंधन में पड़ सकते हैं
<div data-bind=”value: name, event: { focus: function() { viewModel.selectItem($data); }, blur: function() { viewModel.selectItem(null); }”></div> 
इस लेख में html कोड स्वच्छता के लिए बड़े पैमाने पर चर्चा की गई है - http://www.knockmeout.net/2011/08/simplifying-and-cleaning-up-views-in.html । आपको dependObservable का उपयोग करने की आवश्यकता है, कस्टम-बाइंडिंग करते हैं, अनाम कार्यों से बचें। आप अपना बाइंडिंग पॉवइडर लिख सकते हैं या इस https://github.com/rniemeyer/knockout-classBindingBrovider का उपयोग कर सकते हैं।

लक्ष्य

यदि आप एक वास्तविक एप्लिकेशन लिखते हैं, तो एक आधार के रूप में नॉकआउट से उदाहरण लेते हुए, आपको विशाल अखंड मॉडल मिलते हैं, और यह स्पष्ट नहीं हो सकता है कि उन्हें कैसे विकसित और डिबग करना है। मेरे उदाहरण का मुख्य लक्ष्य कोड को दृश्य टुकड़ों में तोड़ने का एक तरीका दिखाना है।

मैं वर्णन करूंगा कि हमारे पास आखिर में क्या होगा। हम मॉड्यूल फ़ोल्डर में संबंधित फाइलों में टेम्पलेट फोल्डर फ़ोल्डर और नॉकआउट-जेएस में HTML फाइलों में टेम्पलेट होंगे। कुछ क्रियाओं के साथ, एक विधि शुरू की जाएगी, जो टेम्पलेट और कोड को वांछित div में लोड करेगी। उदाहरण के लिए अंतिम कोड यहाँ है: https://github.com/Kasheftin/ko-test

StringTemplateEngine

बॉक्स से बाहर नॉकआउट, टेम्पलेट के साथ काम करने के दो तरीकों का समर्थन करता है - अनाम और नाम । उदाहरण:
 //  <div data-bind="foreach: items"> //   <li> <span data-bind="name"></span> <span data-bind="price"></span> </li> </div> //  <div data-bind="template: {name:'person-template',data:person}"></div> <script type="text/html" id="person-template"> //   <h3 data-bind="text: name"></h3> <p>Credits: <span data-bind="text: credits"></span></p> </script> 

सभी मामलों में, टेम्पलेट मौजूदा डोम ट्री के टुकड़े हैं। हमारे मामले में, कोड सर्वर से एक स्ट्रिंग के रूप में आएगा, और सबसे कार्बनिक समाधान आपके टेम्पलेट इंजन को लिखना है। आप इस लेख से सिद्धांत जान सकते हैं, http://www.knockmeout.net/2011/10/ko-13-preview-part-3-template-sources.html । शायद एक अच्छा टर्नकी समाधान है https://github.com/ifandelse/Knockout.js-External-Template-Engine , लेकिन हम शुरुआत में जिस प्रेजेंटेशन के बारे में लिखे थे, उसी के आधार पर अपना लिखेंगे।

यहां प्रेजेंटेशन से stringTemplateEngine कोड दिया गया है - https://github.com/rniemeyer/SamplePresentation/blob/master/js/stringTemplateEngine.js । मुझे क्या पसंद नहीं है: वैश्विक सरणी ko.templates का उपयोग किया जाता है, जिसमें डाउनलोड किए गए टेम्प्लेट लिखे जाते हैं, और टेम्प्लेट को उन नामों के साथ आने की आवश्यकता होती है जिनके द्वारा उन्हें बुलाया जाता है। हम इस सरणी का उपयोग नहीं करेंगे, क्योंकि आवश्यकता है। कैशिंग के साथ व्यवहार करता है। हमारे stringTemplateEngine इस तरह से कुछ कहा जाएगा:
 <div data-bind="with: currentState"> <div data-bind="template: {html:html,data:data}"></div> </div> 
यही है, अगर html संपत्ति निर्दिष्ट की जाती है, तो हमारे stringTemplateEngine कहा जाता है, अन्यथा हम इसे निष्पादन के लिए मानक नॉकआउट में वापस कर देते हैं। currentState एक ऐसी वस्तु है जिसमें html कोड के साथ html गुण और संभवतः एक मॉड्यूल ऑब्जेक्ट के साथ डेटा होना चाहिए।

इसलिए, एक नया टेम्पलेट बनाएं:
 ko.templateSources.stringTemplate = function(element,html) { this.domElement = element; this.html = ko.utils.unwrapObservable(html); } ko.templateSources.stringTemplate.prototype.text = function() { if (arguments.length == 0) return this.html; this.html = ko.utils.unwrapObservable(arguments[0]); } 

और हम nativeTemplateEngine ऑब्जेक्ट से makeTemplateSource विधि को फिर से परिभाषित करते हैं। अब तक कोई भी बाइक - मेक टेमप्लस सोर्स रिडिफाइनमेंट में नहीं लिखा गया है। हालाँकि, अंतर्निहित मेकमाईटीपी सोर्स केवल टेम्प्लेट और टेम्प्लेकेंडमेंट को इनपुट के रूप में स्वीकार करता है, जहां टेम्प्लेट टेम्पलेट का नाम है, यदि कोई हो, और किसी अन्य मामले में वर्तमान डोम का लिंक हो। टाइप कन्फ्यूजन एक अच्छा उपाय नहीं है। इसके अलावा, हमारे StringTemplateEngine को जोड़ने के लिए, हमें नाम विशेषता नहीं, बल्कि html विशेषता की जांच करनी होगी। ऐसा कोई डेटा नहीं है, लेकिन वे रेंडरटेम्पलेट पद्धति में आते हैं, इसलिए हम इसे भी फिर से परिभाषित करते हैं:
 var engine = new ko.nativeTemplateEngine(); //   renderTemplate -   makeTemplateSource    engine.renderTemplate = function(template,bindingContext,options,templateDocument) { var templateSource = this.makeTemplateSource(template, templateDocument, bindingContext, options); return this.renderTemplateSource(templateSource, bindingContext, options); } //  ,   2  engine.makeTemplateSource = function(template, templateDocument, bindingContext, options) { //  engine  knockout- if (typeof template == "string") { templateDocument = templateDocument || document; var elem = templateDocument.getElementById(template); if (!elem) throw new Error("Cannot find template with ID " + template); return new ko.templateSources.domElement(elem); } //  stringTemplateEngine,  options else if (options && options.html) { return new ko.templateSources.stringTemplate(template,options.html); } else if ((template.nodeType == 1) || (template.nodeType == 8)) { //  engine   knockout- return new ko.templateSources.anonymousTemplate(template); } else throw new Error("Unknown template type: " + template); } ko.setTemplateEngine(engine); 

ओवरराइडिंग रेंडर टेटप्लेट नॉकआउट को नहीं तोड़ता है क्योंकि मेकमाईप्लेट सोर्स केवल इसमें कहा जाता है और यहां वर्णित एक अन्य रीराइटइटेमप्लेट पद्धति में: https://github.com/SteveSanderson/knockout/blob/master/src/templating/templateEngine.js । हालाँकि, उत्तरार्द्ध नहीं कहा जाता है क्योंकि allowTemplateRewriting = false nativeTemplateEngine में सेट है।

हमारे stringTemplateEngine का पूरा कोड यहां पाया जा सकता है: https://github.com/Kasheftin/ko-test/blob/master/js/stringTemplateEngine.js

State.js

अब हम State.js लिखेंगे - यह एक ऐसा ऑब्जेक्ट है, जब इनिशियलाइज़ होने पर, निर्दिष्ट टेम्पलेट और मॉड्यूल को लोड करेगा। हमारे राज्यों को एक-दूसरे में घोंसला दिया जाएगा, इसलिए आवेदन स्वयं भी एक राज्य होगा, राज्य इसमें एक मेनू के साथ संलग्न किया जाएगा जो अन्य राज्यों को प्रपत्र और डेटा के साथ लोड करेगा।

 define(["knockout","text"],function(ko) { return function(file,callback) { var s = this; s.callback = callback; s.data = ko.observable(null); s.html = ko.observable(null); require(["/js/modules/" + file + ".js","text!/js/templates/" + file + ".html"],function(Module,html) { s.data(typeof Module === "function" ? new Module(s) : Module); s.html(html); if (s.callback && typeof s.callback === "function") s.callback(s); }); s.setVar = function(i,v) { var data = s.data(); data[i] = v; s.data(data); } } }); 

यह सब कोड है। HTML स्क्रिप्ट लोड करने के लिए AMD स्क्रिप्ट, नॉकआउट और आवश्यकता.जेएस पाठ प्लगइन का उपयोग करें। इनपुट फ़ाइल का नाम और कॉलबैक विधि है, दो अवलोकन योग्य चर डेटा और HTML के अंदर, वही जो हमारे stringTemplateEngine में आवश्यक हैं। सेटवर विधि भी बनाई गई है - कई राज्य एक ही समय में पृष्ठ पर रहते हैं, उन्हें डेटा का आदान-प्रदान करना चाहिए। आमतौर पर, रूट राज्य का एक संदर्भ सेटवार को दिया जाएगा, और वहां से सब कुछ मिलेगा।

main.js
मुख्य पृष्ठ के लिए HTML कोड में कुछ लाइनें होती हैं:
 <body> <div class="container" data-bind="template:{html:html,data:data}"></div> <script type="text/javascript" data-main="/js/main" src="/lib/require/require.js"></script> </body> 

हम उस मुख्य फ़ाइल को लिखते हैं जिसे पृष्ठ लोड और आवश्यकता के बाद निष्पादित किया जाएगा। js:
 require(["knockout","state","stringTemplateEngine"], function(ko,State) { var sm = new State("app",function(state) { ko.applyBindings(state); }); }); 


App.js, App.html

मैंने पहले ही लिखा है कि आवेदन भी एक राज्य है। सब कुछ एक दूसरे में अंतर्निहित है। पृष्ठ में मेनू और सामग्री शामिल हैं। इसलिए पेज लेआउट के लिए HTML-कोड टेम्प्लेट / app.html में है, और मेनू और सामग्री का इनिशियलाइज़ेशन मॉड्यूल / ऐप में है ।jpg:
 // templates/app.html: <div class="row"> <div data-bind="with:menu"><div class="span3 menu" data-bind="template:{html:html,data:data}">Menu</div></div> <div data-bind="with:currentState"><div class="span9 content" data-bind="template:{html:html,data:data}"></div></div> </div> 
 // modules/app.js: define(["knockout","state"],function(ko,State) { return function() { var app = this; this.menu = new State("menu",function(state) { // ,  callback-,    app,  app       state- state.setVar("app",app); }); this.currentState = ko.observable(null); } }); 


Menu.js, Menu.html

मैं मेनू का एक और उदाहरण दूंगा। जब आप लिंक पर क्लिक करते हैं, तो दूसरे राज्य की सामग्री, करंट स्टेयट वैरिएबल, जो राज्य ऐप में निहित है, बदल जाता है। इसका उपयोग इसलिए है क्योंकि मेनू प्रारंभ होने पर ऐप को सेट वीयर पर भेजा गया था।
 // menu.html <ul class="nav nav-list"> <li><a href="javascript:void(0);" data-bind="click:gotoSample" data-id="1">Hello World</a></li> <li><a href="javascript:void(0);" data-bind="click:gotoSample" data-id="2">Click counter</a></li> <li><a href="javascript:void(0);" data-bind="click:gotoSample" data-id="3">Simple list</a></li> ... 
 // menu.js: define(["jquery","knockout","state"],function($,ko,State) { return function() { var menu = this; this.gotoSample = function(obj,e) { var sampleId = $(e.target).attr("data-id"); var newState = new State("samples/sample" + sampleId,function(state) { state.setVar("app",menu.app); //     app.currentState, ..   observable- currentState,     menu.app.currentState(state); }); } } }); 

वह सब है। कोड पहले से ही मॉड्यूल में टूट गया है। विभिन्न tins वाले उदाहरणों के पृष्ठों को लाइव उदाहरणों से कॉपी-पेस्ट किया जाता है, केवल amd-form में सजाया जाता है। फिर यह सभी शुरुआती, अजाक्स-एस के साथ भरी हुई है, लेकिन ये पहले से ही "स्थानीय" विवरण हैं जो राज्य-एस में झूठ हैं।

एक बार फिर मैं उदाहरण के अंतिम कोड का लिंक दूंगा - https://github.com/Kasheftin/ko-test

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


All Articles