IT이야기

하위 구성 요소에서 상위 데이터 업데이트

cyworld 2022. 3. 10. 22:17
반응형

하위 구성 요소에서 상위 데이터 업데이트

나는 부에즈(2.0)를 가지고 놀기 시작했다.나는 하나의 구성요소가 들어 있는 간단한 페이지를 만들었다.페이지에는 데이터가 포함된 Vue 인스턴스가 하나 있다.그 페이지에서 나는 html에 구성요소를 등록하고 추가했다.구성 요소가 하나 있음input[type=text]그이 부모 인스턴스)에 나는 그 값이 부모(메인 Vue 인스턴스)에 반영되기를 원한다.

구성 요소의 상위 데이터를 올바르게 업데이트하는 방법부모로부터 바운드된 소품을 건네는 것은 좋지 않고 콘솔에 약간의 경고를 던진다.그들은 의사록에 뭔가가 있지만 그것은 효과가 없다.

양방향 바인딩은 Vue 2.0에서 더 이벤트 중심 아키텍처의 사용을 위해 더 이상 사용되지 않았다.일반적으로 어린이는 그 소품을 변이해서는 안 된다.오히려, 그것은 사건들을 발생시키고 부모들이 그 사건들에 반응하도록 해야 한다.

특정 경우에는 다음 구성 요소를 사용하여v-model. 이것은 양방향 바인딩에 가까운 것을 허용하는 특별한 구문이지만, 실제로는 위에서 설명한 사건 중심 아키텍처의 속기다.당신은 여기서 그것에 대해 읽을 수 있다 -> https://vuejs.org/v2/guide/components.html#Form-Input-Components-using-Custom-Events.

여기 간단한 예가 있다.

Vue.component('child', {
  template: '#child',
  
  //The child has a prop named 'value'. v-model will automatically bind to this prop
  props: ['value'],
  methods: {
    updateValue: function (value) {
      this.$emit('input', value);
    }
  }
});

new Vue({
  el: '#app',
  data: {
    parentValue: 'hello'
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>

<div id="app">
  <p>Parent value: {{parentValue}}</p>
  <child v-model="parentValue"></child>
</div>

<template id="child">
   <input type="text" v-bind:value="value" v-on:input="updateValue($event.target.value)">
</template>


문서에는 다음과 같이 명시되어 있다.

<custom-input v-bind:value="something" v-on:input="something = arguments[0]"></custom-input>

와 같다

<custom-input v-model="something"></custom-input>

그렇기 때문에 아이에 대한 소품은 가치라는 이름을 붙여야 하고, 아이도 가치라는 이름을 붙인 이벤트를 열어야 하는 것이다.input.

하위 구성 요소:

this.$emit('eventname', this.variable)

상위 구성 요소:

<component @eventname="updateparent"></component>

methods: {
    updateparent(variable) {
        this.parentvariable = variable
    }
}

설명서:

Vue.js에서는 부모-자녀 구성 요소 관계를 소품 다운, 이벤트 업으로 요약할 수 있다.부모는 소품을 통해 아이에게 데이터를 전달하고, 아이는 이벤트를 통해 부모에게 메시지를 보낸다.다음엔 어떻게 작동하는지 봅시다.

여기에 이미지 설명을 입력하십시오.

소품 전달 방법

하위 요소에 소품을 전달하기 위한 코드는 다음과 같다.

<div>
  <input v-model="parentMsg">
  <br>
  <child v-bind:my-message="parentMsg"></child>
</div>

이벤트 발생 방법

HTML:

<div id="counter-event-example">
  <p>{{ total }}</p>
  <button-counter v-on:increment="incrementTotal"></button-counter>
  <button-counter v-on:increment="incrementTotal"></button-counter>
</div>

JS:

Vue.component('button-counter', {
  template: '<button v-on:click="increment">{{ counter }}</button>',
  data: function () {
    return {
      counter: 0
    }
  },
  methods: {
    increment: function () {
      this.counter += 1
      this.$emit('increment')
    }
  },
})
new Vue({
  el: '#counter-event-example',
  data: {
    total: 0
  },
  methods: {
    incrementTotal: function () {
      this.total += 1
    }
  }
})

하위 구성 요소

사용하다this.$emit('event_name')상위 구성 요소로 이벤트를 전송하십시오.

여기에 이미지 설명을 입력하십시오.

상위 구성 요소

부모 구성 요소에서 그 사건을 듣기 위해, 우리는v-on:event_name그리고 방법 (ex. handleChange)은(는) 해당 이벤트에 대해 실행하고자 하는 경우

여기에 이미지 설명을 입력하십시오.

완료 :)

나는 위의 사람들에 대한 이벤트 배출과 v-model 답변에 동의한다.하지만, 구글에서 돌아온 첫 기사 중 하나인 것처럼 보이기 때문에, 나는 부모에게 다시 배출하고 싶은 여러 폼 요소를 가진 부품들에 대해 내가 발견한 것을 게시할 것이라고 생각했다.

나는 그 질문이 단일 입력을 명시한다는 것을 알지만, 이것은 가장 가까운 일치처럼 보였고 유사한 vue 구성 요소를 가진 사람들을 얼마간 시간을 절약할 수 있을 것이다.또한, 아무도 그 문제를 언급하지 않았다..sync아직 수식어

내가 아는 바로는 그 사람은v-model솔루션은 부모에게 반환되는 하나의 입력에만 적합하다.나는 그것을 찾는데 시간이 좀 걸렸지만 Vue(2.3.0) 문서에는 구성 요소로 전송된 여러 소품들을 부모에게 (물론 방출로) 동기화하는 방법이 나와 있다.

그것은 적절히 "The"라고 불린다..sync수식어

설명서의 내용은 다음과 같다.

경우에 따라서는 소품용 '양방향 바인딩'이 필요할 수도 있다.불행히도, 진정한 양방향 결합은 유지보수에 문제를 일으킬 수 있다. 왜냐하면 자식 구성 요소는 부모와 자식 모두에게 그러한 돌연변이의 원인이 명백하지 않은 상태에서 부모를 변이시킬 수 있기 때문이다.

그렇기 때문에 그 대신 우리는 그 패턴으로 이벤트를 내보내는 것을 추천한다.update:myPropName예를 들어, 가상 구성 요소에서title새로운 가치를 할당하려는 의도를 다음과 같이 전달할 수 있다.

this.$emit('update:title', newTitle)

그런 다음, 부모가 원할 경우 해당 이벤트를 듣고 로컬 데이터 속성을 업데이트할 수 있다.예를 들면 다음과 같다.

<text-document   
 v-bind:title="doc.title"  
 v-on:update:title="doc.title = $event"
></text-document>

편의를 위해 .sync 수식어를 사용하여 이 패턴에 대한 속기를 제공한다.

<text-document v-bind:title.sync="doc.title"></text-document>

객체를 통해 전송하여 한 번에 여러 개를 동기화할 수도 있다.여기에서 설명서를 확인하십시오.

보다 간단한 방법은 사용이다.this.$emit

신부님

<template>
  <div>
    <h1>{{ message }}</h1>
    <child v-on:listenerChild="listenerChild"/>
  </div>
</template>

<script>
import Child from "./Child";
export default {
  name: "Father",
  data() {
    return {
      message: "Where are you, my Child?"
    };
  },
  components: {
    Child
  },
  methods: {
    listenerChild(reply) {
      this.message = reply;
    }
  }
};
</script>

Child.vue

<template>
  <div>
    <button @click="replyDaddy">Reply Daddy</button>
  </div>
</template>

<script>
export default {
  name: "Child",
  methods: {
    replyDaddy() {
      this.$emit("listenerChild", "I'm here my Daddy!");
    }
  }
};
</script>

자세한 예: https://codesandbox.io/s/update-parent-property-ufj4b

또한 소품을 Object 또는 Array로 전달할 수도 있다.이 경우 데이터는 양방향 바인딩된다.

(주제의 마지막 부분에 설명되어 있음: https://vuejs.org/v2/guide/components.html#One-Way-Data-Flow )

Vue.component('child', {
  template: '#child',
  props: {post: Object},
  methods: {
    updateValue: function () {
      this.$emit('changed');
    }
  }
});

new Vue({
  el: '#app',
  data: {
    post: {msg: 'hello'},
    changed: false
  },
  methods: {
    saveChanges() {
        this.changed = true;
    }
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.13/vue.js"></script>

<div id="app">
  <p>Parent value: {{post.msg}}</p>
  <p v-if="changed == true">Parent msg: Data been changed - received signal from child!</p>
  <child :post="post" v-on:changed="saveChanges"></child>
</div>

<template id="child">
   <input type="text" v-model="post.msg" v-on:input="updateValue()">
</template>

상위 제안자 ->에

data : function(){
            return {
                siteEntered : false, 
            };
        },

하위 구성 요소 ->에서

this.$parent.$data.siteEntered = true;

아이 안에서

 <input
            type="number"
            class="form-control"
            id="phoneNumber"
            placeholder
            v-model="contact_number"
            v-on:input="(event) => this.$emit('phoneNumber', event.target.value)"
    />

data(){
    return {
      contact_number : this.contact_number_props
    }
  },
  props : ['contact_number_props']

부모인

<contact-component v-on:phoneNumber="eventPhoneNumber" :contact_number_props="contact_number"></contact-component>


 methods : {
     eventPhoneNumber (value) {
      this.contact_number = value
    }

2021년 답변 - Vue 2.3 이상

간단한 답변: 추가만 하십시오..sync부모에서 수정자 및 데이터를 자식에게 소품으로 전달:

    // PARENT:
    data () {
    return {
      formData: {
        members: [] //<- we wanna pass this one down to children and add/remove from the child component
      }
    }

   // PARENT TEMPLATE:
   <!-- ADD MEMBERS -->
  <add-members :members.sync="formData.members" />

중첩된 자식 구성 요소:회원 추가.부에를 하다

export default {
  name: 'AddMembers',
  props: ['members'],
  methods: {
    addMember () {
      this.members.push(new Member()) // <-- you can play and reactivity will work (in the parent)  
    },
    removeMember (index) {
      console.log('remove', index, this.members.length < 1)
      this.members.splice(index, 1)
    }
  }
}

긴 이야기: 리앨리티의 하위 구성 요소에서 변경된 사항이 $emailing 및 업데이트되고 있음formData.members[]모계의

출처: Mauro Perez(중간

올바른 방법은 기본 Vue 인스턴스가 수신하는 하위 구성 요소의 이벤트에 대한 것이다.

// Child.js
Vue.component('child', {
  methods: {
    notifyParent: function() {
      this.$emit('my-event', 42);
    }
  }
});

// Parent.js
Vue.component('parent', {
  template: '<child v-on:my-event="onEvent($event)"></child>',
  methods: {
    onEvent: function(ev) {
      v; // 42
    }
  }
});

또 다른 방법은 부모로부터 세터 참조를 소품으로 자식 구성요소에 전달하는 것인데, 그들이 반응에서 세터를 수행하는 방법과 유사하다. 넌 , 넌어.updateValue값을 업데이트하기 위해 부모에서 다음과 같이 자식 구성 요소를 인스턴스화할 수 있다.<child :updateValue="updateValue"></child>아이에게는 다음과 같은 소품이 제공된다.props: {updateValue: Function}, 그리고 템플릿에서 입력이 변경되면 메소드를 호출한다.<input @input="updateValue($event.target.value)">.

이유는 모르겠지만, 나는 단지 데이터를 개체로 사용하면서 부모 데이터를 성공적으로 업데이트했어.:set&computed

상위.vue

<!-- check inventory status - component -->
    <CheckInventory :inventory="inventory"></CheckInventory>

data() {
            return {
                inventory: {
                    status: null
                },
            }
        },

Child.vue

<div :set="checkInventory">

props: ['inventory'],

computed: {
            checkInventory() {

                this.inventory.status = "Out of stock";
                return this.inventory.status;

            },
        }

그의 예는 제출 버튼에서 입력값을 부모에게 전달하는 방법을 알려줄 것이다.

먼저 eventBus를 새 Vue로 정의하십시오.

//main.js
import Vue from 'vue';
export const eventBus = new Vue();

Pass your input value via Emit.
//Sender Page
import { eventBus } from "../main";
methods: {
//passing data via eventbus
    resetSegmentbtn: function(InputValue) {
        eventBus.$emit("resetAllSegment", InputValue);
    }
}

//Receiver Page
import { eventBus } from "../main";

created() {
     eventBus.$on("resetAllSegment", data => {
         console.log(data);//fetching data
    });
}

내 생각엔 이게 요령을 터득할 것 같아.

@change="$emit(variable)"

도입부

나는 vue3에서 부모로부터 자식(그리고 다시)으로의 데이터 전송을 찾고 있었다(질문은 vue2에 관한 것이었지만, 당시에는 SO에 대한 vue3에 대한 참조가 없다).

아래는 작동하는 보일러플레이트 결과인데, 내가 주의할 점이 거의 없는 순수 "html + js", 포장기, 모듈 등이 있다고 설명했다.

주의:

  1. Child - line에 Tnserting
    <component-a :foo="bar" @newfooevent="bar = $event"></component-a>`
    
  • 나는 속박한다parent.barchild.foo으로 :foo="bar", 와 같다.v-bind:foo="bar"그것은 소품을 통해 부모로부터 자식에게 데이터를 전달한다.

  • 주의사항: 이벤트 수신기는 하위 구성요소 태그에만 배치되어야 한다!

    바로 그것이다.@newfooevent="bar = $event"일부분할하다

    신호는 앞쪽에서 잡을 수 없다.<div id="app">또는 부모 내부의 다른 모든 곳에.

    그래도 이것은 우주의 부모 쪽이고, 여기서는 모든 부모의 데이터에 접근하여 아이의 신호에서 데이터를 추출하여 처리할 수 있다.

  1. 앱을 생성하고, 앱 다음에 구성 요소를 정의할 수 있다.app.component("component-a", ...)일부분할하다

    주의사항: C/C++의 함수 등 구성요소의 전진 선언에는 필요하지 않다.구성요소를 사용하는 앱을 생성하고 구성요소를 나중에 정의할 수 있다.나는 그것을 어떻게 해서든 신고할 방법을 찾느라 많은 시간을 허비했다. 필요 없다.

  2. 여기서 당신은 좋은 예시를 찾을 수 있다.v-model사용법, 그리고 내가 분류할 때 사용한 코드: https://javascript.plainenglish.io/vue-3-custom-events-d2f310fe34c9

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>App</title>
    <meta charset="utf-8" />
    <script src="https://unpkg.com/vue@next"></script>
  </head>
  <body>
    <div id="app">
      <component-a :foo="bar" @newfooevent="bar = $event"></component-a>
      <p>Parent copy of `bar`: {{ bar }}</p>
      <button @click="bar=''">Clear</button>
    </div>

    <script>
      const app = Vue.createApp({
        data() {
          return {
            bar: "bar start value"
          };
        }
      });      

      app.component("component-a", {
        props: {
          foo: String
        },
        template: `
          <input 
            type="text"
            :value="foo"
            @input="$emit('newfooevent', $event.target.value)">
        `
      });      

      app.mount("#app");
    </script>
  </body>
</html>

자식에서 부모로 데이터 변경을 전달하는 또 다른 방법이 있다.provide-inject나 방법을 하며,되지만,에서 방법을 하는 데도 할 수 상위 구성요소는 하위 구성요소에 데이터 또는 방법을 "제공"하며, 이 데이터 또는 방법은 하위 구성요소에 "주입"되지만, 상위 구성요소에서 메서드를 트리거하고 매개변수를 전달하는 데도 사용할 수 있다.
이 접근방식은 여러 다른 구성요소에 포함된 하위 구성요소를 가질 때 특히 유용할 수 있다.또한, 대규모 프로젝트에서는 다음 사항에 대한 개요를 놓치지 않도록 주의해야 한다.provide그리고inject관용법

상위(상위 수준) 구성 요소 App.vue의 예:provide그 방법에 접근할 수 있게 하다updateParentValue(데이터가 아닌 방법이 제공된 경우,provide방법의 형태:

<template>
  <h2>App.vue, parentValue is: <em>{{ parentValue }}</em></h2>
  <ChildComponent1 />
</template>

<script>
import ChildComponent1 from "./components/ChildComponent1.vue";

export default {
  data() {
    return {
      parentValue: "",
    };
  },
  components: {
    ChildComponent1,
  },
  provide() {
    return {
      updateParent: this.updateParentValue,
    };
  },
  methods: {
    updateParentValue($value) {
      this.parentValue = $value;
    },
  },
};
</script>

이 예에서 구성 요소4.vue가 "하단", 즉 App.vue가 구성 요소1, 구성 요소1이 구성 요소2를 포함하는 경우...실제로 사용하는 구성 요소4까지inject호출된 상위 메서드와 매개 변수에 대한 액세스 권한 얻기$value전달됨(여기서는 임의의 번호만):

<template>
  <div>
    <h2>ChildComponent4.vue</h2>
    <button @click="updateParent(Math.random())">
      Update parent value in App.vue
    </button>
  </div>
</template>

<script>
export default {
  inject: ["updateParent"],
};
</script>

전체 예는 여기에서 확인할 수 있다.
.js 설서

여기에 이미지 설명을 입력하십시오.

참조URL: https://stackoverflow.com/questions/40915436/vuejs-update-parent-data-from-child-component

반응형