programing

Vuex / Vue를 사용하여 비동기 데이터 검색을 처리하는 방법

prostudy 2022. 5. 19. 22:36
반응형

Vuex / Vue를 사용하여 비동기 데이터 검색을 처리하는 방법

나는 공통 스택이 있는 간단한 앱을 가지고 있다.

  • 백엔드 서버(레일)
  • 프런트엔드 앱(Vue)
  • 데이터베이스(PG)

Vue 앱은 다음과 같이 Vuex 저장소 라이브러리의 작업을 사용하여 백엔드에서 데이터를 가져온다.

// store/store.js
import Vue from 'vue';
import Vuex from 'vuex';
import * as MutationTypes from '@/store/mutation-types';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    investment: {},
  },
  mutations: {
    [MutationTypes.SET_INVESTMENT_SHOW](state, investment) {
      state.investment = investment;
    },
  },
  actions: {
    fetchInvestment({ commit }, id) {
      InvestmentsApi.get(id).then((response) => {
        commit(MutationTypes.SET_INVESTMENT_SHOW, response.data);
      });
    },
  },
  getters: {
    participation: state =>
      state.investment.included[0],
  },
});

이 작업은 다음과 같이 구성 요소의 생성된 라이프사이클 후크에서 호출된다.

// components/Investment.vue

import { mapActions, mapGetters } from 'vuex';
export default {
  name: 'Investment',
  computed: {
    ...mapState(['investment']),
    ...mapGetters(['participation']),
  },
  created() {
    this.fetchData(this.$route.params.id);
  },
  methods: mapActions({
    fetchData: 'fetchInvestment',
  }),
};

위에 쓴 코드에 문제가 있어, 나는 실제로 다음과 같이 내 템플릿에 계산된 값 '참여'를 사용한다.

<BaseTitleGroup
  :subtitle="participation.attributes.name"
  title="Investissements"
/>

물론 구성 요소가 렌더링될 때 참여를 사용하기 때문에 getter 방법에서 다음과 같은 오류를 얻는다.

Error in render: "TypeError: Cannot read property '0' of undefined"

found in

---> <InvestmentSummary> at src/views/InvestmentSummary.vue
       <App> at src/App.vue
         <Root>

이 문제를 해결하기 위한 몇 가지 해결책이 있다고 생각하는데, 어떤 것이 가장 좋은 방법인지, 더 좋은 방법이 있는지 궁금하다.

  1. 첫 번째 해결 방법은 데이터를 기다리는 동안 요소가 렌더링되지 않도록 v-if 속성을 내 템플릿에 넣는 것이다.
    • Con : 렌더링 오프셋(데이터가 있을 때 요소가 렌더링을 시작함)?
    • Con: 비동기 데이터를 다루는 내 앱의 모든 구성 요소에 대해 해야 하는데, 직관적으로 나는 이것을 다른 곳(아마 매장)에서 처리하고 싶어.
  2. 요소를 렌더링하고 "로드 중..."과 같은 가짜 데이터를 저장소에 넣으십시오.."
    • Con: 페이지를 로드할 때, 텍스트가 로딩에서 실제 텍스트로 전환될 때 사용자가 볼 수 있는 작은 결함은 못생겼다.
    • Con: 내 가게의 빈 버전은 쓰기 힘들고 내 앱이 확장될 때 엄청나게 클 거야.
  3. 저장소가 아닌 초기 빈 데이터를 반환하도록 Getter 변경
    • 콘: 게이터가 점점 더 복잡해 진다.
    • Con: 게이터가 필요하지 않은 데이터(아마 주(州)에서 직접 액세스할 수 있을 것이다)는 것은 어떨까?
  4. 다른거?

위의 패턴 중 하나라도 어떤 것이 가장 좋을지 잘 모르겠다.읽어줘서 정말 고마워! 또한 나는 vue 프레임워크를 사용하지만 비동기 데이터의 현대적인 자바스크립트 프레임워크 처리와 렌더링에 대한 일반적인 질문이라고 생각해.

긴 포스트에 미안, 여기 감자 있어! (아, 9개그에는 안돼;) )

Angle에는 결국 도착하는 반응형 데이터를 처리하는 간결한 방법인 Elvis(안전한 항법) 연산자가 있다.

Vue 템플릿 컴파일러에서 사용할 수 있는 경우 템플릿은 다음과 같이 표시됨:

<BaseTitleGroup
  :subtitle="participation?.attributes?.name"
  title="Investissements"
/>

하지만 에반 유는 그것이 암호 냄새처럼 들린다고 말한다.

모델/상태는 가능한 한 예측 가능해야 한다.

이 의견을 컨텍스트로 확장하려고 하면 템플릿이 저장소보다 데이터 구조에 대해 더 잘 알고 있다는 것을 의미한다고 생각한다.

템플릿

"participation.attributes.name"

이는 다음을 가리키는 말이다.

state.investment.included[0].attributes.name

저장하다

state: {
  investment: {},
},

Getter가 컴포넌트(및 it's template)를 서비스하기 위해 있기 때문에, 나는 Getter를 향상시키는 것을 선택할 것이다.

getters: {
  participation_name: state => {
    return 
      (state.investment.included 
       && state.investment.included.length
       && state.investment[0]
       && state.investment[0].attributes
       && state.investment[0].attributes.name)
      || null;
},

<BaseTitleGroup
  :subtitle="participation_name"
  title="Investissements"
/>

하지만 엘비스 기능을 원한다면 믹싱으로 제공할 수 있다.

var myMixin = {
  computed: {
    elvis: {
      get: function() {
        return (known, unknown) => {
          // use regex split to handle both properties and array indexing
          const paths = unknown.split(/[\.(\[.+\])]+/); 
          let ref = known
          paths.forEach(path => { if (ref) ref = ref[path] });
          return ref;
        }
      }
    },
  }
}

export default {
  name: 'Investment',
  ...
  mixins: [myMixin],
  computed: {
    ...mapState(['investment']),
    participation_name() {
      return this.elvis(this.investment, 'included[0].attributes.name')
    }
  },
  ...
};

최선의 해결책은 없는 것 같은데, 그냥 다 섞지 말고 그냥 아무데나 골라 써.

v-if그러나 중첩된 속성에서 데이터를 렌더링하려는 경우에는 더 나을 수 있다.v-if="object.some.nested.property v-for="el in object.some.nested.property"효과가 있을 것이다. 그러나 미리 계획되어 있을 것이다.object = {}하지 않을 것이다(그것은 에러를 던질 것이다).some정의되지 않았으며 액세스하려는 경우).

나는 너의 예처럼 어떤 가짜 데이터도 넣지 않을 것이다. 하지만 너는 ES6 클래스를 사용하여 기본 개체를 정의하고 기본 값으로 설정할 수 있다.이것은 또한 당신의 클래스 객체가 적절한 구조를 가지고 있는 한 위의 사전 정의 문제를 해결한다(그리고 그것은 또한 동의적으로 투명하고 이해하기 쉽다).

세 번째 옵션인 Getter에게 빈 데이터를 제공하는 것은 복잡할 필요가 없다. 단지 Getter를 다음과 같이 변경하십시오.

getters: {
    participation: state =>
      state.investment.included[0] || new DefaultParticipationObject() // I don't know what's in included array
  },

이것은 사용한다.state.investment.included[0]정의되어 있고 기본 개체인 경우.

참조URL: https://stackoverflow.com/questions/52438853/how-to-deal-with-async-data-retrieval-with-vuex-vue

반응형