Programing

동일한 페이지에 여러 번 표시된 Vuejs 구성 요소를 동기화할 수 있는가?

c10106 2022. 3. 12. 09:17
반응형

동일한 페이지에 여러 번 표시된 Vuejs 구성 요소를 동기화할 수 있는가?

나는 항목을 표시하는 웹 페이지를 가지고 있다.각 항목에 대해 버튼(vuejs 구성 요소)이 있어 사용자가 이 항목을 자신의 컬렉션에 추가/제거할 수 있다.

구성 요소는 다음과 같다.

<template lang="html">
        <button type="button" @click="toggle" name="button" class="btn" :class="{'btn-danger': dAdded, 'btn-primary': !dAdded}">{{ dText }}</button>
    </template>

<script>
export default {
    props: {
        added: Boolean,
        text: String,
        id: Number,
    },
    data() {
        return {
            dAdded: this.added,
            dText: this.text,
            dId: this.id
        }
    },
    watch: {
        added: function(newVal, oldVal) { // watch it
            this.dAdded = this.added
        },
        text: function(newVal, oldVal) { // watch it
            this.dText = this.text
        },
        id: function(newVal, oldVal) { // watch it
            this.dId = this.id
        }
    },
    methods: {
        toggle: function(event) {
            axios.post(route('frontend.user.profile.pop.toggle', {
                    pop_id: this.dId
                }))
                .then(response => {
                    this.dText = response.data.message
                    let success = response.data.success
                    this.dText = response.data.new_text
                    if (success) {
                        this.dAdded = success.attached.length
                        let cardPop = document.getElementById('card-pop-'+this.dId);
                        if(cardPop)
                            cardPop.classList.toggle('owned')
                    }
                })
                .catch(e => {
                    console.log(e)
                })
        }
    }
}
</script>

각 항목에 대해 사용자는 다음 링크를 클릭해 로드한 모달도 열 수 있다.

<a href="#" data-toggle="modal" data-target="#popModal" @click="id = {{$pop->id}}">
    <figure>
        <img class="card-img-top" src="{{ URL::asset($pop->img_path) }}" alt="Card image cap">
    </figure>
</a>

모달은 또한 Vuejs 구성 요소:

<template>
    <section id="pop" class="h-100">
        <div class="card">
            <div class="container-fluid">
                <div class="row">

                    <div class="col-12 col-lg-1 flex-column others d-none d-xl-block">
                        <div class="row flex-column h-100">

                            <div v-for="other_pop in pop.other_pops" class="col">
                                <a :href="route('frontend.pop.collection.detail', {collection: pop.collection.slug, pop: other_pop.slug})">
                                        <img :src="other_pop.img_path" :alt="'{{ other_pop.name }}'" class="img-fluid">
                                    </a>
                            </div>

                            <div class="col active order-3">
                                <img :src="pop.img_path" :alt="pop.name" class="img-fluid">
                            </div>

                        </div>
                    </div>

                    <div class="col-12 col-lg-6 content text-center">
                        <div class="row">
                            <div class="col-12">
                                <img :src="pop.img_path" :alt="pop.name" class="img-fluid">
                            </div>

                            <div class="col-6 text-right">
                                <toggle-pop :id="pop.id" :added="pop.in_user_collection" :text="pop.in_user_collection ? 'Supprimer' : 'Ajouter'"></toggle-pop>
                            </div>
                            <div class="col-6 text-left">
                                <!-- <btnaddpopwhishlist :pop_id="propid" :added="pop.in_user_whishlist" :text="pop.in_user_whishlist ? 'Supprimer' : 'Ajouter'"></btnaddpopwhishlist> -->
                            </div>
                        </div>


                    </div>
                    <div class="col-12 col-lg-5 infos">
                        <div class="header">
                            <h1 class="h-100">{{ pop.name }}</h1>
                        </div>
                        <div class="card yellow">
                            <div class="card p-0">
                                <div class="container-fluid">
                                    <div class="row">
                                        <div class="col-3 py-2">

                                        </div>
                                        <div class="col-6 py-2 bg-lightgray">
                                            <h4>Collection:</h4>
                                            <h3>{{ pop.collection ? pop.collection.name : '' }}</h3>
                                        </div>
                                        <div class="col-3 py-2 bg-lightgray text-center">
                                            <a :href="route('frontend.index') + 'collections/' + pop.collection.slug" class="btn-round right white"></a>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </section>
</template>

<script>
export default {
    props: {
        id: Number
    },
    data() {
        return {
            pop: {
                collection: {

                }
            }
        }
    },
    ready: function() {
        if (this.propid != -1)
            this.fetchData()
    },
    watch: {
        id: function(newVal, oldVal) { // watch it
            // console.log('Prop changed: ', newVal, ' | was: ', oldVal)
            this.fetchData()
        }
    },
    computed: {
        imgSrc: function() {
            if (this.pop.img_path)
                return 'storage/images/pops/' + this.pop.img_path
            else
                return ''
        }
    },
    methods: {
        fetchData() {
            axios.get(route('frontend.api.v1.pops.show', this.id))
                .then(response => {
                    // JSON responses are automatically parsed.
                    // console.log(response.data.data.collection)
                    this.pop = response.data.data
                })
                .catch(e => {
                    this.errors.push(e)
                })
            // console.log('fetchData')
        }
    }
}
</script>

여기 내 app.js 스크립트:

window.Vue = require('vue');

Vue.component('pop-modal', require('./components/PopModal.vue'));
Vue.component('toggle-pop', require('./components/TogglePop.vue'));

const app = new Vue({
    el: '#app',
    props: {
        id: Number
    }
});

이름이 지정된 구성 요소의 상태를 동기화하려고 함toggle-pop, 내가 어떻게 이것을 성취할 수 있는가?하나는 블레이드 템플릿(래블)으로 렌더링되고 다른 하나는pop-modal구성 요소하지만 그것들은 서로 다른 장소에 전시된, 똑같다.

고마워요.

국가 사물을 재산으로 전가할 수 있다.toggle-pop구성 요소들그들은 그들의 상태를 저장/수정하기 위해 이 재산을 사용할 수 있다.이러한 방식으로 여러 구성 요소 집합이 공유 상태를 가질 수 있다.

구성 요소가 될 수 있는 항목:

<template lang="html">
  <button type="button" @click="toggle" name="button" class="btn" :class="{'btn-danger': sstate.added, 'btn-primary': !sstate.added}">{{ sstate.text }}</button>
</template>

<script>
export default {
  props: {
    sstate: {
      type: Object,
      default: function() {
        return { added: false, text: "", id: -1 };
      }
    }
  },
  data() {
    return {};
  },
  methods: {
    toggle: function(event) {
      axios.post(route('frontend.user.profile.pop.toggle', {
        pop_id: this.sstate.id
      }))
        .then(response => {
            this.sstate.text = response.data.message
            let success = response.data.success
            this.sstate.text = response.data.new_text
            if (success) {
                this.sstate.ddded = success.attached.length
                let cardPop = document.getElementById('card-pop-'+this.sstate.id);
                if(cardPop)
                    cardPop.classList.toggle('owned')
            }
        })
        .catch(e => {
          console.log(e)
        })
  }
};
</script>

라이브 데모

https://codesandbox.io/s/vq8r33o1w7

모든 성분의 상태가 항상 동일해야 한다고 100% 확신할 경우 정의하지 않도록 선택할 수 있다.data함수로서그냥 물건이라고 선언해.

  data: {
    dAdded: this.added,
    dText: this.text,
    dId: this.id
  }

https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function,에서 언급한다.

구성 요소의 데이터 옵션은 각 인스턴스가 반환된 데이터 개체의 독립 복사본을 유지할 수 있도록 함수가 되어야 함

Vue에 이 규칙이 없는 경우 버튼 하나를 클릭하면 다른 모든 인스턴스의 데이터에 영향을 미침

모든 데이터를 동기화하려면toggle-pop구성 요소 인스턴스(instance)를 따를 필요 없음data option must be a function통치를 하다

참조URL: https://stackoverflow.com/questions/49740422/is-it-possible-to-sync-vuejs-components-displayed-multiple-times-on-the-same-pag

반응형