Vue.js 2 में प्रारंभिक डेटा के रूप में सहारा पास करने का सही तरीका क्या है?


97

इसलिए मैं एक वीयू कंपोनेंट के लिए प्रॉपर पास करना चाहता हूं, लेकिन मैं उम्मीद करता हूं कि भविष्य में इन कंपोनेंट्स को उस कंपोनेंट के अंदर से बदल दूंगा। उदाहरण के तौर पर जब मैं AJAX का उपयोग करके उस व्यू कंपोनेंट को अपडेट करता हूं। इसलिए वे केवल घटक के प्रारंभ के लिए हैं।

मेरा cars-listVue घटक तत्व जहां मैं प्रारंभिक गुण के साथ सहारा पास करता हूं single-car:

// cars-list.vue

<script>
    export default {
        data: function() {
            return {
                cars: [
                    {
                        color: 'red',
                        maxSpeed: 200,
                    },
                    {
                        color: 'blue',
                        maxSpeed: 195,
                    },
                ]
            }
        },
    }
</script>

<template>
    <div>
        <template v-for="car in cars">
            <single-car :initial-properties="car"></single-car>
        </template>
    </div>
</template>

जिस तरह से मैं इसे अभी कर single-carरहा हूं कि मेरे घटक के अंदर मैं इनिशियलाइज़ेशन हुक पर असाइन this.initialPropertiesकर रहा हूं । और यह काम करता है और प्रतिक्रियाशील है।this.data.propertiescreated()

// single-car.vue

<script>
    export default {
        data: function() {
            return {
                properties: {},
            }
        },
        created: function(){
            this.data.properties = this.initialProperties;
        },
    }
</script>

<template>
    <div>Car is in {{properties.color}} and has a max speed of {{properties.maxSpeed}}</div>
</template>

लेकिन इसके साथ मेरी समस्या यह है कि मुझे नहीं पता कि क्या यह करने का एक सही तरीका है? क्या इससे मुझे सड़क पर कुछ परेशानी नहीं होगी? या इसे करने का एक बेहतर तरीका है?


13
यह मेरी राय में Vue के बारे में सबसे भ्रामक बात है: हर dataजाता है two-wayबाध्य है, लेकिन आप पारित नहीं हो सकता dataघटकों के लिए, आप पारित props, लेकिन आप प्राप्त नहीं बदल सकते हैं propsऔर न ही परिवर्तित propsकरने के लिए data। फिर क्या? एक चीज जो मैंने सीखी है वह यह है कि आपको propsघटनाओं को कम करना चाहिए और घटनाओं को ट्रिगर करना चाहिए । यही है, अगर घटक propsइसे प्राप्त बदलना चाहता है, तो उसे एक घटना को कॉल करना चाहिए और "पुन: प्रस्तुत करना" चाहिए। लेकिन फिर आप one-wayरिएक्ट की तरह एक बंधन के साथ छोड़ दिए जाते हैं और मैं dataतब के लिए उपयोग नहीं देखता । बहुत भ्रामक।
एंड्रे पेना

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

आज मैं यहाँ पर एक धागा शुरू करने के लिए कोशिश की है: forum.vuejs.org/t/...
bgraves

जवाबों:


102

इसके लिए धन्यवाद https://github.com/vuejs/vuejs.org/pull/567 मुझे अब जवाब पता है।

विधि 1

डेटा को सीधे प्रारंभिक पास दें। अद्यतन डॉक्स में उदाहरण की तरह:

props: ['initialCounter'],
data: function () {
    return {
        counter: this.initialCounter
    }
}

लेकिन ध्यान रखें कि यदि पास किया गया प्रोप एक ऑब्जेक्ट या एरे है, जो पेरेंट कंपोनेंट स्टेट में उपयोग किया जाता है, तो उस प्रो में कोई भी संशोधन उस पेरेंट कंपोनेंट स्टेट में बदलाव का परिणाम होगा।

चेतावनी : यह विधि अनुशंसित नहीं है। यह आपके घटकों को अप्रत्याशित बना देगा। यदि आपको बाल घटकों से मूल डेटा सेट करने की आवश्यकता है या तो राज्य प्रबंधन का उपयोग करें जैसे Vuex या "वी-मॉडल" का उपयोग करें। https://vuejs.org/v2/guide/components.html#Using-v-model-on-Components

विधि 2

यदि आपका प्रारंभिक प्रॉप एक वस्तु या सरणी है और यदि आप नहीं चाहते हैं कि बच्चों की स्थिति में परिवर्तन माता-पिता की स्थिति में हो, तो बस उदाहरणों का उपयोग करें Vue.util.extend[1] इसके बजाय प्रॉपर की प्रतिलिपि बनाने के लिए इसे सीधे बच्चों के आंकड़ों की ओर इंगित करें, जैसे:

props: ['initialCounter'],
data: function () {
    return {
        counter: Vue.util.extend({}, this.initialCounter)
    }
}

विधि 3

आप प्रॉपर क्लोन करने के लिए स्प्रेड ऑपरेटर का भी उपयोग कर सकते हैं। इगोर जवाब में अधिक जानकारी: https://stackoverflow.com/a/51911118/3143704

लेकिन ध्यान रखें कि पुराने ब्राउज़रों में प्रसार ऑपरेटरों का समर्थन नहीं किया जाता है और बेहतर संगतता के लिए आपको कोड का उपयोग करके उदासीन करना होगा babel

फुटनोट

[१] ध्यान रखें कि यह एक आंतरिक Vue उपयोगिता है और यह नए संस्करणों के साथ बदल सकती है। आप उस प्रोप को कॉपी करने के लिए अन्य तरीकों का उपयोग करना चाह सकते हैं, " मैं एक जावास्क्रिप्ट ऑब्जेक्ट को सही ढंग से कैसे क्लोन करूं? " देखें।

मेरी बेला जहाँ मैं इसे परख रहा था: https://jsfiddle.net/sm4kx7p9/3/


1
इसलिए माता-पिता के घटक के लिए परिवर्तनों का प्रचार करना ठीक है?
इगोर

1
@ व्यक्तिगत रूप से मैं जितना संभव हो उतना इसे टालने की कोशिश करूंगा। यह आपके घटकों को अप्रत्याशित बना देगा। मुझे लगता है कि मूल घटक में परिवर्तन प्राप्त करने का बेहतर तरीका "वी-मॉडल" पद्धति का उपयोग करना है, जहां आप अपने बच्चे के घटक से माता-पिता के घटक में परिवर्तन का उत्सर्जन करते हैं। vuejs.org/v2/guide/computers.html#Using-v-model-on-Compords
डोमिनिक

हाँ, लेकिन गहरी वस्तुओं के बारे में क्या? क्या मुझे गहरी नकल करनी चाहिए? क्या मुझे गहरी वस्तु का उपयोग न करने के लिए अपने घटकों को नया स्वरूप देना चाहिए? यानी एक प्रोप के साथ: { ok: 1, notOk: { meh: 2 } }यदि पिछली क्लोनिंग पद्धति में से किसी के साथ एक आंतरिक डेटा पर सेट किया जाता है, तब भी वह प्रोप को बदल देगाnotOk.meh
निको

1
उत्कृष्ट सवाल और जवाब के लिए @DominikSerafin धन्यवाद। यह पूरी तरह से Vue.js. के achilles हील को दर्शाता है एक रूपरेखा के रूप में यह अच्छी तरह से मानकीकरण को संभालता है, लेकिन कंप्यूटरों के बीच डेटा पारित करना एक प्रमुख पीटीए है। बस बनाए गए नामकरण दुःस्वप्न को देखें। इसलिए अब मुझे अपने सभी प्रॉप्स को उपसर्ग करने की जरूरत है, ताकि मैं initialउन्हें अपने कंप्‍यूटर के भीतर उपयोग कर सकूं। यह इतना साफ-सुथरा होगा अगर हम dataकिसी भी कंप को कॉल करने वाले प्रोप को पास कर सकते हैं और यह सब बिना initialPropNameपागलपन के स्थानीयकृत डेटा को स्वचालित रूप से प्रचारित करता है ।
एजेबी

1
@DominikSerafin मैं सुन रहा हूँ कि तुम क्या कह रहे हो, और तुम गलत नहीं हो। लेकिन Vue.js का उपयोग करके एक फॉर्म-बिल्डर एप्लिकेशन लिखें और आप जल्दी से देखेंगे कि मेरा क्या मतलब है। मैं वास्तव में सभी डेटा के prop --> comp.dataलिए Vue-Stash का उपयोग करने से डेटा साझा करने की अपनी तकनीक को बदलने की प्रक्रिया में हूं (या Vuex बहुत काम करेगा)। लेकिन अब मैं अपने डेटा को ऑब्जेक्ट से दूर कर रहा हूं क्योंकि मैं "आधुनिक" जेएस फ्रेमवर्क से पहले उन पर अपनी राय देता था। तो यह सवाल है: क्या comp.data संपत्ति का मुद्दा बिल्कुल है? window
एजेबी

24

साथी में @ डॉमिक-सेराफिन का जवाब:

यदि आप किसी वस्तु को पास कर रहे हैं, तो आप प्रसार ऑपरेटर (ES6 सिंटैक्स) का उपयोग करके इसे आसानी से क्लोन कर सकते हैं:

 props: {
   record: {
     type: Object,
     required: true
   }
 },

data () { // opt. 1
  return {
    recordLocal: {...this.record}
  }
},

computed: { // opt. 2
  recordLocal () {
    return {...this.record}
  }
},

लेकिन सबसे महत्वपूर्ण यह है कि ऑप्ट का उपयोग करना याद रखें। 2 यदि आप एक गणना मूल्य, या उससे अधिक एक अतुल्यकालिक मूल्य से गुजर रहे हैं। अन्यथा स्थानीय मान अपडेट नहीं होगा।

डेमो:

Vue.component('card', { 
  template: '#app2',
  props: {
    test1: null,
    test2: null
  },
  data () { // opt. 1
    return {
      test1AsData: {...this.test1}
    }
  },
  computed: { // opt. 2
    test2AsComputed () {
      return {...this.test2}
    }
  }
})

new Vue({
  el: "#app1",
  data () {
    return {
      test1: {1: 'will not update'},
      test2: {2: 'will update after 1 second'}
    }
  },
  mounted () {
    setTimeout(() => {
      this.test1 = {1: 'updated!'}
      this.test2 = {2: 'updated!'}
    }, 1000)
  }
})
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>

<div id="app1">
  <card :test1="test1" :test2="test2"></card>
</div>

<template id="app2">
  <div>
    test1 as data: {{test1AsData}}
    <hr />
    test2 as computed: {{test2AsComputed}}
  </div>
</template>

https://jsfiddle.net/nomikos3/eywraw8t/281070/


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

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

recordLocal: [...this.record](मेरे मामले में रिकॉर्ड एक सरणी है) मेरे लिए काम नहीं किया - vue घटक को लोड करने और निरीक्षण करने के बाद, recordइसमें आइटम शामिल हैं और recordLocalएक खाली सरणी थी।
क्रिश्चियन

जब मैं इसे संपीडित संपत्ति का उपयोग करता हूं, तो यह अच्छी तरह से हो जाता है, मेरे लिए जब मैं डेटा के अंदर सेट करने की कोशिश करता हूं तो यह काम नहीं कर रहा है = (... लेकिन मुझे इसका उपयोग करना मिलाcomputed
felipe muner

ध्यान रखना। प्रसार ऑपरेटर केवल उथले क्लोन करता है, इसलिए उन वस्तुओं के लिए जिनमें ऑब्जेक्ट या सरणियां हैं आप अभी भी एक नई प्रतिलिपि प्राप्त करने के बजाय पॉइंटर्स कॉपी करेंगे। मैं लॉंच से क्लोनडिप का उपयोग करता हूं।
सिंडी कॉनवे

13

मेरा मानना ​​है कि आप इसे सही कर रहे हैं क्योंकि यह डॉक्स में बताया गया है।

एक स्थानीय डेटा प्रॉपर्टी को परिभाषित करें जो प्रोप के प्रारंभिक मूल्य को अपने प्रारंभिक मूल्य के रूप में उपयोग करता है

https://vuejs.org/guide/components.html#One-Way-Data-Flow


4
पास-बाय-वैल्यू प्रॉप्स के लिए जो ठीक है। इस मामले में यह एक वस्तु है, इसलिए इसे बदलने से जनक प्रभावित होगा। उस पृष्ठ से: "ध्यान दें कि जावास्क्रिप्ट में ऑब्जेक्ट्स और सरणियों को संदर्भ द्वारा पारित किया जाता है, इसलिए यदि प्रोप एक सरणी या ऑब्जेक्ट है, तो ऑब्जेक्ट या सरणी को बच्चे के घटक के अंदर उत्परिवर्तित करने से मूल स्थिति प्रभावित होगी।"
जेक

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

तो 4 साल और सीखने के घंटे के सैकड़ों के बाद मैं सही वापस आ गया हूं, जहां मैंने windowऑब्जेक्ट से बस वर्जन उछलाना शुरू कर दिया है ।
एजेबी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.