Vuex लड़ाई बनाम म्यूटेशन


173

Vuex में, "क्रिया" और "उत्परिवर्तन" दोनों होने का तर्क क्या है?

मैं उन घटकों के तर्क को समझता हूं जो राज्य को संशोधित करने में सक्षम नहीं हैं (जो स्मार्ट लगता है), लेकिन दोनों क्रियाएं और उत्परिवर्तन होने से ऐसा लगता है कि आप एक फ़ंक्शन को दूसरे फ़ंक्शन को ट्रिगर करने के लिए लिख रहे हैं, फिर राज्य को बदल सकते हैं।

"एक्शन" और "म्यूटेशन" के बीच क्या अंतर है, वे एक साथ कैसे काम करते हैं, और मोर्सो, मैं उत्सुक हूं कि क्यों Vuex डेवलपर्स ने इसे इस तरह से करने का फैसला किया?



संबंधित चर्चा: github.com/vuejs/vuex/issues/587
chuck911

1
आप सीधे स्टोर की स्थिति को म्यूट नहीं कर सकते। स्टोर की स्थिति को बदलने का एकमात्र तरीका स्पष्ट रूप से म्यूटेशन करना है। इसके लिए हमें म्यूटेशन करने के लिए क्रियाओं की आवश्यकता है।
सुरेश सपकोटा

1
@SureshSapkota वह कथन बहुत ही भ्रामक है, दोनों के रूप में mutationsऔर actionsबदलते राज्य के तरीकों के रूप में vuex प्रलेखन में परिभाषित किया गया है। आपको म्यूटेशन करने के लिए कार्रवाई की आवश्यकता नहीं है।
ग्राहम

1
म्यूटेशन, जैसा कि नाम से पता चलता है कि इसका उपयोग आपकी राज्य वस्तु को संशोधित / म्यूट करने के लिए किया जाता है। क्रियाएं उत्परिवर्तन के समान हैं, लेकिन राज्य को उत्परिवर्तित करने के बजाय, क्रियाएं उत्परिवर्तन करती हैं। क्रिया में कोई भी मनमाना अतुल्यकालिक कोड या व्यावसायिक तर्क हो सकता है । Vuex राज्य वस्तु की सिफारिश करता है केवल उत्परिवर्तन कार्यों के अंदर उत्परिवर्तित किया जाना चाहिए। यह म्यूटेशन फ़ंक्शन के अंदर किसी भी भारी या अवरुद्ध कोड को नहीं चलाने की भी सिफारिश की जाती है क्योंकि यह प्रकृति में समकालिक है
इमैनुएल नेनी

जवाबों:


221

प्रश्न 1 : Vuejs डेवलपर्स ने इसे इस तरह से करने का फैसला क्यों किया?

उत्तर:

  1. जब आपका आवेदन बड़ा हो जाता है, और जब इस परियोजना पर कई डेवलपर्स काम करते हैं, तो आपको "राज्य प्रबंधन" (विशेष रूप से "वैश्विक राज्य") मिलेगा, तेजी से और अधिक जटिल हो जाएगा।
  2. Vuex तरीका (बस प्रतिक्रिया में Redux की तरह ) राज्य का प्रबंधन करने के लिए एक नया तंत्र प्रदान करता है, राज्य रखें, और "सहेजें और ट्रैक करने योग्य" (इसका मतलब है कि हर क्रिया जो राज्य को संशोधित करती है, डिबग टूल द्वारा ट्रैक किया जा सकता है : vue-devusools )

प्रश्न 2 : "एक्शन" और "म्यूटेशन" में क्या अंतर है?

आइए पहले आधिकारिक स्पष्टीकरण देखें:

उत्परिवर्तन:

Vuex म्यूटेशन अनिवार्य रूप से घटनाएं हैं: प्रत्येक म्यूटेशन में एक नाम और एक हैंडलर है।

import Vuex from 'vuex'

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    INCREMENT (state) {
      // mutate state
      state.count++
    }
  }
})

क्रियाएँ: क्रियाएँ केवल फ़ंक्शंस हैं जो म्यूटेशन भेजती हैं।

// the simplest action
function increment (store) {
  store.dispatch('INCREMENT')
}

// a action with additional arguments
// with ES2015 argument destructuring
function incrementBy ({ dispatch }, amount) {
  dispatch('INCREMENT', amount)
}

यहाँ ऊपर की मेरी व्याख्या है:

  • उत्परिवर्तन राज्य को संशोधित करने का एकमात्र तरीका है
  • उत्परिवर्तन व्यावसायिक तर्क के बारे में परवाह नहीं करता है, यह सिर्फ "राज्य" की परवाह करता है
  • कार्रवाई व्यापार तर्क है
  • कार्रवाई एक समय में 1 से अधिक म्यूटेशन भेज सकती है , यह सिर्फ व्यापार तर्क को लागू करती है, यह डेटा बदलने के बारे में परवाह नहीं करती है (जो म्यूटेशन द्वारा प्रबंधित होती है)

80
तथ्य यह है कि एक कार्रवाई "व्यापार तर्क है" और एक बार में कई म्यूटेशनों को प्रेषित कर सकता है। यही वह उत्तर है जिसकी मुझे तलाश थी। धन्यवाद।
कोबी

11
आप cuys कह रहे हैं आप "एक उत्परिवर्तन प्रेषण"। क्या यह सही शब्द नहीं है कि आप एक उत्परिवर्तन की पुष्टि करते हैं?
प्रॉब्लम्सऑफसमिट

4
आप कार्रवाई भेजते हैं और म्यूटेशन करते हैं।
ईरिक

4
प्रेषण अब म्यूटेशन के लिए vue 2.0 में काम नहीं कर रहा है, आपको कार्रवाई में एक म्यूटेशन करने की आवश्यकता है।
SKLTFZ

18
@Kaicui यह उत्तर म्यूटेशन के बारे में एक नोट याद कर रहा है कि वह हमेशा सिंक्रोनस हो सकता है, और क्रियाएं संभवतः एसिंक्रोनस हो रही हैं। उसके अलावा, एक अच्छा जवाब!
decates

58

म्यूटेशन सिंक्रोनस होते हैं, जबकि क्रियाएं एसिंक्रोनस हो सकती हैं।

इसे दूसरे तरीके से रखने के लिए: यदि आपके ऑपरेशन समकालिक हैं, तो आपको कार्यों की आवश्यकता नहीं है, अन्यथा उन्हें लागू करें।


2
यह वास्तव में एक प्रश्न का उत्तर देता है जिसे मैं बनाने वाला था, कि कैसे todomvc उदाहरण क्रियाओं का उपयोग नहीं करता है।
sksallaj

7
'तुम कार्रवाई की आवश्यकता नहीं है, तो अपने संचालन तुल्यकालिक हैं' : यह सच नहीं है: क्या आप कर जरूरत कार्यों यदि आप एक ही मॉड्यूल से कई उत्परिवर्तन रचना करना चाहते हैं, क्योंकि आप एक एक्शन से दूसरे कॉल कार्रवाई नहीं कर सकते।
रेमुंडस

1
इस उत्तर का स्पष्ट अनुवर्ती होगा "फिर क्यों न सिर्फ कार्रवाई की जाए और म्यूटेशन से छुटकारा पाएं"
माइकल Mrozek

34

मेरा मानना ​​है कि 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 एट अल), या कुछ पिछड़ी संगतता, या सभी बताई गई संभावनाओं के कुछ संयोजन को बनाए रखने के लिए हो सकता है।

मुझे विश्वास नहीं होता है कि अपने म्यूटेशन के लिए गेट्स पास करना स्वयं एक संकेत है कि आप कुछ गलत कर रहे हैं। मैं इसे केवल फ्रेमवर्क की कमियों में से एक "पैचिंग" के रूप में देखता हूं।


1
मेरे लिए यह सबसे अच्छा जवाब है। इसे पढ़ने के बाद ही, मेरे पास यह "क्लिक" था जब आपको लगता है कि आप कुछ समझ गए हैं।
रॉबर्ट कुज़्नियर

गेटर्स मूल रूप से computedआउटपुट हैं। वे पढ़े-लिखे ही हैं। म्यूटेशन देखने का एक अच्छा तरीका यह हो सकता है कि if elseआप इसे हटा दें । Vuex डॉक्स का कहना है कि आप commitएक एक्शन के अंदर 1 से अधिक घर बना सकते हैं । इसलिए यह मानना ​​तर्कसंगत होगा कि आप तर्क के आधार पर कुछ उत्परिवर्तन कर सकते हैं। मैं कार्यों को आग में उत्परिवर्तित करने के तरीके के रूप में देखता हूं।
ताम्ब

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

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

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

15

मुझे लगता है कि TLDR का उत्तर यह है कि Mutations तुल्यकालिक / लेन-देन करने योग्य हैं। इसलिए यदि आपको अजाक्स कॉल चलाने की आवश्यकता है, या कोई अन्य एसिंक्रोनस कोड करने की आवश्यकता है, तो आपको एक एक्शन में ऐसा करने की आवश्यकता है, और उसके बाद नए राज्य को सेट करने के लिए एक म्यूटेशन करें।


1
यह प्रलेखन का संक्षेप जैसा दिखता है; जिसमें कुछ भी गलत नहीं है। हालाँकि, इस जवाब के साथ समस्या यह है कि यह जो कहता है जरूरी नहीं है। आप एक अतुल्यकालिक फ़ंक्शन / AJAX को लागू करते समय एक उत्परिवर्तन के अंदर स्थिति को संशोधित कर सकते हैं, जिसे तब पूर्ण कॉलबैक में बदला जा सकता है। मुझे लगता है कि यह वही भ्रम है जिसके कारण Vuex के साथ काम करते समय सर्वोत्तम विकास प्रथाओं के लिए कार्यों का उपयोग क्यों किया जाना चाहिए । मुझे पता है कि निश्चित रूप से मेरे लिए भ्रम की स्थिति थी जब मैंने Vuex के साथ काम करना शुरू किया।
Erutan409

8

क्रिया और उत्परिवर्तन के बीच मुख्य अंतर:

  1. अंदर की कार्रवाइयां आप एसिंक्रोनस कोड चला सकते हैं लेकिन म्यूटेशन में नहीं। अत: अतुल्यकालिक कोड के लिए क्रियाओं का उपयोग करें अन्यथा म्यूटेशन का उपयोग करें।
  2. अंदर की क्रियाओं में आप गेटर्स, स्टेट, म्यूटेशन (उन्हें कमिट करना), एक्शन (उन्हें डिस्पैच करना) कर सकते हैं। इसलिए यदि आप केवल राज्य उपयोग म्यूटेशन का उपयोग करना चाहते हैं अन्यथा कार्रवाई का उपयोग करें।

5

के अनुसार docs

क्रियाएं उत्परिवर्तन के समान हैं , जो अंतर हैं:

  • इसके बजाय परिवर्तनशील राज्य, कार्रवाई के लिए प्रतिबद्ध म्यूटेशन।
  • क्रियाओं में मनमाने ढंग से अतुल्यकालिक संचालन हो सकते हैं ।

निम्नलिखित स्निपेट पर विचार करें।

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++               //Mutating the state. Must be synchronous
    }
  },
  actions: {
    increment (context) {
      context.commit('increment') //Committing the mutations. Can be asynchronous.
    }
  }
})

एक्शन हैंडलर ( वेतन वृद्धि ) एक संदर्भ ऑब्जेक्ट प्राप्त करता है जो स्टोर इंस्टेंस पर विधियों / गुणों के एक ही सेट को उजागर करता है, इसलिए आप एक म्यूटेशन करने के लिए Reference.com को कॉल कर सकते हैं, या स्टेट को प्राप्त कर सकते हैं और संदर्भ के माध्यम से प्राप्त कर सकते हैं।


1
'म्यूटेशन' फंक्शन से पॉसिबल कॉल क्या है, एक विधि vuejs घटक से?
अल्बर्टो Acuña

@ AlbertoAcuña मेरे पास एक ही सवाल है, क्योंकि जब मैं ऐसा करने की कोशिश करता हूं, तो यह एक त्रुटि है कि स्थानीय उत्परिवर्तन अपरिभाषित है।
रुटविक गंगूरडे

5

डिस्क्लेमर - मैंने केवल vuejs का उपयोग करना शुरू कर दिया है, इसलिए यह सिर्फ डिजाइन के इरादे के लिए मुझे अलग कर रहा है।

टाइम मशीन डिबगिंग राज्य के स्नैपशॉट का उपयोग करता है, और क्रियाओं और उत्परिवर्तन की एक समयरेखा दिखाता है। सिद्धांत रूप में, हम actionsराज्य के बसने वालों और पाने वालों की एक रिकॉर्डिंग के साथ-साथ परस्पर रूपांतर का वर्णन कर सकते थे। परन्तु फिर:

  • हमारे पास अशुद्ध इनपुट (async परिणाम) होंगे जो कि बसने वालों और गेटर्स के कारण होते हैं। यह तार्किक रूप से और विभिन्न async बसे का पालन करना कठिन होगा और गेटर्स आश्चर्यजनक रूप से बातचीत कर सकते हैं। यह अभी भी mutationsलेनदेन के साथ हो सकता है लेकिन फिर हम कह सकते हैं कि लेनदेन को सुधारने की आवश्यकता है क्योंकि यह कार्रवाई में एक दौड़ की स्थिति होने के विपरीत है। एक कार्रवाई के अंदर बेनामी म्यूटेशन अधिक आसानी से इन प्रकार के बगों को फिर से जीवंत कर सकता है क्योंकि async प्रोग्रामिंग नाजुक और कठिन है।
  • लेन-देन लॉग को पढ़ना मुश्किल होगा क्योंकि राज्य परिवर्तनों के लिए कोई नाम नहीं होगा। यह बहुत अधिक कोड की तरह और कम अंग्रेजी होगा, जो म्यूटेशन के तार्किक समूहों को याद कर रहा है।
  • यह डेटा ऑब्जेक्ट पर किसी भी उत्परिवर्तन को दर्ज करने के लिए मुश्किल और कम प्रदर्शन करने वाला हो सकता है, जैसा कि अब विरोध किया गया है, जहां म्यूटेशन फ़ंक्शन कॉल से पहले और बाद में सिंक्रोनाइज़्ड डिफाइन पॉइंट्स हैं -। मुझे यकीन नहीं है कि यह कितनी बड़ी समस्या है।

नामित म्यूटेशनों के साथ निम्न लेन-देन लॉग की तुलना करें।

Action: FetchNewsStories
Mutation: SetFetchingNewsStories
Action: FetchNewsStories [continuation]
Mutation: DoneFetchingNewsStories([...])

लेन-देन लॉग के साथ जिसका कोई नाम परिवर्तन नहीं है:

Action: FetchNewsStories
Mutation: state.isFetching = true;
Action: FetchNewsStories [continuation]
Mutation: state.isFetching = false;
Mutation: state.listOfStories = [...]

मुझे आशा है कि आप async में संभावित जोड़ा जटिलता और कार्यों के अंदर अनाम उत्परिवर्तन से अतिरिक्त उदाहरण दे सकते हैं।

https://vuex.vuejs.org/en/mutations.html

अब कल्पना करें कि हम एप्लिकेशन को डिबग कर रहे हैं और devtool के म्यूटेशन लॉग को देख रहे हैं। लॉग किए गए प्रत्येक म्यूटेशन के लिए, devtool को "पहले" और "राज्य के स्नैपशॉट" के बाद कैप्चर करना होगा। हालांकि, ऊपर दिए गए उदाहरण म्यूटेशन के अंदर असिंक्रोनस कॉलबैक असंभव बनाता है: कॉलबैक अभी तक नहीं किया गया है जब म्यूटेशन किया जाता है, और देवता के लिए यह जानने का कोई तरीका नहीं है कि कॉलबैक वास्तव में कब कहा जाएगा - कॉलबैक में किया गया कोई भी स्टेट म्यूटेशन अनिवार्य रूप से अन-ट्रैक करने योग्य है!


4

उत्परिवर्तन:

Can update the state. (Having the Authorization to change the state).

क्रियाएँ:

Actions are used to tell "which mutation should be triggered"

Redux वे में

Mutations are Reducers
Actions are Actions

क्यों दोनों ??

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


2

इसने मुझे बहुत भ्रमित किया इसलिए मैंने एक सरल डेमो बनाया।

component.vue

<template>
    <div id="app">
        <h6>Logging with Action vs Mutation</h6>
        <p>{{count}}</p>
        <p>
            <button @click="mutateCountWithAsyncDelay()">Mutate Count directly with delay</button>
        </p>
        <p>
            <button @click="updateCountViaAsyncAction()">Update Count via action, but with delay</button>
        </p>
        <p>Note that when the mutation handles the asynchronous action, the "log" in console is broken.</p>
        <p>When mutations are separated to only update data while the action handles the asynchronous business
            logic, the log works the log works</p>
    </div>
</template>

<script>

        export default {
                name: 'app',

                methods: {

                        //WRONG
                        mutateCountWithAsyncDelay(){
                                this.$store.commit('mutateCountWithAsyncDelay');
                        },

                        //RIGHT
                        updateCountViaAsyncAction(){
                                this.$store.dispatch('updateCountAsync')
                        }
                },

                computed: {
                        count: function(){
                                return this.$store.state.count;
                        },
                }

        }
</script>

store.js

import 'es6-promise/auto'
import Vuex from 'vuex'
import Vue from 'vue';

Vue.use(Vuex);

const myStore = new Vuex.Store({
    state: {
        count: 0,
    },
    mutations: {

        //The WRONG way
        mutateCountWithAsyncDelay (state) {
            var log1;
            var log2;

            //Capture Before Value
            log1 = state.count;

            //Simulate delay from a fetch or something
            setTimeout(() => {
                state.count++
            }, 1000);

            //Capture After Value
            log2 = state.count;

            //Async in mutation screws up the log
            console.log(`Starting Count: ${log1}`); //NRHG
            console.log(`Ending Count: ${log2}`); //NRHG
        },

        //The RIGHT way
        mutateCount (state) {
            var log1;
            var log2;

            //Capture Before Value
            log1 = state.count;

            //Mutation does nothing but update data
            state.count++;

            //Capture After Value
            log2 = state.count;

            //Changes logged correctly
            console.log(`Starting Count: ${log1}`); //NRHG
            console.log(`Ending Count: ${log2}`); //NRHG
        }
    },

    actions: {

        //This action performs its async work then commits the RIGHT mutation
        updateCountAsync(context){
            setTimeout(() => {
                context.commit('mutateCount');
            }, 1000);
        }
    },
});

export default myStore;

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


0

1. से डॉक्स :

क्रियाएं उत्परिवर्तन के समान हैं, जो अंतर हैं:

  • राज्य को बदलने के बजाय, कार्य उत्परिवर्तन करते हैं।
  • क्रियाओं में मनमाने ढंग से अतुल्यकालिक संचालन हो सकते हैं।

क्रियाओं में अतुल्यकालिक ऑपरेशन हो सकते हैं, लेकिन उत्परिवर्तन नहीं हो सकता है।

2. हम म्यूटेशन लागू करते हैं, हम राज्य को सीधे बदल सकते हैं। और हम इस तरह से राज्यों को बदलने की कार्रवाई में भी कर सकते हैं:

actions: {
  increment (store) {
    // do whatever ... then change the state
    store.dispatch('MUTATION_NAME')
  }
}

क्रियाओं को अन्य चीजों को संभालने के लिए डिज़ाइन किया गया है, हम वहां कई चीजें कर सकते हैं (हम अतुल्यकालिक संचालन का उपयोग कर सकते हैं) फिर वहां प्रेषण उत्परिवर्तन द्वारा स्थिति बदल सकते हैं।


0

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

एक और बात - क्रिया। जैसा कि कहा गया है - क्रियाएँ उत्परिवर्तन करती हैं। इसलिए वे स्टोर को नहीं बदलते हैं, और इसके लिए सिंक्रोनस होने की कोई आवश्यकता नहीं है। लेकिन, वे अतुल्यकालिक तर्क के एक अतिरिक्त टुकड़े का प्रबंधन कर सकते हैं!


0

उदाहरण के लिए, actionsकॉल करने के लिए एक अतिरिक्त परत होना अनावश्यक लग सकता है mutations:

const actions = {
  logout: ({ commit }) => {
    commit("setToken", null);
  }
};

const mutations = {
  setToken: (state, token) => {
    state.token = token;
  }
};

तो अगर कॉलिंग actionsकॉल करते हैं logout, तो म्यूटेशन क्यों नहीं कहते हैं?

एक कार्रवाई का संपूर्ण विचार एक कार्रवाई के अंदर से कई म्यूटेशन को कॉल करना या अजाक्स अनुरोध या किसी भी प्रकार के अतुल्यकालिक तर्क को आप कल्पना कर सकते हैं।

हमारे पास अंततः ऐसी क्रियाएं हो सकती हैं जो कई नेटवर्क अनुरोध करती हैं और अंततः कई अलग-अलग उत्परिवर्तन को बुलाती हैं।

इसलिए हम अपने में Vuex.Store()जितना संभव हो उतना जटिलता से सामान बनाने की कोशिश करते हैं actionsऔर यह हमारे mutations, stateऔर gettersक्लीनर और सीधा छोड़ देता है और उस तरह की मॉड्यूलरिटी के अनुरूप हो जाता है जो पुस्तकालयों को Vue और React की तरह लोकप्रिय बनाता है।


0

मैं लगभग 3 वर्षों से व्यावसायिक रूप से Vuex का उपयोग कर रहा हूं, और यहां मुझे लगता है कि मुझे क्रियाओं और उत्परिवर्तन के बीच आवश्यक अंतरों के बारे में पता चला है कि आप उन्हें अच्छी तरह से एक साथ उपयोग करने से कैसे लाभ उठा सकते हैं, और यदि आप अपना जीवन कठिन बना सकते हैं इसे अच्छी तरह से उपयोग न करें।

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

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

मूल विचार यह है:

  • स्टोर में एक आंतरिक स्थिति होती है, जिसे घटकों द्वारा सीधे एक्सेस नहीं किया जाना चाहिए (मैपस्टेट प्रभावी रूप से प्रतिबंधित है)
  • स्टोर में म्यूटेशन हैं, जो आंतरिक राज्य के लिए तुल्यकालिक संशोधन हैं। एक उत्परिवर्तन का एकमात्र काम राज्य को संशोधित करना है। उन्हें केवल एक कार्रवाई से बुलाया जाना चाहिए। उन्हें उन चीजों का वर्णन करने के लिए नामित किया जाना चाहिए जो राज्य के लिए हुईं (ORDER_CANCELED, ORDER_CREATED)। उन्हें छोटा और मीठा रखें। आप Vue Devtools ब्राउज़र एक्सटेंशन का उपयोग करके उनके माध्यम से कदम बढ़ा सकते हैं (यह डीबगिंग के लिए भी बहुत अच्छा है!)
  • स्टोर में भी क्रियाएं हैं, जो कि async होनी चाहिए या एक वादा वापस करना चाहिए। वे ऐसी क्रियाएं हैं जो आपके घटक तब कॉल करेंगे जब वे आवेदन की स्थिति को संशोधित करना चाहेंगे। उन्हें व्यावसायिक उन्मुख कार्यों के साथ नामित किया जाना चाहिए (क्रियाओं, अर्थात रद्दकर्ता, क्रिएट ऑडर) के । यह वह जगह है जहाँ आप अपने अनुरोधों को मान्य करते हैं और भेजते हैं। यदि राज्य को बदलना आवश्यक हो तो प्रत्येक क्रिया अलग-अलग चरण में अलग-अलग कॉल कर सकती है।
  • अंत में, स्टोर में गेटर्स हैं, जो आप अपने घटकों को अपने राज्य को उजागर करने के लिए उपयोग करते हैं। उम्मीद है कि आपके आवेदन के विस्तार के रूप में उन्हें कई घटकों में भारी उपयोग किया जाएगा। Vuex कैश बेकार संगणना चक्र से बचने के लिए भारी मात्रा में मिलता है (जब तक आप अपने गेटटर में पैरामीटर नहीं जोड़ते हैं - मापदंडों का उपयोग न करने की कोशिश करें) ताकि उन्हें बड़े पैमाने पर उपयोग करने में संकोच न करें। बस यह सुनिश्चित कर लें कि आप ऐसे नाम दें जो जितना संभव हो उतना करीब का वर्णन करते हैं जो वर्तमान में आवेदन में है।

यह कहा जा रहा है, जादू तब शुरू होता है जब हम अपने आवेदन को इस तरह से डिजाइन करना शुरू करते हैं। उदाहरण के लिए:

  • हमारे पास एक घटक है जो उन आदेशों को हटाने की संभावना के साथ उपयोगकर्ता को आदेशों की एक सूची प्रदान करता है
  • घटकों ने एक स्टोर गेट्टर (डिलीटेबलऑर्डर्स) को मैप किया है, जो आईडी के साथ ऑब्जेक्ट्स की एक सरणी है
  • घटक में आदेशों की प्रत्येक पंक्ति पर एक बटन होता है, और इसकी क्लिक को एक स्टोर एक्शन (डिलीटऑर्डर) में मैप किया जाता है, जो इसे ऑर्डर ऑब्जेक्ट पास करता है (जो हमें याद होगा, स्टोर की सूची से ही आता है)
  • दुकान हटाने वाली कार्रवाई निम्नलिखित करती है:
    • यह विलोपन को मान्य करता है
    • यह अस्थायी रूप से हटाने का आदेश संग्रहीत करता है
    • यह आदेश के साथ ORDER_DELETED उत्परिवर्तन करता है
    • यह वास्तव में आदेश को हटाने के लिए एपीआई कॉल भेजता है (हाँ, राज्य को संशोधित करने के बाद!)
    • यह कॉल समाप्त होने की प्रतीक्षा करता है (स्थिति पहले से ही अद्यतन है) और विफलता पर, हम ORDER_DELETE_FAILED म्यूटेशन को उस क्रम से कहते हैं जिसे हमने पहले रखा था।
  • ORDER_DET
  • ORDER_DELETE_FAILED म्यूटेशन केवल इसे वापस रखता है, और त्रुटि की सूचना देने के लिए राज्य को संशोधित करता है (एक अन्य घटक, त्रुटि-अधिसूचना, उस स्थिति को ट्रैक कर रहा होगा जब स्वयं को प्रदर्शित करने के लिए पता हो)

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

तुम हमेशा एक दुकान की जरूरत नहीं है, तुम मन। यदि आप पाते हैं कि आप ऐसे स्टोर लिख रहे हैं जो इस तरह दिखते हैं:

export default {
  state: {
    orders: []
  },
  mutations: {
    ADD_ORDER (state, order) {
       state.orders.push(order)
    },
    DELETE_ORDER (state, orderToDelete) {
       state.orders = state.orders.filter(order => order.id !== orderToDelete.id)
    }
  },
  actions: {
    addOrder ({commit}, order) {
      commit('ADD_ORDER', order)
    },
    deleteOrder ({commit}, order) {
      commit('DELETE_ORDER', order)
    }
  },
  getters: {
    orders: state => state.orders
  }
}

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.