programing

구성 요소를 로드하기 전에 VueX 값이 로드될 때까지 기다리십시오.

nicescript 2022. 7. 6. 22:20
반응형

구성 요소를 로드하기 전에 VueX 값이 로드될 때까지 기다리십시오.

사용자가 컴포넌트 URL 로드를 직접 네비게이트하려고 하면 vuex 액션으로 http 콜이 발신되어 해결되면 내 상태의 값이 정의됩니다.

http 콜이 해결되어 상태 값이 정의될 때까지 컴포넌트를 로드하지 않습니다.

예를 들어, 내 구성 요소에서

export default {
  computed: {
    ...mapState({
      // ** this value needs to load before component mounted() runs **
      asyncListValues: state => state.asyncListValues
    })
  },

  mounted () {
    // ** I need asyncListValues to be defined before this runs **
    this.asyncListValues.forEach((val) => { 
      // do stuff
    });
  }
}

컴포넌트를 대기시키는 방법asyncListValues컴포넌트를 장착하기 전에 로딩할 수 있습니까?

이를 위한 한 가지 방법은 상태 값을 저장하는 것입니다.

예를 들어 스토어가 단일 API에 의존하는 경우 다음과 같은 작업을 수행합니다.단, 여러 API의 경우 각 API 로드 상태를 개별적으로 저장하거나 각 API에 대해 전용 개체를 사용하는 것이 좋습니다.

일반적으로 4가지 상태를 가질 수 있습니다.글로벌하게 액세스 가능한 모듈로 설정하는 것이 좋습니다.

// enums.js
export default {
  INIT: 0,
  LOADING: 1,
  ERROR: 2,
  LOADED: 3
};

그런 다음 변수를 vuex 상태로 저장할 수 있습니다. 여기서 apiState는 다음과 같이 초기화됩니다.INIT어레이를 초기화할 수도 있습니다.[]하지만 그럴 필요는 없어요

import ENUM from "@/enums";
// store.js
export default new Vuex.Store({
  state: {
    apiState: ENUM.INIT,
    accounts: [],
    // ...other state
  },
  mutations: {
    updateAccounts (state, accounts) {
      state.accounts = accounts;
      state.apiState = ENUM.LOADED;
    },
    setApiState (state, apiState) {
      state.apiState = apiState;
    },
  },
  actions: {
    loadAccounts ({commit) {
      commit('setApiState', ENUM.LOADING);
      someFetchInterface()
        .then(data=>commit('updateAccounts', data))
        .catch(err=>commit('setApiState', ENUM.ERROR))
    }
  }
});

그리고 나서 조금 더...computed표시되는 컴포넌트를 전환할 수 있습니다.상태를 사용하면 Error 상태를 쉽게 식별할 수 있고 상태가 준비되지 않았을 때 로드 애니메이션을 표시할 수 있습니다.

<template>
  <ChildComponent v-if="apiStateLoaded"/>
  <Loader v-if="apiStateLoading"/>
  <Error v-if="apiStateError"/>
</template>
<script>
import ENUM from "@/enums";
export default {
  computed: {
    ...mapState({
      apiState: state=> state.apiState
    }),
    apiStateLoaded() {
      return this.apiState === ENUM.LOADED;
    },
    apiStateLoading() {
      return this.apiState === ENUM.LOADING || this.apiState === ENUM.INIT;
    },
    apiStateError() {
      return this.apiState === ENUM.ERROR;
    },
  })
}
</script>

차치하고...이 패턴을 사용하여 응용 프로그램을 상태 시스템으로 관리합니다.이 예에서는 vuex를 사용하지만 컴포넌트에서 사용하도록 조정할 수 있습니다.Vue.observable(vue 2.6 이상) 또는ref(vue3)

또는 단순히 초기화를 하는 경우asyncListValues진열되어 있지 않은 가게에서[]어레이를 상정하는 에러를 회피할 수 있습니다.

말씀하신 대로vue-router질문하신 내용은beforeRouteEnter컴포넌트의 렌더링을 지연시키기 위해 작성되었습니다.

예를 들어, "photo"라는 루트가 있는 경우:

import Photo from "../page/Photo.vue";

new VueRouter({
  mode: "history",
  routes: [
    { name: "home", path: "/", component: Home },
    { name: "photo", path: "/photo", component: Photo }
  ]
});

를 사용할 수 있습니다.beforeRouteEnter다음과 같습니다.

<template>
  <div>
    Photo rendered here
  </div>
</template>
<script>
export default {
  beforeRouteEnter: async function(to, from, next) {
    try {
      await this.$store.dispatch("longRuningHttpCall");

      next();
    } catch(exception) {
      next(exception);
    }
  }
}
</script>

동작은 액션이 완료될 때까지 기다렸다가 원하는 대로 상태를 갱신하고 콜을 하는 것입니다.next()라우터에 프로세스를 속행하도록 지시합니다(컴포넌트 내의 컴포넌트).<router-view></router-view>).

ES6가 필요 없는 예제가 필요한 경우(예를 들어 이 구문을 사용하지 않는 경우)를 알려 주십시오.

이 페이지에서 의 공식 매뉴얼을 확인할 수 있습니다.또, 다음의 방법으로 루트 레벨에 배치할 수도 있습니다.beforeEnter.

한 가지 방법은 컴포넌트를 2개의 다른 컴포넌트로 분할하는 것입니다.데이터가 준비되면 새 상위 구성 요소가 데이터 가져오기 및 하위 구성 요소 렌더링을 처리할 수 있습니다.

부모 컴포넌트표시하다

<template>
  <child-component v-if="asyncListValues && asyncListValues.length" :asyncListValues="asyncListValues"/>
  <div v-else>Placeholder</div>
</template>
<script>
export default {
  computed: {
    ...mapState({
      asyncListValues: state => state.asyncListValues
    })
  }
}
</script>

Child Component(Child Component)표시하다

export default {
  props: ["asyncListValues"],
  mounted () {
    this.asyncListValues.forEach((val) => { 
      // do stuff
    });
  }
}

간단한 방법:

...
watch: {
   vuexvalue(newVal) {
      if (newVal == 'XXXX')
        this.loadData()
      }
   }
},
computed: {
   ...mapGetters(['vuexvalue'])
}

회답에 라우터를 하고 있는 는, 할 수 .RouterView상태가 로드되었을 때.

@daniel을 @daniel로 하세요.stateLoaded플래그를 지정합니다.여기에서는 2개의 스테이트 플래그를 사용하여 간단하게 설명하겠습니다만, 원하는 대로 상세하게 기술할 수 있습니다.

const store = createStore({
  state () {
    return {
      mysettings: {},         // whatever state you need
      stateLoaded: false,
    }
  },
  mutations: {
    set_state (state, new_settings) {
      state.settings = new_settings;
      state.stateLoaded = true;
    },
  }
}

ㅇㅇㅇㅇ에서는요.app.vue하다

<div class="content">
  <RouterView/>
</div>

변경 내용:

<div class="content">
  <RouterView v-if="this.$store.state.stateLoaded"/>
</div>

v-if 하나 까딱하지 않다RouterViewstateLoaded이 내리다true따라서 라우터를 사용하여 렌더링하는 모든 것은 호출되지 않으므로 라우터가 로드될 때 정의되지 않은 상태 변수가 라우터에 없습니다.

물론 이 기능을 기반으로 구축하려면v-else"로드 중... 그런 거 있잖아요 에 대비해서'이렇게 하면 안 돼요. 상태 로딩이 예상보다 오래 걸릴 경우를 대비해서요.@daniel의 multi-state 플래그를 사용하면 상태를 로드하는 데 문제가 있는지 보고하고 Retry 버튼 등을 제공할 수도 있습니다.

언급URL : https://stackoverflow.com/questions/56587777/wait-for-vuex-value-to-load-before-loading-component

반응형