knockout.js
2015-12-26 10 views 5 likes 
5

नॉकआउट प्रलेखन here के अनुसार, एक घटक ViewModel केवल "मांग पर" instantiated है, माना जाता है कि यह इस तरह के रूप में घोषित किया जाता है:कॉलबैक के रूप में एक नॉकआउट जेएस घटक व्यूमोडेल फ़ंक्शन का उपयोग कैसे किया जा सकता है?

<div data-bind='component: { 
 
    name: componentNameObservable, 
 
    params: { mode: "detailed-list", items: productsList } 
 
}'></div>

एक मार्ग के साथ एक एकल पृष्ठ आवेदन के परिदृश्य पर विचार करें तंत्र जैसे सैमीजेएस, क्रॉस रोड्सजेस, या किसी अन्य।

जब एक मार्ग परिवर्तन अनुरोध मार्ग पैटर्न से मेल खाता है, तो मार्ग मिलान किए गए ईवेंट के लिए रूटिंग लाइब्रेरी हैंडलर को सामान्य नाम घटक के लिए नया मान सेट करने के लिए सामान्य है। यह बाध्य तत्व में एक नए घटक के इंजेक्शन ट्रिगर करेगा। उस के शीर्ष पर, इस मार्ग के अंदर भी हैंडलर मिलान किया गया है, मान लीजिए कि मैं घटक दृश्य के अंदर घोषित एक फ़ंक्शन निष्पादित करना चाहता हूं मॉडल मॉडल को डेटा रीफ्रेश/सेटअप करने के लिए, रूट चेंज इवेंट का जवाब देने के लिए बाध्य किया जा रहा है। यह कैसे संभव होगा? घटक दृश्य के बाद से इन मामलों में मॉडल तत्कालता को नॉकआउट के आंतरिक घटक बाध्यकारी तंत्र द्वारा नियंत्रित किया जाता है, मैं अपने कार्यों तक नहीं पहुंच सकता ताकि मैं उन्हें कॉलबैक के रूप में संदर्भित कर सकूं। यदि यह संभव था, तो मैं रूटिंग लाइब्रेरी रूट मिलान वाले हैंडलर को कॉलबैक पैरामीटर के रूप में एक घटक दृश्य मॉड्यूल फ़ंक्शन पास कर दूंगा, फिर कॉलबैक फ़ंक्शन निष्पादित करूँगा, सभी अच्छे होंगे ... लेकिन ऐसा लगता है कि ऐसा नहीं लगता है ...

मैं जैसे यहाँ

http://knockoutjs.com/documentation/component-loaders.html#note-integrating-with-browserify

वर्णित इस मामले में घटक Browserify, के साथ काम करने CommonJS उपयोग करके उसे पंजीकृत कर रहा हूँ, घटक दृश्य मॉडल पर module.exports बेनकाब करने के लिए अपनी पूरी गैर instantiated है कन्स्ट्रक्टर फ़ंक्शन, ताकि जो कुछ भी आवश्यक हो ('myViewModel') का अनुवाद हो जाता है, वें देखने के लिए दृश्य मॉडल को सही ढंग से "नया" किया जाता है ई तत्व

कोई सुझाव?

+1

* "[..] मार्ग मिलान किए गए ईवेंट के लिए रूटिंग लाइब्रेरी हैंडलर को घटक नाम के लिए एक नया मान सेट करने के लिए बनाएं।" * पारस्परिक रूप से अनन्य है: * "[..] घटक दृश्य के अंदर घोषित एक फ़ंक्शन निष्पादित करें मॉडल बाध्य, [..] मार्ग बदल गया घटना बदल गया "*। क्योंकि मार्ग बदलते समय हर बार आपका घटक टूट जाता है। तो आप केवल दो बार मार्ग परिवर्तन पर प्रतिक्रिया कर सकते हैं: कन्स्ट्रक्टर फ़ंक्शन (सेटअप) में, या घटक टियरडाउन से पहले, [कॉलबैक का निपटान करें] में (http://knockoutjs.com/documentation/component-binding.html#disposal-and- स्मृति प्रबंधन)। कम से कम, यह है, इस सेटअप के साथ। – Tyblitz

+0

आप सही हैं, @Tyblitz, मामला यह है कि मैं इस मामले के लिए अपने सेटअप पर आगे विस्तार करने में विफल रहा। असल में, स्पा सेटअप में मैं बात कर रहा हूं, घटक नाम के लिए एक नए मान के लिए सेटर एक अलग नॉकआउट घटक में होता है क्योंकि घटक के विपरीत मैं अपने दृश्य मॉडल के अंदर एक फ़ंक्शन निष्पादित करना चाहता हूं। –

+0

एक ही एचटीएमएल पर, नेविगेशन को संभालने वाला एक घटक (वह घटक जो घटक नाम बदलता है) और नॉकआउट के घटक बाध्यकारी के साथ एक अन्य कंटेनर टैग, जैसे कि प्रश्न की शुरुआत में दिखाया गया स्निपेट। नेविगेशन घटक घटक NameObservable को बदलता है, इसके आधार पर, घटक बाध्यकारी के साथ कंटेनर (इस मामले में एक div) में एक बार में कई अन्य घटकों को इंजेक्शन दिया जाता है। –

उत्तर

3

मान लें कि मैं घटक दृश्य के अंदर घोषित एक फ़ंक्शन निष्पादित करना चाहता हूं मॉडल मॉडल को डेटा रीफ्रेश/सेटअप करने के लिए, रूट बदलते ईवेंट का जवाब देने के लिए बाध्य होना चाहिए। यह कैसे संभव होगा?

में component registration documentation आप 4 विभिन्न विकल्पों को देखने के मॉडल प्रदान करने के लिए:

  • 1: एक निर्माता समारोह
  • 2: एक साझा वस्तु दृष्टान्त
  • 3: एक createViewModel कारखाने समारोह
  • चौथा: एक एएमडी मॉड्यूल जिसका मान व्यूमोडेल
का वर्णन करता है

वास्तव में, चौथा विकल्प अन्य 3 विकल्पों में से एक को वापस करने के लिए एएमडी मॉड्यूल का उपयोग कर रहा है। तो require का उपयोग किए बिना या बिना 3 संभावित विकल्प हैं।

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

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

// Here you'll store the component APIs to access them: 
var childrenComponentsApi = {}; 
// This will be passed as a callback, so that the child component 
// can register the API 
var registerChildComponentApi = function(api) { 
    childrenComponentsApi.componentX = api; 
}; 

नोट के मुख्य गुंजाइश में

: यह एक वस्तु जहां कार्यक्षमता ताकि पंजीकृत किया जा सकता है के लिए महत्वपूर्ण है आप संदर्भ

खोना नहीं है ध्यान में रखते हुए:

<div data-bind='component: { 
    name: 'componentX', 
    params: { registerApi: registerChildComponentApi, /*other params*/ } 
}'></div> 

घटकों में दृश्य मॉडल निर्माता (या कारखाना) शरीर:

params.registerApi({ // The callback is available in thereceived params 
    func1: func1, // register the desired functions 
    func2: func2}); 

बाद में, मुख्य दायरे में, अगर आप इस तरह घटक की कार्यक्षमता का उपयोग कर सकते हैं:

childrenComponentsApi.componentX.fun1 (/ * पैरामीटर * /);

यह बिल्कुल काम नहीं कर रहा कोड है, लेकिन मुझे उम्मीद है कि यह आपको एक विचार देता है कि आपको क्या चाहिए।

यह समाधान पूरी तरह से काम करता है अगर एपीआई तुरंत नहीं आती है। मैंने इस कार्यान्वयन का उपयोग किया जब कार्यक्षमता को उपयोगकर्ता की कार्रवाई के लिए बुलाया जाएगा, ताकि मुझे यकीन है कि घटक पहले ही इंस्टॉल हो चुका है।

लेकिन, आपके मामले में, घटक निर्माण असीमित है, इसलिए आपको कार्यान्वयन को संशोधित करना होगा। कम से कम दो संभावित तरीके हैं:

1) registerApi कार्यान्वयन को बदलने और प्रारंभ करने के लिए इसका उपयोग करना आसान है। कुछ इस तरह:

ViewModels निर्माता में:

params.registerApi({ 
    init: init, // initialization function 
    func1: func1, // other exposed functionality 
    func2: func2}); 

मुख्य गुंजाइश में: के बाद कॉलबैक ग्राहक घटक द्वारा चलाया जाता है

var registerChildComponentApi = function(api) { 
    childrenComponentsApi.componentX = api; 
    childrenComponentsApi.componentx.init(/* params*/) 
} 

इस implementacion init में कहा जाता है, इसलिए आप सुनिश्चित कर सकते हैं कि घटक उपलब्ध है।

2) एक और जटिल समाधान में वादे का उपयोग करना शामिल है। यदि आपके घटक को तैयार होने के लिए एसिंक्रोनस ऑपरेशंस करने की आवश्यकता है (उदाहरण के लिए AJAX कॉल कर रहे हैं), तो आप इसे सभी खुला एपीआई के अलावा एक वादा वापस कर सकते हैं, ताकि घटक वास्तव में तैयार होने पर वादा को हल कर सके, और मुख्य दायरा चलता है एपीआई कार्यक्षमता केवल जब वादा हल हो गया है।कुछ इस तरह:

दृश्य मॉडल निर्माता में:

params.registerApi({ 
    ready: ready, // promise created and solved by the component 
    func1: func1, // exposed functionality 
    func2: func2}); 

मुख्य गुंजाइश में:

var registerChildComponentApi = function(api) { 
    childrenComponentsApi.componentX = api; 
} 
childrenComponentsApi.componentx.ready().then(
    childrenComponentsApi.componentx.func1; 
); 

ये कुछ कार्यान्वयन नमूने हैं, लेकिन वहाँ उन पर कई रूपों हो सकता है। उदाहरण के लिए, यदि आपको घटक व्यूमोडेल के init फ़ंक्शन को चलाने की आवश्यकता है, तो आप घटक को provideInit जैसे पैरामीटर की आपूर्ति कर सकते हैं, और घटक के init को पेज़ करके इसे कॉन्स्टक्टर में चला सकते हैं। कुछ इस तरह:

<div data-bind='component: { 
    name: 'componentX', 
    params: { provideInit: provideInit, /*other params*/ } 
}'></div> 

var proviedInit: function(init) { 
    init(/* params */); 
}; 

और भूल नहीं है कि यह भी भी पैरामीटर के रूप में observables गुजर और उन्हें मुख्य दायरे से संशोधित करके constructor.Or के लिए सभी आवश्यक मानकों को पारित करके घटक के viewmodel प्रारंभ करने में संभव है।

आखिरी सबसे अच्छी सलाह जो मैं आपको दे सकता हूं वह यह है कि आप registerApi कार्यक्षमता को सही ढंग से मानकीकृत और दस्तावेज करते हैं, ताकि सभी घटकों को लागू किया जा सके और उसी तरह उपयोग किया जा सके।

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

+0

उत्कृष्ट, @ जोटाबी, मुझे यह बिल्कुल इरादे से काम मिल गया। मेरे एसपीए, इस मामले के लिए, घटक के केवल एक उदाहरण (मेरे एसपीए के लिए घटक = पेज) की आवश्यकता है। मैं एक साझा व्यूमोडेल मॉड्यूल सेट करता हूं, मेरे प्रत्येक पृष्ठ दृश्य मॉडल के उदाहरण निर्यात करता हूं।जब भी वे आवश्यक होते हैं, वे हमेशा गुंजाइश में होते हैं। मैंने इन साझा दृश्यों का उपयोग किया, मॉडल ऑब्जेक्ट्स को तब व्यूमोडेल प्रदान करने वाले घटकों को पंजीकृत करने के लिए दूसरा विकल्प: एक साझा ऑब्जेक्ट उदाहरण। अब मुझे इन दृश्यों के लिए उजागर की गई सभी चीज़ों तक पहुंच है मॉडल, कॉलबैक के रूप में अपने कार्यों का उपयोग कर सकते हैं, वे अवलोकन सीधे सेट कर सकते हैं, वास्तव में सहायक। –

+0

जो वास्तव में मुझे अंतर्दृष्टि देता है वह आपका कथन था: _ चौथा विकल्प अन्य 3 विकल्पों में से एक को वापस करने के लिए एएमडी मॉड्यूल का उपयोग कर रहा है। तो आवश्यकता_ के उपयोग के साथ या बिना केवल 3 संभावित विकल्प हैं। यह गेम परिवर्तक था, दस्तावेज़ीकरण ने मुझे इस निष्कर्ष तक नहीं पहुंचाया। –

+0

एक और बात, @ जोटाबी, मैं वास्तव में आमजेएस का उपयोग कर रहा हूं, एएमडी नहीं, दस्तावेज़ीकरण में एक संभावना [यहां] (http://knockoutjs.com/documentation/component-loaders.html#note-integrating-with-browserify) । ध्यान दें कि यह लिंक स्पष्ट रूप से बताता है: _ नोट करें कि निम्न * केवल * ब्राउज़र के साथ काम करता है - requ.js के साथ नहीं, क्योंकि यह सिंक्रनाइज़_ को लौटने की आवश्यकता() पर निर्भर करता है। क्या यह आपके द्वारा किए गए परिवर्तन को बदलता है: _But, आपके मामले में, घटक निर्माण असीमित है, इसलिए आपको कार्यान्वयन को संशोधित करना होगा ._? –

संबंधित मुद्दे