vue.js의 구성 요소에 데이터 전달


94

vue.js의 구성 요소간에 데이터를 전달하는 방법을 이해하는 데 어려움을 겪고 있습니다. 문서를 여러 번 읽었고 많은 vue 관련 질문과 자습서를 보았지만 여전히 이해하지 못하고 있습니다.

이것에 대해 머리를 감싸기 위해 꽤 간단한 예제를 완성하는 데 도움이되기를 바랍니다.

  1. 하나의 구성 요소에 사용자 목록 표시 (완료)
  2. 링크를 클릭 (완료)하면 사용자 데이터를 새 구성 요소로 보냅니다. 하단의 업데이트를 참조하십시오.
  3. 사용자 데이터를 편집하고 원래 구성 요소로 다시 보냅니다 (지금까지 확인하지 않음).

다음은 2 단계에서 실패한 바이올린입니다. https://jsfiddle.net/retrogradeMT/d1a8hps0/

새 구성 요소에 데이터를 전달하기 위해 소품을 사용해야한다는 것을 이해하지만 기능적으로 수행하는 방법을 모르겠습니다. 데이터를 새 구성 요소에 어떻게 바인딩합니까?

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>

주요 구성 요소에 대한 Node.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);
     }
    }
  })

두 번째 구성 요소에 대한 JS :

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

최신 정보

좋아, 두 번째 단계를 알아 냈다. 다음은 진행 상황을 보여주는 새로운 바이올린입니다 : https://jsfiddle.net/retrogradeMT/9pffnmjp/

Vue-router를 사용하고 있기 때문에 데이터를 새 구성 요소로 보내는 데 소품을 사용하지 않습니다. 대신 v-link에 매개 변수를 설정 한 다음 전환 후크를 사용하여 수락해야합니다.

V-link 변경 사항 은 vue-router 문서에서 명명 된 경로를 참조하십시오 .

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

그런 다음 구성 요소에서 경로 옵션에 데이터를 추가하고 전환 후크를 참조하십시오 .

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,
        }
   },
})

답변:


47

------------- 다음은 Vue 1에만 적용됩니다. --------------

데이터 전달은 여러 가지 방법으로 수행 할 수 있습니다. 방법은 사용 유형에 따라 다릅니다.


새 구성 요소를 추가하는 동안 html에서 데이터를 전달하려는 경우. 그것은 소품을 사용하여 수행됩니다.

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

이 소품 값은 속성에 소품 이름 prop-name을 추가하는 경우에만 구성 요소에서 사용할 수 있습니다 props.


일부 동적 또는 정적 이벤트로 인해 구성 요소에서 다른 구성 요소로 데이터가 전달되는 경우. 이는 이벤트 디스패처와 브로드 캐스터를 사용하여 수행됩니다. 예를 들어 다음과 같은 구성 요소 구조가있는 경우 :

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

그리고 당신은 데이터를 보낼 <my-child-A><my-child-B>에 다음 <my-child-A>당신이 이벤트를 전달해야합니다 :

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

이 이벤트는 상위 체인까지 이동합니다. 그리고 어떤 부모로부터 당신을 향한 분기를 가지고 <my-child-B>데이터와 함께 이벤트를 방송합니다. 따라서 부모에서 :

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

이제이 방송은 자식 체인으로 이동합니다. 그리고 이벤트를 잡으려는 아이에게 우리의 경우 <my-child-B>다른 이벤트를 추가합니다.

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

데이터를 전달하는 세 번째 방법은 v-link의 매개 변수를 사용하는 것입니다. 이 메서드는 구성 요소 체인이 완전히 파괴되거나 URI가 변경 될 때 사용됩니다. 그리고 나는 당신이 이미 그들을 이해하고 있음을 볼 수 있습니다.


원하는 데이터 통신 유형을 결정하고 적절하게 선택하십시오.


1
감사합니다. 정말 도움이되었습니다. 내가 아직도 고민하고있는 유일한 부분은 명명 규칙입니다. 즉 : 나는 이름으로 v-link를 통해 전달하는 user.name을 가지고 있습니다. 이제 name 변수를 편집하고 이름으로 원래 구성 요소에 다시 전달할 수 있지만 원래 구성 요소에는 name이라는 변수가 없습니다. 내가 여기서 무엇을 놓치고 있습니까? v-link를 통해 개체를 전달할 수없는 것 같습니까?
역행

1
이미 개체를 전달하고 있습니다. params객체입니다. this.user.name구성 요소에서 이름 키를 할당 할 수 있습니다 . 도움이 필요하면 바이올린을 만들어 알려주세요. 이 체크 아웃 : vuejs.github.io/vue-router/en/route.html
notANerdDev

아, 알겠습니다. 다시 한번 감사드립니다. 도와 주셔서 감사합니다. 정말 일이 훨씬 더 명확 해졌습니다.
역행

6
멋진 대답이지만 이벤트가 더 이상 사용되지 않기 때문에 2.0에서 작동하지 않는다는 것을 알고 있습니까?
rix 2016

2
나는 대답을 좋아했지만 의견을 얻었고 Vue 2와 함께 일하고 있기 때문에 당신이 제안한 두 번째 방법을 할 수 없을 것 같습니다. 그게 정확히 두렵습니까?
Konrad Viltersten

23

부모 구성 요소에서 자식으로 데이터를 보내는 가장 좋은 방법은 props를 사용하는 것입니다 .

다음을 통해 부모에서 자식으로 데이터 전달 props

  • 자식에서 props(배열 또는 객체 ) 선언
  • 그것을 통해 아이에게 전달하십시오 <child :name="variableOnParent">

아래 데모를 참조하십시오.

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>


작은 수정 : "<child"및 variableAtParent 대신 "<child-comp".. <child-comp : name = "variableAtParent">를 통해 자식에게 전달
muenalan

단순 속성에서만 작동하며 개체 참조는 업데이트되지 않습니다. 예를 들어 부모 속성이 배열이고이 배열이 부모 개체에서 다른 배열로 대체 된 경우 자식은이를 볼 수 없습니다.
Stan Sokolov

@StanSokolov 전혀. 배열 작업을 수행합니다. jsfiddle.net/acdcjunior/q4mank05를 참조하십시오 . 어레이가 반응 적이 지 않다면 아마도 반응 문제에 직면했을 것입니다. Vue.set, 자세한 내용은 여기에서 사용해보세요 : vuejs.org/v2/guide/reactivity.html#For-Arrays
acdcjunior

그것이 반응하지 않는다면 요점은 무엇입니까? 확실히 그것은 새로운 어레이로 끊임없이 교체되는 레퍼런스와 반응했습니다. Vue는 "참조 변경"을 자식에게 전파하지 않고 단순한 요소의 값만 변경합니다. 따라서 부모에서 배열에 대한 참조를 덮어 쓴 경우 자식은 여전히 ​​이전 참조를 보게됩니다. 부모가 이제 다른 개체와 함께 작동하는지 결코 알 수 없습니다.
Stan Sokolov

@StanSokolov 참조 : jsfiddle.net/acdcjunior/ftmrne2h 어레이가 부모에서 교체되고 자식이보고 / 반응합니다 (테스트하려면 버튼 클릭). 아니면 다른 의미입니까? 만약 그렇다면, 그것을 보여주기 위해 바이올린을 편집하는 것이 도움이 될 것입니다
acdcjunior

15

문제가 여기에 있다고 생각합니다.

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

prop에 접두사 :를 붙이면 Vue에 문자열이 아니라 변수임을 나타냅니다. 따라서 {{}}주위 가 필요하지 않습니다 user.name. 시험:

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

편집하다-----

위는 사실이지만 여기서 더 큰 문제는 URL을 변경하고 새 경로로 이동하면 원래 구성 요소가 사라진다는 것입니다. 두 번째 구성 요소가 상위 데이터를 편집하도록하려면 두 번째 구성 요소가 첫 번째 구성 요소의 하위 구성 요소이거나 동일한 구성 요소의 일부 여야합니다.


고마워 제프. {{}}을 제거하려고했지만 여전히 동일한 오류가 발생합니다.
역행

2

Vue의 구성 요소 범위에 부모 데이터를 전달하는 방법을 찾았습니다. 약간의 해킹이라고 생각하지만 아마도 이것이 도움이 될 것입니다.

1) Vue 인스턴스의 데이터를 외부 개체로 참조 (data : dataObj)

2) 그런 다음 하위 구성 요소의 데이터 반환 기능에서 그냥 반환 parentScope = dataObj하고 짜잔합니다. 이제 당신은 같은 일을 할 수 없으며 {{ parentScope.prop }}매력처럼 작동합니다.

행운을 빕니다!


그것은 트리와 그의 노드에 대해 괜찮을 수 있지만 일반적으로 선호되지 않는 두 구성 요소를 함께 결합하는 것입니다. 나는 이것을 피하려고 노력할 것입니다.
12

1

위에서 언급 한 응답은 잘 작동하지만 두 형제 구성 요소간에 데이터를 전달하려는 경우 이벤트 버스도 사용할 수 있습니다. 더 잘 이해하는 데 도움이되는이 블로그를 확인하십시오.

두 가지 구성 요소가 있다고 가정합니다 : CompA 및 CompB는 동일한 부모를 가지며 main.js는 main vue 앱을 설정합니다. 상위 구성 요소를 포함하지 않고 CompA에서 CompB로 데이터를 전달하려면 다음을 수행 할 수 있습니다.

main.js 파일에서 이벤트 버스가 될 별도의 글로벌 Vue 인스턴스를 선언하십시오.

export const bus = new Vue();

이벤트가 생성되는 CompA에서 : 이벤트를 버스로 내 보내야합니다.

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

이제 작업은 방출 된 이벤트를 수신하는 것이므로 CompB에서 다음과 같이 수신 할 수 있습니다.

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

장점 :

  • Less & Clean 코드.
  • 부모는 1 개의 하위 구성 요소에서 다른 구성 요소로 데이터를 전달하는 데 관여해서는 안됩니다 (자녀 수가 증가함에 따라 유지 관리가 어려워 짐).
  • pub-sub 접근 방식을 따릅니다.

0

을 사용하여 주요 속성에 액세스합니다 $root.

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

-2

전역 JS 변수 (객체)를 사용하여 구성 요소간에 데이터를 전달할 수 있습니다. 예 : Ammlogin.vue에서 Options.vue로 데이터 전달. Ammlogin.vue에서 rspData는 서버의 응답으로 설정됩니다. Options.vue에서 서버의 응답은 rspData를 통해 사용할 수 있습니다.

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;
            });
    },
....

Options.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>
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.