मेरा मानना है कि Mutations और Actions के पीछे की प्रेरणाओं की समझ होने से व्यक्ति बेहतर जज को बता सकता है कि कब और कैसे इस्तेमाल करना है। यह प्रोग्रामर को उन स्थितियों में अनिश्चितता के बोझ से मुक्त करता है जहां "नियम" फजी हो जाते हैं। उनके संबंधित उद्देश्यों के बारे में थोड़ा सा तर्क देने के बाद, मैं इस नतीजे पर पहुंचा कि हालाँकि एक्टेशन और म्यूटेशन का उपयोग करने के गलत तरीके हो सकते हैं, मुझे नहीं लगता कि कोई विहित दृष्टिकोण है।
आइए सबसे पहले यह समझने की कोशिश करें कि हम म्यूटेशन या क्रियाओं से क्यों गुजरते हैं।
पहली जगह में बॉयलरप्लेट के माध्यम से क्यों जाएं? सीधे तौर पर घटकों में राज्य क्यों नहीं बदलते?
सख्ती से बोलना आप state
अपने घटकों से सीधे बदल सकते हैं । यह state
केवल एक जावास्क्रिप्ट ऑब्जेक्ट है और इसमें कुछ भी जादुई नहीं है जो आपके द्वारा किए गए परिवर्तनों को वापस कर देगा।
// Yes, you can!
this.$store.state['products'].push(product)
हालाँकि, ऐसा करने से आप अपने राज्य के परिवर्तन को सभी जगह बिखेर रहे हैं। आप राज्य में केवल एक मॉड्यूल आवास खोलने की क्षमता खो देते हैं और एक नज़र में देखते हैं कि किस तरह के संचालन को इसके लिए लागू किया जा सकता है। केंद्रीकृत उत्परिवर्तन होने के बाद, यह कुछ बॉयलरप्लेट की कीमत पर होता है।
// so we go from this
this.$store.state['products'].push(product)
// to this
this.$store.commit('addProduct', {product})
...
// and in store
addProduct(state, {product}){
state.products.push(product)
}
...
मुझे लगता है कि यदि आप बॉयलरप्लेट के साथ कुछ कम जगह लेते हैं तो आप चाहते हैं कि बॉयलरप्लेट भी छोटा हो। इसलिए मैं मानता हूं कि उत्परिवर्तन राज्य के मूल संचालन के आसपास बहुत पतले रैपर हैं, लगभग कोई व्यावसायिक तर्क नहीं है। दूसरे शब्दों में, उत्परिवर्तन का उपयोग ज्यादातर बसने वालों की तरह किया जाता है।
अब जब आपने अपने उत्परिवर्तन को केंद्रीकृत कर लिया है तो आपके पास अपने राज्य परिवर्तनों का एक बेहतर अवलोकन है और चूंकि आपके टूलींग (vue-devtools) भी उस स्थान के बारे में जानते हैं जिससे यह डीबग करना आसान हो जाता है। यह भी ध्यान में रखने योग्य है कि कई Vuex के प्लग इन परिवर्तनों को ट्रैक करने के लिए राज्य को सीधे नहीं देखते हैं, वे इसके लिए म्यूटेशन पर भरोसा करते हैं। राज्य के लिए "आउट ऑफ बाउंड" परिवर्तन इस प्रकार उनके लिए अदृश्य हैं।
तो mutations
, actions
वैसे भी क्या अंतर है?
म्यूटेशन की तरह कार्य भी स्टोर के मॉड्यूल में रहते हैं और state
ऑब्जेक्ट प्राप्त कर सकते हैं । तात्पर्य यह है कि वे इसे प्रत्यक्ष रूप से परिवर्तित भी कर सकते थे । तो दोनों होने की क्या बात है? यदि हम यह तर्क देते हैं कि म्यूटेशन को छोटा और सरल रखा जाना है, तो इसका मतलब है कि हमें अधिक विस्तृत व्यापार तर्क को घर में रखने के लिए एक वैकल्पिक साधन की आवश्यकता है। क्रियाएँ ऐसा करने का साधन हैं। और जब से हमने पहले स्थापित किया है, vue-devtools और plugins म्यूटेशन के माध्यम से परिवर्तन के बारे में जानते हैं, लगातार रहने के लिए हमें अपने कार्यों से म्यूटेशन का उपयोग करते रहना चाहिए। इसके अलावा, चूंकि क्रियाओं को सभी शामिल किया जाता है और यह तर्क कि वे जो संक्षिप्त करते हैं वे अतुल्यकालिक हो सकते हैं, यह समझ में आता है कि क्रियाएँ भी शुरू से ही अतुल्यकालिक बन जाएंगी।
अक्सर इस बात पर जोर दिया जाता है कि क्रियाएं अतुल्यकालिक हो सकती हैं, जबकि उत्परिवर्तन आमतौर पर नहीं होते हैं। आप अंतर को एक संकेत के रूप में देखने का निर्णय ले सकते हैं कि म्यूटेशन का उपयोग कुछ भी सिंक्रोनस (और कुछ एसिंक्रोनस के लिए क्रियाएं) के लिए किया जाना चाहिए; हालाँकि, अगर आप एक से अधिक म्यूटेशन (सिंक्रोनाइज़) करना चाहते हैं, या यदि आपको अपने म्यूटेशन से गेट्टर के साथ काम करने की ज़रूरत है, तो म्यूटेशन फ़ंक्शंस के रूप में न तो गेटर्स मिलते हैं और न ही म्यूटेशन तर्क के रूप में करने पर आपको कुछ मुश्किलों में भागना पड़ेगा।
... जो एक दिलचस्प सवाल की ओर जाता है।
उत्परिवर्तन क्यों नहीं प्राप्त करते हैं?
मुझे इस प्रश्न का संतोषजनक उत्तर नहीं मिला, फिर भी। मैंने कोर टीम द्वारा कुछ स्पष्टीकरण देखा है जो मुझे सबसे अच्छा लगा। यदि मैं उनके उपयोग को संक्षेप में बताता हूं, तो गेट्स राज्य के लिए गणना (और अक्सर कैश्ड) एक्सटेंशन के लिए होते हैं। दूसरे शब्दों में, वे मूल रूप से अभी भी राज्य हैं, भले ही उन्हें कुछ अग्रिम गणना की आवश्यकता हो और वे सामान्य रूप से केवल-पढ़ने के लिए हों। यह कम से कम कैसे वे उपयोग करने के लिए प्रोत्साहित किया जाता है।
इस प्रकार, म्यूटेशन को सीधे गेटर्स तक पहुंचने से रोकने का मतलब है कि तीन चीजों में से एक अब आवश्यक है, अगर हमें बाद की पेशकश की गई पूर्व की कुछ कार्यक्षमता से एक्सेस करने की आवश्यकता है: (1) या तो गेट द्वारा प्रदान की जाने वाली राज्य गणनाओं को कहीं-कहीं दोहराया जाता है जो कि सुलभ है म्यूटेशन (खराब गंध), या (2) गणना मूल्य (या प्रासंगिक गेट्टर स्वयं) को म्यूटेशन (फंकी) के एक स्पष्ट तर्क के रूप में पारित किया जाता है, या (3) गेट्टर के तर्क को सीधे म्यूटेशन के भीतर दोहराया जाता है , गेटर (बदबू) द्वारा प्रदान किए गए कैशिंग के अतिरिक्त लाभ के बिना।
निम्नलिखित (2) का एक उदाहरण है, जो मेरे द्वारा सामना किए गए अधिकांश परिदृश्यों में "कम से कम बुरा" विकल्प लगता है।
state:{
shoppingCart: {
products: []
}
},
getters:{
hasProduct(state){
return function(product) { ... }
}
}
actions: {
addProduct({state, getters, commit, dispatch}, {product}){
// all kinds of business logic goes here
// then pull out some computed state
const hasProduct = getters.hasProduct(product)
// and pass it to the mutation
commit('addProduct', {product, hasProduct})
}
}
mutations: {
addProduct(state, {product, hasProduct}){
if (hasProduct){
// mutate the state one way
} else {
// mutate the state another way
}
}
}
मेरे लिए, उपरोक्त न केवल थोड़ा जटिल लगता है, बल्कि कुछ हद तक "टपका हुआ" भी है, क्योंकि एक्शन में मौजूद कोड में से कुछ म्यूटेशन के आंतरिक तर्क से स्पष्ट रूप से प्रभावित हैं।
मेरी राय में, यह एक समझौता का संकेत है। मेरा मानना है कि म्यूटेशन को स्वचालित रूप से गेटर्स प्राप्त करने की अनुमति देना कुछ चुनौतियों को प्रस्तुत करता है। यह या तो खुद Vuex के डिजाइन के लिए हो सकता है, या टूलींग (vue-devtools एट अल), या कुछ पिछड़ी संगतता, या सभी बताई गई संभावनाओं के कुछ संयोजन को बनाए रखने के लिए हो सकता है।
मुझे विश्वास नहीं होता है कि अपने म्यूटेशन के लिए गेट्स पास करना स्वयं एक संकेत है कि आप कुछ गलत कर रहे हैं। मैं इसे केवल फ्रेमवर्क की कमियों में से एक "पैचिंग" के रूप में देखता हूं।