Verileri vue.js'deki bileşenlere aktarma


92

Vue.js'deki bileşenler arasında verilerin nasıl aktarılacağını anlamakta zorlanıyorum. Dokümanları birkaç kez okudum ve vue ile ilgili birçok soruya ve öğreticiye baktım, ancak yine de anlamıyorum.

Kafamı bu konuya kaptırmak için, oldukça basit bir örneği tamamlamak için yardım almayı umuyorum.

  1. bir bileşendeki kullanıcıların listesini görüntüle (tamamlandı)
  2. Bir bağlantı tıklandığında (tamamlandığında) kullanıcı verilerini yeni bir bileşene gönderin - alttaki güncellemeye bakın.
  3. kullanıcı verilerini düzenleyin ve orijinal bileşene geri gönderin (şimdiye kadar ulaşmadınız)

İşte ikinci adımda başarısız olan bir keman: https://jsfiddle.net/retrogradeMT/d1a8hps0/

Verileri yeni bileşene aktarmak için props kullanmam gerektiğini anlıyorum, ancak bunu işlevsel olarak nasıl yapacağımdan emin değilim. Verileri yeni bileşene nasıl bağlarım?

HTML:

    <div id="page-content">
       <router-view></router-view>
     </div>

 <template id="userBlock" >
   <ul>
     <li v-for="user in users">{{user.name}} - <a v-link="{ path: '/new' }"> Show new component</a>
     </li>
   </ul>
 </template>

  <template id="newtemp" :name ="{{user.name}}">
    <form>
      <label>Name: </label><input v-model="name">
      <input type="submit" value="Submit">
    </form>
  </template>

ana bileşen için js:

Vue.component('app-page', {
  template: '#userBlock',

  data: function() {
    return{

        users: []
      }
    },

ready: function () {
    this.fetchUsers();
},

methods: {
    fetchUsers: function(){
        var users = [
          {
            id: 1,
            name: 'tom'
          },
          {
            id: 2,
            name: 'brian'
          },
          {
            id: 3,
            name: 'sam'
          },
        ];

        this.$set('users', users);
     }
    }
  })

İkinci bileşen için JS:

Vue.component('newtemp', {
  template: '#newtemp',
  props: 'name',
  data: function() {
    return {
        name: name,
        }
   },
})

GÜNCELLEME

Tamam, ikinci adımı anladım. İşte ilerlemeyi gösteren yeni bir keman: https://jsfiddle.net/retrogradeMT/9pffnmjp/

Vue-yönlendirici kullandığım için, verileri yeni bir bileşene göndermek için props kullanmıyorum. Bunun yerine, v-link üzerinde parametreler ayarlamam ve bunu kabul etmek için bir geçiş kancası kullanmam gerekiyor.

V-link değişiklikleri , vue-router belgelerinde adlandırılmış rotalara bakın :

<a v-link="{ name: 'new', params: { name: user.name }}"> Show new component</a>

Ardından bileşen üzerinde, rota seçeneklerine veri ekleyin, bkz. Geçiş kancaları :

Vue.component('newtemp', {
  template: '#newtemp',
  route: {
   data: function(transition) {
        transition.next({
            // saving the id which is passed in url
            name: transition.to.params.name
        });
     }
  },
 data: function() {
    return {
        name:name,
        }
   },
})

Yanıtlar:


46

------------- Aşağıdakiler yalnızca Vue 1 için geçerlidir --------------

Veri aktarımı birden çok yolla yapılabilir. Yöntem, kullanım türüne bağlıdır.


Yeni bir bileşen eklerken html'nizden veri iletmek istiyorsanız. Bu, sahne kullanılarak yapılır.

<my-component prop-name="value"></my-component>

Eğer pervane adını ekleyin yalnızca bu prop değer, bileşenin sunulacak prop-namesizin için propsöznitelik.


Veriler, bazı dinamik veya statik olaylar nedeniyle bir bileşenden başka bir bileşene aktarıldığında. Bu, olay dağıtıcıları ve yayıncıları kullanılarak yapılır. Örneğin, aşağıdaki gibi bir bileşen yapınız varsa:

<my-parent>
    <my-child-A></my-child-A>
    <my-child-B></my-child-B>
</my-parent>

Ve gelen veri göndermek istediğiniz <my-child-A>için <my-child-B>daha sonra <my-child-A>bir olayı göndermesine sahip olacaktır:

this.$dispatch('event_name', data);

Bu olay, ana zincirin sonuna kadar gidecek. Ve hangi ebeveynden size doğru bir şubeniz <my-child-B>varsa, olayı verilerle birlikte yayınlayın. Yani ebeveynde:

events:{
    'event_name' : function(data){
        this.$broadcast('event_name', data);
    },

Şimdi bu yayın çocuk zincirini aşacak. Etkinliği hangi çocukta kapmak isterseniz isteyin, bizim durumumuzda <my-child-B>başka bir etkinlik ekleyeceğiz:

events: {
    'event_name' : function(data){
        // Your code. 
    },
},

Veri geçirmenin üçüncü yolu v-linklerindeki parametrelerdir. Bu yöntem, bileşen zincirleri tamamen yok edildiğinde veya URI'nin değiştiği durumlarda kullanılır. Ve onları zaten anladığını görebiliyorum.


Ne tür bir veri iletişimi istediğinize karar verin ve uygun şekilde seçin.


1
Teşekkür ederim, bu gerçekten yardımcı oldu. Hala uğraştığım tek parça adlandırma kuralları. yani: v-link aracılığıyla isim olarak geçirdiğim user.name var. Şimdi isim değişkenini düzenleyebilir ve onu orijinal bileşene isim olarak geri gönderebilirim, ancak orijinal bileşenin name adında bir varisi yok. Burada neyi özlüyorum? Bir nesneyi v-link üzerinden geçirmek mümkün görünmüyor mu?
retrograd

1
Zaten bir nesneyi geçiyorsunuz. paramsbir nesnedir. Ad anahtarı, this.user.namebileşeninizde atanabilir . Yardıma ihtiyacın olursa bir keman oluştur ve bana haber ver. Şuna bir
notANerdDev

Ah, tamam şimdi anladım. Tekrar teşekkürler. Yardımın için minnettarım, gerçekten işleri daha net hale getirdi
geriye dönük

6
Harika cevap ama anladığım kadarıyla olaylar kullanımdan kaldırıldığı için 2.0 ile çalışmayacak mı?
rix

2
Cevabı sevdim ama sonra yorumlara ulaştım ve Vue 2 ile çalıştığım için, sizin önerdiğiniz ikinci yöntemi yapamayacağımı hissediyorum. Bundan doğru bir şekilde korkuluyor mu?
Konrad Viltersten

23

Bir üst bileşenden bir alt öğeye veri göndermenin en iyi yolu props kullanmaktır .

Verileri ebeveynden çocuğa iletme props

  • Alt öğede bildirme props(dizi veya nesne )
  • Bunu çocuğa iletin <child :name="variableOnParent">

Aşağıdaki demoya bakın:

Vue.component('child-comp', {
  props: ['message'], // declare the props
  template: '<p>At child-comp, using props in the template: {{ message }}</p>',
  mounted: function () {
    console.log('The props are also available in JS:', this.message);
  }
})

new Vue({
  el: '#app',
  data: {
    variableAtParent: 'DATA FROM PARENT!'
  }
})
<script src="https://unpkg.com/vue@2.5.13/dist/vue.min.js"></script>

<div id="app">
  <p>At Parent: {{ variableAtParent }}<br>And is reactive (edit it) <input v-model="variableAtParent"></p>
  <child-comp :message="variableAtParent"></child-comp>
</div>


küçük düzeltme: "<child" ve variableAtParent yerine "<child-comp" .. <child-comp: name = "variableAtParent"> aracılığıyla çocuğa
aktar

Yalnızca basit özellik ile çalışacak, nesne referansları güncellenmeyecektir. Örneğin, ebeveyn özelliğiniz dizi ise ve bu dizi üst nesnede başka bir diziyle değiştirilirse, çocuk onu görmez.
Stan Sokolov

@StanSokolov değil. Diziler için çalışıyorum, bakınız: jsfiddle.net/acdcjunior/q4mank05 . Diziniz reaktif değilse, muhtemelen bir tepkisellik sorunuyla karşı karşıyasınızdır. Daha Vue.setfazla şuradan kullanmayı deneyin : vuejs.org/v2/guide/reactivity.html#For-Arrays
acdcjunior

Reaktif değilse ne anlamı var? Elbette, referans sürekli olarak yeni bir dizi ile değiştirilerek reaktifti. Vue, "referans değişikliklerini" çocuklara yaymaz, yalnızca basit öğeler üzerindeki değer değişikliklerini yayar. Yani diziye referansın üst öğede üzerine yazılması durumunda, çocuklar yine de eski referansı göreceklerdir. Ebeveynin artık farklı bir nesneyle çalıştığını asla bilemeyeceğim.
Stan Sokolov

@StanSokolov Şuna bakın: jsfiddle.net/acdcjunior/ftmrne2h dizi ebeveynde değiştirilir ve çocuk onu görür / tepki verir (test etmek için düğmeye tıklayın). Yoksa başka bir şey mi kastediyorsun? Öyleyse, kemanını göstermek için düzenlemeniz faydalı olacaktır
acdcjunior

15

Sanırım sorun burada:

<template id="newtemp" :name ="{{user.name}}">

Pervanenin önüne eklediğinizde, Vue'ya :onun bir dize değil, bir değişken olduğunu belirtmiş olursunuz. Yani {{}}etrafa ihtiyacınız yok user.name. Deneyin:

<template id="newtemp" :name ="user.name">

DÜZENLE-----

Yukarıdakiler doğrudur, ancak buradaki daha büyük sorun, URL'yi değiştirip yeni bir rotaya gittiğinizde orijinal bileşenin kaybolmasıdır. İkinci bileşenin üst veriyi düzenlemesini sağlamak için, ikinci bileşenin birincinin alt bileşeni veya sadece aynı bileşenin bir parçası olması gerekir.


Teşekkürler jeff. {{}} Kaldırmayı denedim ama yine de aynı hataları alıyorum.
retrograd

2

Vue'da ana verileri bileşen kapsamına geçirmenin bir yolunu buldum, sanırım bu biraz hack ama belki bu size yardımcı olabilir.

1) Vue Örneğinde harici bir nesne olarak referans verileri (data : dataObj)

2) Daha sonra, alt bileşendeki veri dönüş işlevinde sadece dönün parentScope = dataObjve tamamlayın . Şimdi böyle şeyler yapamazsın {{ parentScope.prop }}ve bir cazibe gibi çalışacak.

İyi şanslar!


Bu, her iki bileşeni bir ağaç ve düğümleri için uygun olabilecek şeyleri birbirine bağlar, ancak normalde tercih edilmez. Bundan kaçınmaya çalışırdım.
Aralık

1

Yukarıda belirtilen yanıtlar iyi çalışıyor ancak verileri 2 kardeş bileşen arasında geçirmek istiyorsanız, olay veriyolu da kullanılabilir. Daha iyi anlamanıza yardımcı olacak bu bloga göz atın.

2 bileşen için varsayalım: Ana vue uygulamasını kurmak için aynı parent ve main.js'ye sahip CompA & CompB. Ana bileşeni dahil etmeden verileri CompA'dan CompB'ye geçirmek için aşağıdakileri yapabilirsiniz.

main.js dosyasında, olay veriyolu olacak ayrı bir genel Vue örneği belirtin.

export const bus = new Vue();

Olayın oluşturulduğu CompA'da: olayı veriyoluna göndermeniz gerekir.

methods: {
      somethingHappened (){
          bus.$emit('changedSomething', 'new data');
      }
  }

Şimdi görev yayılan olayı dinlemektir, bu nedenle CompB'de beğenebilirsiniz.

created (){
    bus.$on('changedSomething', (newData) => {
      console.log(newData);
    })
  }

Avantajlar:

  • Daha Az ve Temiz kod.
  • Ebeveyn, verileri 1 çocuk kompozisyonundan diğerine aktarmaya dahil olmamalıdır (çocuk sayısı arttıkça bakımı zorlaşır)
  • Pub-sub yaklaşımını takip eder.

0

Kullanarak ana özelliklere erişiyorum $root.

Vue.component("example", { 
    template: `<div>$root.message</div>`
});
...
<example></example>

-2

Bileşenler arasında veri aktarmak için genel bir JS değişkeni (nesne) kullanılabilir. Örnek: Ammlogin.vue'dan Options.vue'ya veri aktarımı. Ammlogin.vue'da rspData, sunucudan gelen yanıta ayarlanır. Options.vue'da sunucudan gelen yanıt rspData aracılığıyla kullanıma sunulur.

index.html:

<script>
    var rspData; // global - transfer data between components
</script>

Ammlogin.vue:

....    
export default {
data: function() {return vueData}, 
methods: {
    login: function(event){
        event.preventDefault(); // otherwise the page is submitted...
        vueData.errortxt = "";
        axios.post('http://vueamm...../actions.php', { action: this.$data.action, user: this.$data.user, password: this.$data.password})
            .then(function (response) {
                vueData.user = '';
                vueData.password = '';
                // activate v-link via JS click...
                // JSON.parse is not needed because it is already an object
                if (response.data.result === "ok") {
                    rspData = response.data; // set global rspData
                    document.getElementById("loginid").click();
                } else {
                    vueData.errortxt = "Felaktig avändare eller lösenord!"
                }
            })
            .catch(function (error) {
                // Wu oh! Something went wrong
                vueData.errortxt = error.message;
            });
    },
....

Seçenekler.vue:

<template>
<main-layout>
  <p>Alternativ</p>
  <p>Resultat: {{rspData.result}}</p>
  <p>Meddelande: {{rspData.data}}</p>
  <v-link href='/'>Logga ut</v-link>
</main-layout>
</template>
<script>
 import MainLayout from '../layouts/Main.vue'
 import VLink from '../components/VLink.vue'
 var optData = { rspData: rspData}; // rspData is global
 export default {
   data: function() {return optData},
   components: {
     MainLayout,
     VLink
   }
 }
</script>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.