यह पोस्ट उस श्रृंखला की एक निरंतरता है जो यहां शुरू हुई (पिछले भाग को अवश्य पढ़ा जाना चाहिए)। आज हम तथाकथित "टू-डू लिस्ट" (टोडो- एमवीसी प्रोजेक्ट से टोडो-लिस्ट) बनाएंगे । कोणीय पर बने संस्करण के आधार पर, और डर्बी पर कार्यक्षमता को फिर से बनाने की कोशिश करें।
कार्य विकल्प का अन्वेषण करें
तो, आइए देखें कि हमारे पास कोणीय संस्करण में क्या है, और यह कैसे काम करता है (कार्यक्षमता का पता लगाने के लिए 5 मिनट खर्च करें):
- एक नया कार्य ऊपरी इनपुट फ़ील्ड में दर्ज किया गया है, यह उस सूची में जाता है जब आप एंटर दबाते
enter
; - सूची के किसी भी कार्य को कार्य के दाईं ओर "क्रॉस" पर क्लिक करके हटाया जा सकता है (यदि आप कार्य पर मंडराते हैं);
- कार्य के बाईं ओर "चेकमार्क" पर क्लिक करके "पूर्ण" के रूप में चिह्नित किया जा सकता है (आप बॉक्स को अनचेक कर सकते हैं);
- जब आप कार्य पर डबल-क्लिक करते हैं, तो यह संपादन मोड में जाता है, दाएं, एंटर दबाएं - यह अपडेट हो गया है;
- यदि हमने कार्य पूर्ण कर लिए हैं, तो स्पष्ट पूर्ण बटन नीचे दाईं ओर दिखाई देता है; यदि आप उस पर क्लिक करते हैं, तो पूर्ण कार्य हटा दिए जाएंगे
- यह पूर्ण और सक्रिय कार्यों को गिनता है (और प्रदर्शित करता है)। स्थिति पट्टी में नीचे;
- नीचे भी, स्थिति रेखा में 3 लिंक हैं (सभी, सक्रिय, पूर्ण, क्रमशः url को बदलकर '# /', '# / सक्रिय' और '# / पूर्ण'), उन पर क्लिक करके हम कार्य फ़िल्टर बदलते हैं: या तो सभी प्रदर्शित होते हैं कार्य, या तो केवल सक्रिय (पूर्ण नहीं) या केवल पूर्ण;
हम आधार के रूप में क्या लेंगे
हमारे लक्ष्यों (बेहतर डर्बीज सीखने के लिए) के आधार पर, हम यहां शैलियों के साथ नहीं आएंगे, वे पहले से ही लिखे गए हैं और अधिकांश टूडो एमवीसी कार्यान्वयन में बदलाव के बिना उपयोग किए जाते हैं। बस सीएसएस फ़ाइल ले लो। इस पर एक त्वरित नज़र से पता चलता है कि हमें पृष्ठभूमि bg.png के लिए एक चित्र भी लेना होगा। इसके अलावा, कोणीय द्वारा उत्पन्न html को एक ढांचे के रूप में लें (मैंने इसे ब्राउज़र में डेवलपर टूल का उपयोग करके कॉपी किया और इसे कोणीय निर्देशों से थोड़ा साफ किया)।
मूल HTML कोड
<section id="todoapp"> <header id="header"> <h1>todos</h1> <form id="todo-form"> <input id="new-todo" placeholder="What needs to be done?" autofocus> </form> </header> <section id="main"> <input id="toggle-all" type="checkbox"> <label for="toggle-all">Mark all as complete</label> <ul id="todo-list"> <li> <div class="view"> <input class="toggle" type="checkbox"> <label>hello</label> <button class="destroy"> </button> </div> <form > <input class="edit"> </form> </li> </ul> </section> <footer id="footer"> <span id="todo-count"><strong>0</strong> <span>items left</span> </span> <ul id="filters"> <li><a href="/" class="selected">All</a></li> <li><a href="/active">Active</a></li> <li><a href="/completed">Completed</a></li> </ul> <button id="clear-completed">Clear completed (0)</button> </footer> </section>
जैसा कि आप देख सकते हैं, हमारे HTML में 3 मुख्य ब्लॉक हैं:
- हैडर - यहाँ मुख्य इनपुट है। नए कार्यों को शुरू करने की आवश्यकता है;
- मुख्य - मुख्य ब्लॉक, कार्य सूची खुद ही यहां संग्रहीत है;
- पाद लेख - स्थिति रेखा, यहां जानकारी, फ़िल्टर और 'पूर्ण पूर्ण' बटन के बीच स्विच करना
परियोजना की संरचना
तो, आइए कारण। हमारे प्रोजेक्ट में क्या होगा? एक स्टाइलशीट होगी, स्टैटिक डेटा (बैकग्राउंड इमेज) की वापसी होगी, वहाँ html टेम्पलेट होंगे, कम से कम 2 फाइलें भी होंगी - एप्लिकेशन डर्बी के दो हिस्से (सर्वर पार्ट, और डर्बी एप्लीकेशन खुद)। इस सब के आधार पर, मैंने ऐसी एप्लिकेशन फ़ाइल संरचना को फेंक दिया (आप कोई अन्य कर सकते हैं):
public/ bg.png app # - views/ index.html css/ index.css index.js # - server.js # package.json
कृपया ध्यान दें कि सीएसएस फ़ाइल ऐप फ़ोल्डर के अंदर है, सार्वजनिक फ़ोल्डर के अंदर नहीं। यह इस तथ्य के कारण है कि डर्बी शैलियों के साथ एक विशेष तरीके से काम करता है। परिणामस्वरूप, उन्हें सीधे शैली टैग में पृष्ठ के प्रमुख में डाला जाएगा - जैसा कि Google अनुसंधान (डर्बी के रचनाकारों के अनुसार) द्वारा दिखाया गया है - यह शैलियों को गति में रखने का सबसे अच्छा तरीका है।
इसलिए, जैसा कि मैंने पिछले पाठ में कहा था, ऐप फ़ोल्डर में सब कुछ एक आइसोमॉर्फिक डर्बी एप्लिकेशन है। मुझे "आइसोमॉर्फिक" शब्द पसंद नहीं है और मैं इसे छोड़ दूंगा, मैं केवल "डर्बी के सर्वर भाग" के विपरीत डर्बी आवेदन को कहूंगा। यहां मुद्दा यह है कि इन सभी फाइलों को एक साथ (ऐप में सब कुछ), क्लाइंट ब्राउज़र को एक बंडल (टुकड़ा) दिया जाएगा, इसलिए मैंने उन्हें एक साथ रखा।
सामान्य तौर पर (भविष्य के लिए), आप एक परियोजना को कई डर्बी अनुप्रयोगों में विभाजित कर सकते हैं, उदाहरण के लिए, क्लाइंट भाग और व्यवस्थापक पैनल। यह दो कारणों से उचित है, अनावश्यक डेटा (टेम्प्लेट, स्टाइल, कोड), और कनेक्टिविटी को कम करने के लिए नहीं। यही है, यह इस तरह होगा: परियोजना में एक सर्वर भाग और कई डर्बी अनुप्रयोग होंगे (इस मामले में, दो)।
Package.json फ़ाइल में, निर्भरताएँ समान दो मॉड्यूल होंगी: derby@0.6.0-alpha5 और derby-starter।
शुरुआत हो रही है
एक फ़ाइल संरचना बनाएँ। हम पृष्ठभूमि छवि और शैलियों को डाउनलोड करते हैं जो मैंने शुरुआत में संकेत दिए थे, हम
npm init
का उपयोग करके पैकेज बनाते हैं। आप पिछले पाठ में देख सकते हैं।
एचटीएमएल को थोड़ा घुमाया जाता है, सबसे पहले, पिछले उदाहरण के रूप में, यह पूर्वनिर्धारित
Body:
टेम्प्लेट में होना चाहिए
Body:
दूसरी बात, हम हेडर, मेन और फूटर को अलग-अलग डर्बी टेम्पलेट में रखेंगे।
अंतिम सूचकांक। Html
<Body:> <section id="todoapp"> <view name="header"/> <view name="main"/> <view name="footer"/> </section> <header:> <header id="header"> <h1>todos</h1> <form id="todo-form"> <input id="new-todo" placeholder="What needs to be done?" autofocus> </form> </header> <main:> <section id="main"> <input id="toggle-all" type="checkbox"> <label for="toggle-all">Mark all as complete</label> <ul id="todo-list"> <li> <div class="view"> <input class="toggle" type="checkbox"> <label>hello</label> <button class="destroy"> </button> </div> <form > <input class="edit"> </form> </li> </ul> </section> <footer:> <footer id="footer"> <span id="todo-count"><strong>0</strong> <span>items left</span> </span> <ul id="filters"> <li><a href="/" class="selected">All</a></li> <li><a href="/active">Active</a></li> <li><a href="/completed">Completed</a></li> </ul> <button id="clear-completed">Clear completed (0)</button> </footer>
जैसा कि आपने देखा होगा, अपने स्वयं के टेम्प्लेट को कॉल करना
view
टैग का उपयोग करके किया जाता है, जहां टेम्प्लेट का नाम टेम्पलेट का नाम सेट करता है।
शुरू करने के लिए, हम ब्राउज़र में परिणाम देखने और कार्यक्षमता बढ़ाने में सक्षम होने के लिए न्यूनतम कार्य कोड बनाएंगे।
पिछले उदाहरण से server.js फ़ाइल को परियोजना की संरचना को ध्यान में रखने और स्थिर फ़ाइलों को प्रस्तुत करने के लिए थोड़ा विस्तारित किया गया है।
server.js
var server = require('derby-starter'); var appPath = __dirname + '/app'; var options = { static: __dirname + '/public' }; server.run(appPath, options);
आपको याद दिला दूं कि परियोजना की शैक्षिक प्रकृति के कारण, हम सर्वर भाग के रूप में डर्बी-स्टार्टर मॉड्यूल का उपयोग करते हैं। यदि आप अंदर देखते हैं, तो स्थिर फ़ाइलों की वापसी एक्सप्रेस-स्टेटिक स्टेटिक-मिडलवेयर का एक क्लासिक उपयोग है। अपने लिए देखें।
न्यूनतम सूचकांक ।js:
var derby = require('derby'); var app = module.exports = derby.createApp('todos', __filename); // app , // ( ) global.app = app; app.loadViews (__dirname+'/views'); app.loadStyles(__dirname+'/css'); app.get('/', getTodos); function getTodos(page, model){ page.render(); }
सब कुछ, हम npm शुरू करते हैं (या सीधे नोड server.js), हम ब्राउज़र में देखते हैं http: // localhost: 3000 / परिणाम:
लेआउट के साथ शैलियाँ पकड़ी गईं। एक शुरुआत की गई है।
डिजाइन यूआरएल
पिछले पाठ में, मैंने कहा कि एक डर्बी डेवलपर को परियोजना को उरलों में तोड़कर विकास शुरू करना चाहिए। यह क्लाइंट और सर्वर पर दोनों पृष्ठों को उत्पन्न करने की डर्बी की क्षमता के कारण है, जो खोज इंजन को पसंद है। तो, कोणीय संस्करण का अध्ययन करते समय, हमने देखा कि पाद लेख में 3 लिंक हैं जो यूआरएल को बदलते हैं और, तदनुसार, कार्यों के लिए फ़िल्टर। यहां हम समझते हैं कि हमारे पास एप्लिकेशन में 3 रिक्वेस्ट हैंडलर होने चाहिए। कुछ इस तरह:
app.get('/', getAllTodos); app.get('/active', getActiveTodos); app.get('/completed', getCompletedTodos);
यह उचित होगा यदि ये सभी पृष्ठ अलग-अलग थे, लेकिन हमारे लिए, उनके बीच एकमात्र अंतर फ़िल्टर है, इसलिए हम कोड को न्यूनतम करने की कोशिश करेंगे।
डिजाइन डेटा
कार्य स्वयं
todos
संग्रह में संग्रहीत किए जाएंगे। प्रत्येक कार्य को दो क्षेत्रों द्वारा दर्शाया जाएगा:
- पाठ - कार्य विवरण
- पूर्ण - एक संकेत है कि कार्य पूरा हो गया है
इसमें हमें यह जोड़ना होगा कि प्रत्येक कार्य में, एक आईडी फ़ील्ड भी होगी - डर्बी संग्रह में एक आइटम जोड़ते समय इसे स्वचालित रूप से जोड़ देगा।
इसलिए, डर्बी पद्धति के अनुसार, नियंत्रक में (फ़ंक्शन जो url के अनुरोध को संसाधित करता है), रेंडर करने से पहले, हमें डेटा तैयार करना चाहिए और डेटा को अपडेट करने के लिए सदस्यता को पंजीकृत करना चाहिए। यह बताता है कि हैंडलर को योजनाबद्ध रूप से कुछ इस तरह होना चाहिए:
function getTodos(page, model){ model.subscribe('todos', function(){ page.render(); }); }
यह लगभग समान होगा, लेकिन आगे बढ़ने से पहले (सभी तीन प्रश्नों के लिए एक नियंत्रक बनाने के लिए, केवल कार्यों के लिए अलग-अलग फ़िल्टर करने के लिए) आपको डर्बी मॉडल के बारे में कुछ चीजें सीखने की आवश्यकता है:
- "पथ" एक अंडरस्कोर से शुरू होता है (उदाहरण के लिए, "_session", "_page", आदि)
- "_page" की विशेषता क्या है
- डर्बी फिल्टर क्या है
- एक संग्रह में कुछ डेटा के लिए रेफरी क्या है
आखिरी पाठ में, मैंने तथाकथित "पथों" के बारे में बात की। हम उन्हें मॉडल के साथ संचालन में उपयोग करते हैं। उदाहरण के लिए, डेटा की सदस्यता लेते समय: model.subscribe ('path'), मॉडल को डेटा प्राप्त और लिखते समय:
model.get('')
,
model.set('', )
। रास्तों के उदाहरण:
- 'todos' - पूरे todos संग्रह का लिंक
- 'users.42' - आईडी = 42 के साथ उपयोगकर्ताओं के संग्रह में प्रविष्टि को देखें
तो यहाँ है। पथ का पहला खंड है, जैसा कि आप समझते हैं, संग्रह का नाम। यह डर्बी नाम या तो एक लैटिन पत्र के साथ, या अक्षर $ या _ के साथ शुरू हो सकता है। $ और _ से शुरू होने वाले सभी संग्रह विशेष हैं, वे सर्वर के साथ सिंक्रनाइज़ नहीं हैं (वे मॉडल के लिए स्थानीय हैं, और डर्बी एप्लिकेशन में केवल एक मॉडल बनाया गया है)। अपनी आवश्यकताओं के लिए $ आरक्षित डर्बी के साथ शुरू होने वाले संग्रह। एक अंडरस्कोर के साथ शुरू होने वाले संग्रह डेवलपर्स द्वारा उपयोग किए जाते हैं।
थोड़ा प्रयोग करते हैं। ब्राउज़र में डेवलपर कंसोल खोलें और
app.model.get()
टाइप
app.model.get()
- आउटपुट देखें।
"_" - संग्रह में से एक विशेष एक है -
_page
, यह हर बार
_page
जाता है जब यूआरएल
_page
- यह सभी प्रकार के कामकाजी डेटा को संग्रहीत करने के लिए बहुत सुविधाजनक बनाता है। इस पाठ में आपको और उदाहरण दिखाई देंगे।
चलिए फ़िल्टर पर चलते हैं। यदि आप मॉडल के लिए प्रलेखन पढ़ते हैं, तो आप जानते हैं कि डर्बी में प्रतिक्रियाशील डेटा के साथ काम को सुविधाजनक बनाने के लिए विभिन्न तंत्र हैं। यह, उदाहरण के लिए, प्रतिक्रियाशील फ़ंक्शंस, डेटा, डेटा फ़िल्टर, डेटा सॉर्टर्स के साथ होने वाली विभिन्न घटनाओं के लिए सदस्यता।
फिल्टर पर चर्चा करते हैं। हम कैसे लागू कर सकते हैं, उदाहरण के लिए, केवल सक्रिय कार्य दिखाने वाला फ़िल्टर:
हम एक विशिष्ट नाम से एक फिल्टर फ़ंक्शन रजिस्टर करते हैं (बंडल में क्रमांकन के लिए नाम आवश्यक है)। प्रलेखन कहता है कि आपको उन्हें
app.on('model')
में सख्ती से पंजीकृत करने की आवश्यकता है
app.on('model', function(model) { model.fn('completed', function(item) { return item.completed; }); });
और आगे नियंत्रक में, हम इस फ़िल्टर का उपयोग todos संग्रह को फ़िल्टर करने के लिए करते हैं:
function getPage(page, model){ model.subscribe('todos', function() { var filter = model.filter('todos', 'completed') filter.ref('_page.todos'); page.render(); }); }
यहां लाइन
filter.ref('_page.todos');
बहुत महत्वपूर्ण है
filter.ref('_page.todos');
, इसमें, फ़िल्टर किया गया "todos"
_page.todos
पथ पर उपलब्ध हो जाता है। यह सब एक साथ रखकर, मैं यहाँ प्रस्तावित करता हूं कि नियंत्रकों के साथ एक फ़िल्टर कोड है:
app.on('model', function(model) { model.fn('all', function(item) { return true; }); model.fn('completed', function(item) { return item.completed;}); model.fn('active', function(item) { return !item.completed;}); }); app.get('/', getPage('all')); app.get('/active', getPage('active')); app.get('/completed', getPage('completed')); function getPage(filter){ return function(page, model){ model.subscribe('todos', function() { model.filter('todos', filter).ref('_page.todos'); page.render(); }); } }
जैसा कि आपने शायद देखा था, हर चीज को एकजुट करने के लिए, मुझे एक झूठा फिल्टर "ऑल" करना पड़ा, लेकिन मुझे लगता है कि यह कोई कमी नहीं है।
ठीक है, हम थोड़ा विचलित हुए। आइए आवेदन को पुनर्जीवित करें।
कार्यों को जोड़ना और सूचीबद्ध करना
हमारे लेआउट में डेटा इनपुट के लिए इनपुट इस तरह दिखता है:
<form id="todo-form"> <input id="new-todo" placeholder="What needs to be done?" autofocus> </form>
डर्बी में क्लासिक पैटर्न (कई आधुनिक चौखटे में) प्रतिक्रियाशील बंधन है।
_page
में कुछ पथ के साथ इनपुट में दर्ज मूल्य को
_page
।
enter
पर क्लिक करने के लिए हम फॉर्म के
submit
इवेंट हैंडलर को भी पंजीकृत करेंगे:
<form id="todo-form" on-submit="addTodo(_page.newTodo)"> <input id="new-todo" placeholder="What needs to be done?" autofocus value="{{_page.newTodo}}"> </form>
on-submit
बजाय
on-submit
हम स्वाभाविक रूप से
on-click
,
on-keyup
,
on-focus
लिख
on-click
- अर्थात, यह डर्बी में घटनाओं को संभालने का मानक तरीका है। हम हैंडलर को
app.proto
में
app.proto
(जब हम डर्बी घटकों पर चर्चा करते हैं, तो हम देखेंगे कि प्रत्येक घटक अपने हैंडलर को खुद में संग्रहीत करता है, लेकिन अब हम ऐसा करते हैं):
app.proto.addTodo = function(newTodo){ if (!newTodo) return; this.model.add('todos', { text: newTodo, completed: false }); this.model.set('_page.newTodo', ''); };
जांचें कि क्या पाठ खाली है, कार्य को संग्रह में जोड़ें,
input
साफ करें। आपने देखा होगा कि हमारे पास हैंडलर में केवल एक ही पैरामीटर है, यदि किसी कारण से हमें इवेंट ऑब्जेक्ट या स्वयं html तत्व के संदर्भ की आवश्यकता है, तो हमें इसे html में इस तरह स्पष्ट रूप से लिखना होगा:
on-submit="addTodo(_page.newTodo, $event, $element)"
,
$event
और
$element
विशेष पैरामीटर हैं, जो डर्बी द्वारा ही भरे गए हैं।
अब फ़िल्टर किए गए कार्य सूची का आउटपुट - हमारे
ul
तत्व को संपादित करें:
<ul id="todo-list"> {{each _page.todos as #todo, #index}} <li class="{{if #todo.completed}}completed{{/}}"> <div class="view"> <input class="toggle" type="checkbox" checked="{{#todo.completed}}"> <label>{{#todo.text}}</label> <button class="destroy"> </button> </div> <form> <input class="edit"> </form> </li> {{/each}} </ul>
तो क्या किया:
- हम सभी todos (पहले से ही फ़िल्टर) के माध्यम से लूप करते हैं - उनके लिए तत्व बनाते हैं-
li
- कार्य के विवरण को
lable
में प्रिंट करें -
todo.completed
कोcheckbox
बांधtodo.completed
- यदि कार्य पूरा हो गया है, तो
li
टैग के लिएcompleted
वर्ग निर्धारित करें।
आइटम हटाएं
यह प्राथमिक रूप से किया जाता है:
<button class="destroy" on-click="delTodo(#todo.id)"> </button>
app.proto.delTodo = function(todoId){ this.model.del('todos.' + todoId); };
और यह भी कम संभव था:
<button class="destroy" on-click="model.del('todos.' + #todo.id)"> </button>
सभी "पूर्ण" कार्यों को हटाना समान है ("पूरा हुआ" बटन नीचे दाईं ओर से है):
<button id="clear-completed" on-click="clearCompleted()"> Clear completed (0) </button>
app.proto.clearCompleted = function(){ var todos = this.model.get('todos'); for (var id in todos) { if (todos[id].completed) this.model.del('todos.'+id); } }
तत्वों का संपादन
डबल-क्लिक करके, कार्य को संपादन मोड में जाना चाहिए। लेआउट द्वारा देखते हुए, जब इस मोड पर स्विच किया जाता है, तो हमें
editing
वर्ग को संबंधित
li
तत्व में जोड़ना होगा। इसके साथ ही, आपको उस चयन से छुटकारा पाने की आवश्यकता होगी जो तब होता है जब आप डबल-क्लिक करते हैं और सही ढंग से हमारे द्वारा आवश्यक इनपुट पर ध्यान केंद्रित करते हैं।
मैं इसे निम्नानुसार करने का प्रस्ताव करता हूं: हम पथ का उपयोग करके संपादित कार्य के बारे में जानकारी संग्रहीत करेंगे - _page.edit । वहां हम एडिट किए गए टास्क की आईडी और टेक्स्ट को स्टोर करेंगे।
पाठ को अलग से क्यों संग्रहीत किया जाता है, क्या यह पहले से ही कार्य में संग्रहीत है?
यह सब लक्ष्यों पर निर्भर करता है। यदि हम कार्य को इनपुट से सीधे पाठ से जोड़ते हैं, तो उपयोगकर्ता तत्व को सीधे डेटाबेस में संपादित करेगा। यही है, इसके संपादन (एक बटन का प्रत्येक प्रेस) तुरन्त ब्राउज़र में अन्य उपयोगकर्ताओं को दिखाया जाएगा। इसके अलावा, एक ही समय में कई उपयोगकर्ता पाठ को संपादित कर सकते हैं और सभी परिवर्तनों को देख सकते हैं, लेकिन यह वह नहीं है जिसकी हमें आवश्यकता है। सामान्य परिदृश्य अंत में संपादित किए गए डेटा के डेटाबेस के लिए प्रतिबद्ध है, या प्रतिबद्ध होने से इनकार करता है ... यही है, सब कुछ हर किसी के लिए अपडेट किया जाना चाहिए जब उपयोगकर्ता
।
enter
।
इसलिए, हम यह सब लागू करते हैं:
<ul id="todo-list"> {{each _page.todos as #todo}} <li class="{{if #todo.completed}}completed{{/}} {{if _page.edit.id === #todo.id}}editing{{/}}"> <div class="view"> <input class="toggle" type="checkbox" checked="{{#todo.completed}}"> <label on-dblclick="editTodo(#todo)">{{#todo.text}}</label> <button class="destroy" on-click="delTodo(#todo.id)"> </button> </div> <form on-submit="doneEditing(_page.edit)"> <input id="{{#todo.id}}" class="edit" value="{{_page.edit.text}}" on-keyup="cancelEditing($event)"> </form> </li> {{/each}} </ul>
app.proto.editTodo = function(todo){ this.model.set('_page.edit', { id: todo.id, text: todo.text }); window.getSelection().removeAllRanges(); document.getElementById(todo.id).focus() } app.proto.doneEditing = function(todo){ this.model.set('todos.'+todo.id+'.text', todo.text); this.model.set('_page.edit', { id: undefined, text: '' }); } app.proto.cancelEditing = function(e){ // 27 = ESQ-key if (e.keyCode == 27) { this.model.set('_page.edit.id', undefined); } }
एक डबल क्लिक के साथ, EditTodo फ़ंक्शन को ट्रिगर किया जाता है , इसमें हम _path.edit को भरते हैं , अनावश्यक चयन को हटाते हैं , हमें जिस इनपुट की आवश्यकता होती है उस पर ध्यान केंद्रित करते हैं (यहां मैंने थोड़ा धोखा दिया, इनपुट
id = todo.id
)।
संपादन समाप्त करने के बाद, या तो दर्ज करें या esq दबाएँ। तदनुसार, दो संचालकों में से एक
doneEditing
: किया
doneEditing
,
cancelEditing
doneEditing
,
cancelEditing
। कोड जानें - कोई नई बात नहीं।
सक्रिय और पूर्ण कार्यों की संख्या - प्रतिक्रियाशील कार्य
इसलिए, आखिरी चीज जो हम करेंगे, वह पाद लेख में सक्रिय और पूर्ण किए गए कार्यों की संख्या प्रिंट करना है। यह समझाने का एक अच्छा कारण है कि प्रतिक्रियाशील कार्य क्या हैं।
परियोजना की वास्तुकला के बारे में एक छोटी सी टिप्पणी
यह ध्यान दिया जाना चाहिए कि मेरे द्वारा चुना गया आवेदन कार्यान्वयन विकल्प केवल एक ही नहीं है। इसे टांका लगाने से, एक विशिष्ट परियोजना तुरंत लाइव-क्वेरी का उपयोग करते हुए दिमाग में आती है - यह एक और भयानक डर्बी तंत्र है जो आपको डेटाबेस के लिए एक मैंगो-अनुरोध करने की अनुमति देता है, जिसके परिणाम प्रतिक्रियात्मक रूप से अपडेट किए जाएंगे। प्रश्नों में, निश्चित रूप से, आप विभिन्न चयन, सॉर्टिंग, मात्रा सीमा (
,
,
) का उपयोग कर सकते हैं। आप प्रश्न भी बना सकते हैं जो संग्रह में तत्वों की संख्या लौटाते हैं (किसी भी चयन के साथ) - यह सिर्फ हमारा मामला है। हम निम्नलिखित पदों में से एक में "लाइव" प्रश्नों का अध्ययन करते हैं, लेकिन अब मैंने प्रतिक्रियात्मक कार्यों के माध्यम से कार्यान्वयन को दिखाना उचित समझा, जो अक्सर वास्तविक अनुप्रयोगों में भी उपयोग किया जाता है।
$limit
,
$skip
,
$orderby
) का उपयोग कर सकते हैं। आप प्रश्न भी बना सकते हैं जो संग्रह में तत्वों की संख्या लौटाते हैं (किसी भी चयन के साथ) - यह सिर्फ हमारा मामला है। हम निम्नलिखित पदों में से एक में "लाइव" प्रश्नों का अध्ययन करते हैं, लेकिन अब मैंने प्रतिक्रियात्मक कार्यों के माध्यम से कार्यान्वयन को दिखाना उचित समझा, जो अक्सर वास्तविक अनुप्रयोगों में भी उपयोग किया जाता है।
तो, एक प्रतिक्रियाशील फ़ंक्शन एक फ़ंक्शन है जो हर बार ट्रिगर होता है जब कुछ डेटा बदलता है। यही है, हमें संकेत करना चाहिए कि यह विशेष प्रतिक्रियाशील फ़ंक्शन इन विशिष्ट डेटा के परिवर्तन की निगरानी करेगा। यह डेटा इस फ़ंक्शन में पैरामीटर के रूप में आता है। फिर वह कुछ गणना करती है और परिणाम लौटाती है। इसके परिणाम एक विशिष्ट "पथ" से जुड़े होते हैं ...
ठीक है, यह सब सार है और इसलिए पढ़ना मुश्किल है। चलो हमारे उदाहरण का उपयोग करें। हमारे पास सक्रिय और पूर्ण कार्यों के साथ टॉडोस का संग्रह है। यह अच्छा होगा यदि, संग्रह में किसी भी बदलाव पर, हम, कहीं न कहीं (उदाहरण के लिए,
_page.counters
path के साथ), सक्रिय और पूर्ण कार्यों के काउंटरों तक पहुँच प्राप्त कर सकते हैं। कुछ इस तरह:
_page.counters = { active: 2, completed: 3 }
तब हम आसानी से पाद लेख में इस डेटा को प्रदर्शित कर सकते थे।
इन काउंटरों को प्राप्त करने का एक विकल्प प्रतिक्रियाशील कार्यों का उपयोग करना है। वे फिल्टर के रूप में उसी तरह पंजीकृत हैं:
app.on('model', function(model) { model.fn('all', function(item) { return true; }); model.fn('completed', function(item) { return item.completed;}); model.fn('active', function(item) { return !item.completed;}); model.fn('counters', function(todos){ var counters = { active: 0, completed: 0 }; for (var id in todos) { if(todos[id].completed) counters.completed++; else counters.active++; } return counters; }) });
इस प्रकार हमने
counters
कार्य को पंजीकृत किया, लेकिन यह सब नहीं है। इसे अभी भी सही समय पर लॉन्च करने और रास्तों से बंधे रहने की आवश्यकता है। यह कंट्रोलर में
model.start
फ़ंक्शन का उपयोग करके किया
model.start
है:
model.subscribe('todos', function () { model.filter('todos', filter).ref('_page.todos'); model.start('_page.counters', 'todos', 'counters'); page.render(); });
यह अब, काउंटर हमारे टेम्प्लेट में उपलब्ध हैं। हम फूटर को अंतिम रूप दे रहे हैं:
<footer:> <footer id="footer"> <span id="todo-count"><strong>{{_page.counters.active}} </strong> <span>items left</span> </span> <ul id="filters"> <li><a href="/" class="{{if $render.url==='/' }}selected{{/}}">All</a></li> <li><a href="/active" class="{{if $render.url==='/active' }}selected{{/}}">Active</a></li> <li><a href="/completed" class="{{if $render.url==='/completed'}}selected{{/}}">Completed</a></li> </ul> <button id="clear-completed" on-click="clearCompleted()" class="{{if _page.counters.completed==0}}hidden{{/}}"> Clear completed ({{_page.counters.completed}}) </button> </footer>
यदि आवश्यक कार्य पूर्ण न हों, तो हमने आवश्यक काउंटर दिखाए, साथ ही "क्लियर कम्प्लीट" बटन को छिपाए। हमने ब्राउज़र में सांत्वना में
app.model.get()
के अध्ययन के दौरान प्राप्त जानकारी का उपयोग करते हुए,
selected
वर्ग को उस लिंक में जोड़ा है जो सक्रिय है। हां, आरक्षित
$render
संग्रह में विभिन्न उपयोगी जानकारी है, विशेष रूप से रेंडर करने के लिए
url
गया
url
। कंसोल पर फिर से नज़र डालें।
परिणाम
चलो जो हुआ उसके साथ खेलते हैं, कई टैब खोलें, जांचें कि सब कुछ सिंक्रनाइज़ है:
यदि आप कोड की तुलना करना चाहते हैं तो एक गिटब प्रोजेक्ट,
पुनश्च
यदि आप निम्नलिखित डर्बीज लेखों को याद नहीं करना चाहते हैं, तो मेरी प्रोफ़ाइल पर अपडेट की सदस्यता लें: zag2art । मैं इसे स्वयं कर रहा हूं - हब पर, ट्रैकर में एक विशिष्ट (बहुत ही दिलचस्प) हब जोड़ने का कोई तरीका नहीं है ताकि आप कुछ भी याद न करें।
यदि आप डर्बीज को पसंद करते हैं - तो जीथब पर तारांकन करने के लिए परेशानी न लें