Vuex 액션 vs 돌연변이


173

Vuex에서 "동작"과 "돌연변이"를 갖는 논리는 무엇입니까?

구성 요소의 논리가 스마트하게 보이는 상태를 수정할 수는 없지만 동작과 변이를 모두 갖는 것은 하나의 함수를 작성하여 다른 함수를 트리거 한 다음 상태를 변경하는 것처럼 보입니다.

"동작"과 "돌연변이"의 차이점은 무엇이며 어떻게 작동합니까? 또한 Vuex 개발자가 왜 이런 식으로 결정했는지 궁금합니다.


2
"동작시"를 참조하십시오. vuex.vuejs.org/en/mutations.html#on-to-actions
Roy J


1
상점 상태를 직접 변경할 수 없습니다. 상점의 상태를 변경하는 유일한 방법은 명시 적으로 돌연변이를 저지르는 것입니다. 이를 위해서는 돌연변이를 저지르기위한 조치가 필요합니다.
Suresh Sapkota

1
@SureshSapkota 그 진술은 매우 모두 같은 혼란 mutationsactions상태를 변경하는 방법으로 vuex 설명서에 definted된다. 돌연변이를 저지르기위한 조치가 필요하지 않습니다.
Graham

1
이름에서 알 수 있듯이 돌연변이는 상태 객체를 수정 / 돌연변이하는 데 사용됩니다. 액션은 돌연변이와 매우 유사하지만 상태를 변경하는 대신 돌연변이를 저지 릅니다. 작업에는 임의 의 비동기 코드 또는 비즈니스 논리 가 포함될 수 있습니다 . Vuex는 상태 객체가 돌연변이 기능 내에서만 변형되어야한다고 권장합니다. 또한 Mutation 함수 내에서 무겁거나 블로킹 코드를 실행하지 않는 것이 좋습니다 ( 동기 적이므로) .
Emmanuel Neni

답변:


221

질문 1 : Vuejs 개발자가 왜 그렇게하기로 결정 했습니까?

대답:

  1. 응용 프로그램이 커지고이 프로젝트에서 작업중인 여러 개발자가있는 경우 "상태 관리"(특히 "글로벌 상태")가 점점 더 복잡해집니다.
  2. vuex 방식 (react.js의 Redux와 마찬가지로 )은 상태를 관리하고 상태를 유지하며 "저장하고 추적 할 수있는"새로운 메커니즘을 제공합니다 (즉, 상태를 수정하는 모든 작업은 디버그 도구 로 추적 할 수 있음을 의미합니다 : vue-devtools )

질문 2 : "action"과 "mutation"의 차이점은 무엇입니까?

공식적인 설명을 먼저 보자 :

돌연변이 :

Vuex 돌연변이는 본질적으로 사건입니다 : 각 돌연변이에는 이름과 핸들러가 있습니다.

import Vuex from 'vuex'

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    INCREMENT (state) {
      // mutate state
      state.count++
    }
  }
})

액션 : 액션은 돌연변이를 보내는 함수입니다.

// the simplest action
function increment (store) {
  store.dispatch('INCREMENT')
}

// a action with additional arguments
// with ES2015 argument destructuring
function incrementBy ({ dispatch }, amount) {
  dispatch('INCREMENT', amount)
}

위의 설명은 다음과 같습니다.

  • 돌연변이 는 상태를 수정 하는 유일한 방법입니다
  • 돌연변이 는 비즈니스 로직에 관심이없고 "상태"에 관심이있다
  • 행동 은 비즈니스 로직
  • 액션 은 한 번에 둘 이상의 돌연변이를 파견 할 수 있으며 비즈니스 로직 만 구현하며 데이터 변경에 신경 쓰지 않습니다 (돌연변이로 관리)

80
액션이 "비즈니스 로직"이고 한 번에 여러 개의 돌연변이를 파견 할 수 있다는 사실이 도움이됩니다. 그것이 내가 찾던 대답입니다. 감사합니다.
코비

11
당신은 당신이 "변이를 파견한다"고 단언합니다. 돌연변이를 저지르는 올바른 표현이 아닌가?
ProblemsOfSumit

4
액션을 전달하고 돌연변이를 저지 릅니다.
eirik

4
vue 2.0에서 더 이상 돌연변이가 발생하지 않으면 작업에서 돌연변이를 저지르는 것이 필요합니다.
SKLTFZ

18
@Kaicui이 답변에는 항상 동기화되는 돌연변이와 잠재적으로 비동기적인 동작에 대한 메모가 없습니다. 그 외에는 좋은 대답입니다!
결정

58

돌연변이는 동 기적이지만 동작은 비동기적일 수 있습니다.

다른 방법으로 말하자면 : 작업이 동기식 일 경우에는 조치가 필요하지 않으며, 그렇지 않으면 구현하십시오.


2
이것은 실제로 todomvc 예제가 동작을 사용하지 않는 방법에 대한 질문에 대답합니다.
sksallaj

7
'작업이 동기식 일 경우 동작이 필요하지 않습니다' : 사실이 아닙니다 . 동작에서 다른 동작을 호출 할 수 없으므로 동일한 모듈에서 여러 변이를 작성하려면 동작 필요합니다.
Raymundus

1
이 답변에 분명한 후속는 "왜 단지 행동을하고 돌연변이를 제거하지"가 될 것입니다
마이클 Mrozek

34

나는 돌연변이와 행동의 동기에 대한 이해가 어느 때와 어떻게 사용할 것인지 더 잘 판단 할 수 있다고 믿습니다. 또한 "규칙"이 희미 해지는 상황에서 프로그래머가 불확실성의 부담을 덜어줍니다. 각각의 목적에 대해 약간의 추론을 한 후에, 행동과 돌연변이를 사용하는 잘못된 방법이있을 수는 있지만 정식 접근법이 있다고 생각하지 않습니다.

먼저 왜 우리가 돌연변이 또는 행동을 겪는 지 이해하려고 노력합시다.

왜 처음부터 상용구를 통과해야합니까? 구성 요소에서 직접 상태를 변경하지 않는 이유는 무엇입니까?

엄밀히 말하면 state구성 요소 에서 직접 변경할 수 있습니다 . 은 state단지 자바 스크립트 객체이며, 당신이 그것을 만드는 것이 변화를 되돌아갑니다 아무것도 마법이있다.

// Yes, you can!
this.$store.state['products'].push(product)

그러나이 작업을 수행하면 모든 곳에서 상태 돌연변이가 분산됩니다. 상태를 수용하는 단일 모듈을 열 수있는 능력을 잃어 버리고 어떤 종류의 작업을 적용 할 수 있는지 한 눈에 알 수 있습니다. 중앙 집중식 돌연변이가 있으면 일부 상용구 비용이 들지만이를 해결합니다.

// so we go from this
this.$store.state['products'].push(product)

// to this
this.$store.commit('addProduct', {product})

...
// and in store
addProduct(state, {product}){
    state.products.push(product)
}
...

보일러 플레이트로 짧은 것을 교체하면 보일러 플레이트도 작게 만들고 싶습니다. 따라서 돌연변이는 비즈니스 로직이 거의없는 상태에서 네이티브 작업을 둘러싼 매우 얇은 래퍼라고 생각합니다. 다시 말해서, 돌연변이는 주로 세터와 같이 사용되는 것을 의미한다.

이제 돌연변이를 중앙 집중화 했으므로 상태 변경에 대한 개요가 개선되었으며 툴링 (vue-devtools)도 해당 위치를 인식하므로 디버깅이 쉬워집니다. 또한 많은 Vuex 플러그인은 상태를 직접 추적하여 변경 사항을 추적하지 않고 돌연변이에 의존한다는 점을 명심해야합니다. 따라서 상태에 대한 "경계를 벗어난"변경 사항은 보이지 않습니다.

그래서 mutations, actions차이 어쨌든 무엇입니까?

돌연변이와 같은 조치도 상점의 모듈에 상주하며 state오브젝트를 수신 할 수 있습니다 . 그들이 할 수 있음을 의미 직접 돌연변이 수도 . 그렇다면 둘 다 갖는 요점은 무엇입니까? 돌연변이를 작고 단순하게 유지해야한다고 생각한다면보다 정교한 비즈니스 로직을 수용 할 수있는 대체 수단이 필요하다는 것을 의미합니다. 행동은이를위한 수단입니다. 이전에 설정 한 것처럼 vue-devtools 및 플러그인은 Mutations를 통한 변경 사항을 알고 있으므로 일관성을 유지하려면 작업에서 Mutations를 계속 사용해야합니다. 더욱이, 액션은 모두 포함되어야하고, 캡슐화하는 로직은 비동기적일 수 있으므로 액션은 처음부터 단순히 비동기식으로 만들어 질 것입니다.

행동은 비동기적일 수 있지만 돌연변이는 일반적으로 그렇지 않다는 것이 종종 강조된다. 돌연변이는 동기적인 모든 것에 (그리고 비동기적인 것에 대한 행동) 사용되어야한다는 표시로 구별을 보도록 결정할 수있다. 그러나 예를 들어 둘 이상의 돌연변이를 (동 기적으로) 커밋해야하거나 돌연변이 함수가 Getters 또는 Mutations를 인수로받지 않기 때문에 돌연변이에서 Getter와 함께 작업 해야하는 경우 몇 가지 어려움에 처하게됩니다 ...

... 흥미로운 질문으로 이어집니다.

돌연변이는 왜 Getter를받지 않습니까?

아직이 질문에 대한 만족스러운 답변을 찾지 못했습니다. 나는 핵심 팀이 내가 mo을 발견했다고 설명했다. 사용법을 요약하면 Getter는 상태에 대한 확장을 계산 (및 종종 캐시)해야합니다. 다시 말해서, 기본적으로 여전히 상태이지만 일부 선행 계산이 필요하지만 일반적으로 읽기 전용입니다. 그것은 적어도 그들이 사용하도록 권장되는 방법입니다.

따라서 돌연변이가 Getter에 직접 액세스하는 것을 방지한다는 것은 우리가 전자에서 제공하는 일부 기능을 전자에서 액세스해야하는 경우 이제 세 가지 중 하나가 필요하다는 것을 의미합니다. (1) Getter가 제공 한 상태 계산이 액세스 가능한 곳에 중복되어 있습니다. (2) 계산 된 값 (또는 관련 Getter 자체)이 Mutation (펑키)에 대한 명시적인 인수로 전달되거나 (3) Getter의 논리 자체가 Mutation 내에서 직접 복제 됨 Getter (stench)에서 제공하는 캐싱의 추가 이점없이

다음은 (2)의 예입니다. 제가 경험 한 대부분의 시나리오에서 "최소 불량"옵션으로 보입니다.

state:{
    shoppingCart: {
        products: []
    }
},

getters:{
    hasProduct(state){
        return function(product) { ... }
    }
}

actions: {
    addProduct({state, getters, commit, dispatch}, {product}){

        // all kinds of business logic goes here

        // then pull out some computed state
        const hasProduct = getters.hasProduct(product)
        // and pass it to the mutation
        commit('addProduct', {product, hasProduct})
    }
}

mutations: {
    addProduct(state, {product, hasProduct}){ 
        if (hasProduct){
            // mutate the state one way
        } else {
            // mutate the state another way 
        }
    }
}

저에게 위의 내용은 약간 복잡 할뿐만 아니라 다소 "누설"인 것 같습니다. 액션에 존재하는 일부 코드는 분명히 돌연변이의 내부 논리에서 나오기 때문입니다.

내 생각에 이것은 타협의 표시입니다. 돌연변이가 Getter를 자동으로 수신하도록 허용하면 몇 가지 문제가 있다고 생각합니다. Vuex 자체의 설계 또는 툴링 (vue-devtools 등), 또는 이전 버전과의 호환성을 유지하거나 명시된 모든 가능성의 조합 일 수 있습니다.

내가 믿지 않는 것은 Getters를 돌연변이에 전달하는 것이 반드시 무언가 잘못하고 있다는 표시입니다. 프레임 워크의 단점 중 하나를 단순히 "패치"하는 것으로 간주합니다.


1
저에게 가장 좋은 대답입니다. 그것을 읽은 후에 만, 나는 당신이 무언가를 이해한다고 느낄 때 느끼는이 "클릭"을 가졌습니다.
Robert Kusznier

게터는 기본적으로 computed출력됩니다. 읽기 전용입니다. 돌연변이를 보는 더 좋은 방법은 가지고있는 것을 제거하는 if else것입니다. vuex 문서에 따르면 commit액션 안에 둘 이상을 수용 할 수 있다고합니다 . 따라서 논리에 따라 특정 돌연변이를 저지를 수 있다고 가정하는 것이 합리적입니다. 나는 행동을 WHICH 돌연변이가 발사하도록 지시하는 방법으로 본다.
Tamb

@Tamb : State와 Getters는 상황에 맞는 데이터를 제공합니다. 상태를 수정하는 방법을 결정하기 전에 쿼리를받는 것이 좋습니다. 해당 정보를 State에서 완전히 가져올 수있는 경우 State에 액세스 할 수 있으므로 전체 로직이 단일 Mutation 내에 캡슐화되는 것이 좋습니다. 세터의 표준 작동 절차입니다. 이해가되지 않는 것은 이제 비슷한 정보를 얻기 위해 Getter를 쿼리해야하기 때문에 완전히 다른 접근법을 사용하는 것입니다.
Michael Ekoka

@Tamb : 당신이 제안하는 것은 Getter를 쿼리 할 때 위의 패턴을 변경하고 선택 로직을 Getter에 접근 할 수 있고 작은 바보 돌연변이를 묶을 수있는 프록시 액션으로 옮겨야한다는 것입니다. 그것은 작동하지만 여전히 회로적이고 내 대답에서 언급 한 악취를 다루지 않고 다른 곳으로 옮깁니다.
Michael Ekoka

문서에서는 상태를 계산해야 할 때 게터를 사용한다고 말합니다. 그래서 그들은 오늘날 계산 된 속성과 비슷한 것으로 보였습니다. 행동이 돌연변이를 함께 붙일 수 있다고 말함으로써 얻는 것 Idk. 문서는 분명히 비즈니스 로직을 행동에 포함 시키라고 말합니다.
Tamb

15

TLDR의 대답은 돌연변이가 동기 / 트랜잭션이어야한다는 것입니다. 따라서 Ajax 호출을 실행하거나 다른 비동기 코드를 수행해야하는 경우 Action에서 해당 작업을 수행 한 후 새 상태를 설정하기 위해 mutation을 수행해야합니다.


1
이것은 문서의 요약처럼 보입니다. 아무 문제가 없습니다. 그러나이 답변의 문제는 그것이 주장하는 것이 반드시 사실이 아니라는 것입니다. 비동기 함수 / AJAX를 호출 할 때 돌연변이 내부의 상태를 수정할 수 있으며, 이는 완전한 콜백에서 변경 될 수 있습니다. 이것이 Vuex와 함께 작업 할 때 최상의 개발 방법을 위해 조치를 사용해야 하는 이유에 대해 많은 혼란을 야기하는 원인이라고 생각합니다 . Vuex와 함께 일을 시작했을 때 그것이 저에게 혼란의 원인이었습니다.
Erutan409

8

동작과 돌연변이의 주요 차이점 :

  1. 내부 작업에서는 비동기 코드를 실행할 수 있지만 돌연변이는 실행할 수 없습니다. 따라서 비동기 코드에는 동작을 사용하고 그렇지 않으면 돌연변이를 사용하십시오.
  2. 내부 액션은 게터, 상태, 돌연변이 (커밋), 돌연변이의 액션 (디 패칭)에 액세스 할 수 있습니다. 따라서 상태에만 액세스하려면 돌연변이를 사용하고 그렇지 않으면 동작을 사용하십시오.

5

에 따르면 docs

행동변이 와 유사하지만 차이점은 다음과 같습니다.

  • 상태 를 변경 하는 대신 액션 커밋 돌연변이를 .
  • 작업 에는 임의의 비동기 작업 이 포함될 수 있습니다 .

다음 스 니펫을 고려하십시오.

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++               //Mutating the state. Must be synchronous
    }
  },
  actions: {
    increment (context) {
      context.commit('increment') //Committing the mutations. Can be asynchronous.
    }
  }
})

조치 핸들러 ( increment )는 상점 인스턴스에서 동일한 메소드 / 특성 세트를 노출하는 컨텍스트 오브젝트를 수신하므로 context.commit을 호출하여 돌연변이를 커미트하거나 context.state 및 context.getters를 통해 상태 및 게터에 액세스 할 수 있습니다.


1
'mutation'함수에서 호출이 가능한가? vuejs 컴포넌트의 메소드입니까?
Alberto Acuña

@ AlbertoAcuña 나는 같은 질문을 가지고 있습니다. 왜냐하면 그것을 시도 할 때 국소 돌연변이가 정의되지 않았다는 오류가 발생하기 때문입니다.
Rutwick Gangurde

5

면책 조항-방금 vuejs를 사용하기 시작 했으므로 디자인 의도를 외삽하는 것입니다.

Time Machine 디버깅은 상태의 스냅 샷을 사용하고 작업 및 변이의 타임 라인을 보여줍니다. 이론적으로 우리는 actions돌연변이를 동시에 기술하기 위해 상태 설정자와 게터의 기록과 함께 있을 수 있었다 . 하지만:

  • 세터와 게터를 유발하는 입력이 잘못되었습니다 (비동기 결과). 논리적으로 따라 가기가 어려우며 다른 비동기 세터와 게터가 놀랍게 상호 작용할 수 있습니다. mutations트랜잭션에서 여전히 발생할 수 있지만 작업에서 경쟁 조건이 아닌 트랜잭션을 개선해야한다고 말할 수 있습니다. 비동기 프로그래밍은 깨지기 쉽고 어렵 기 때문에 작업 내에서 익명의 돌연변이가 이러한 종류의 버그를 더 쉽게 다시 나타낼 수 있습니다.
  • 상태 변경에 대한 이름이 없으므로 트랜잭션 로그를 읽기가 어렵습니다. 그것은 훨씬 더 코드와 유사하고 영어가 적을 것이고, 돌연변이의 논리적 그룹이 누락되었습니다.
  • 돌연변이 함수 호출 전후에 동 기적으로 정의 된 차이 지점이있는 위치와 달리 데이터 객체에 돌연변이를 기록하는 것은 까다 롭고 성능이 떨어질 수 있습니다. 그것이 얼마나 큰 문제인지 잘 모르겠습니다.

다음 트랜잭션 로그를 명명 된 돌연변이와 비교하십시오.

Action: FetchNewsStories
Mutation: SetFetchingNewsStories
Action: FetchNewsStories [continuation]
Mutation: DoneFetchingNewsStories([...])

명명 된 돌연변이가없는 트랜잭션 로그를 사용하는 경우 :

Action: FetchNewsStories
Mutation: state.isFetching = true;
Action: FetchNewsStories [continuation]
Mutation: state.isFetching = false;
Mutation: state.listOfStories = [...]

이 예제에서 액션 내부의 비동기 및 익명 돌연변이의 잠재적 인 복잡성을 추가 할 수 있기를 바랍니다.

https://vuex.vuejs.org/en/mutations.html

이제 앱을 디버깅하고 devtool의 돌연변이 로그를보고 있다고 상상해보십시오. 기록 된 모든 돌연변이에 대해 devtool은 상태의 "이전"및 "이후"스냅 샷을 캡처해야합니다. 그러나 위의 예제 돌연변이 내부의 비동기 콜백은 불가능합니다. 돌연변이가 커밋되었을 때 콜백이 아직 호출되지 않고 콜백이 실제로 언제 호출되는지 devtool이 알 수있는 방법이 없습니다-콜백에서 수행 된 상태 돌연변이 본질적으로 추적 할 수 없습니다!


4

돌연변이 :

Can update the state. (Having the Authorization to change the state).

행위:

Actions are used to tell "which mutation should be triggered"

Redux 방식으로

Mutations are Reducers
Actions are Actions

왜 둘 다 ??

응용 프로그램이 증가하고 코딩 및 라인이 증가 할 때 변이는 상태를 변경하는 유일한 권한이므로 변이가 아닌 동작의 논리를 처리해야합니다. 가능한 한 깨끗해야합니다.


2

이것은 나도 혼란스러워서 간단한 데모를 만들었습니다.

component.vue

<template>
    <div id="app">
        <h6>Logging with Action vs Mutation</h6>
        <p>{{count}}</p>
        <p>
            <button @click="mutateCountWithAsyncDelay()">Mutate Count directly with delay</button>
        </p>
        <p>
            <button @click="updateCountViaAsyncAction()">Update Count via action, but with delay</button>
        </p>
        <p>Note that when the mutation handles the asynchronous action, the "log" in console is broken.</p>
        <p>When mutations are separated to only update data while the action handles the asynchronous business
            logic, the log works the log works</p>
    </div>
</template>

<script>

        export default {
                name: 'app',

                methods: {

                        //WRONG
                        mutateCountWithAsyncDelay(){
                                this.$store.commit('mutateCountWithAsyncDelay');
                        },

                        //RIGHT
                        updateCountViaAsyncAction(){
                                this.$store.dispatch('updateCountAsync')
                        }
                },

                computed: {
                        count: function(){
                                return this.$store.state.count;
                        },
                }

        }
</script>

store.js

import 'es6-promise/auto'
import Vuex from 'vuex'
import Vue from 'vue';

Vue.use(Vuex);

const myStore = new Vuex.Store({
    state: {
        count: 0,
    },
    mutations: {

        //The WRONG way
        mutateCountWithAsyncDelay (state) {
            var log1;
            var log2;

            //Capture Before Value
            log1 = state.count;

            //Simulate delay from a fetch or something
            setTimeout(() => {
                state.count++
            }, 1000);

            //Capture After Value
            log2 = state.count;

            //Async in mutation screws up the log
            console.log(`Starting Count: ${log1}`); //NRHG
            console.log(`Ending Count: ${log2}`); //NRHG
        },

        //The RIGHT way
        mutateCount (state) {
            var log1;
            var log2;

            //Capture Before Value
            log1 = state.count;

            //Mutation does nothing but update data
            state.count++;

            //Capture After Value
            log2 = state.count;

            //Changes logged correctly
            console.log(`Starting Count: ${log1}`); //NRHG
            console.log(`Ending Count: ${log2}`); //NRHG
        }
    },

    actions: {

        //This action performs its async work then commits the RIGHT mutation
        updateCountAsync(context){
            setTimeout(() => {
                context.commit('mutateCount');
            }, 1000);
        }
    },
});

export default myStore;

이것을 연구 한 결과, 돌연변이는 업데이트 된 데이터 전후에 문제를 더 잘 분리하고 로깅을 개선하기 위해 데이터를 변경하는 데에만 초점을 둔 관습이라는 결론에 도달했습니다. 동작은 상위 수준의 논리를 처리 한 다음 적절하게 돌연변이를 호출하는 추상화 계층입니다.


0

1. 문서에서 :

행동은 돌연변이와 유사하지만 차이점은 다음과 같습니다.

  • 상태를 변경하는 대신 작업이 돌연변이를 저지 릅니다.
  • 작업에는 임의의 비동기 작업이 포함될 수 있습니다.

작업에는 비동기 작업이 포함될 수 있지만 변이는 할 수 없습니다.

2. 돌연변이를 일으켜 상태를 직접 바꿀 수 있습니다. 또한 다음과 같이 상태를 변경하는 작업을 수행 할 수 있습니다.

actions: {
  increment (store) {
    // do whatever ... then change the state
    store.dispatch('MUTATION_NAME')
  }
}

Actions는 더 많은 것들을 처리하기 위해 설계되었으며, 우리는 많은 것들을 할 수 있습니다 (비동기 연산을 사용할 수 있습니다).


0

돌연변이가없는 상태가 없기 때문에! 커밋 될 때 — 예측 가능한 방식으로 상태를 변경하는 논리가 실행됩니다. 돌연변이는 상태를 설정하거나 변경하는 유일한 방법이므로 직접적인 변경은 없습니다. 또한 동기식이어야합니다. 이 솔루션은 매우 중요한 기능을 수행합니다. 돌연변이가 devtools에 기록됩니다. 그리고 그것은 당신에게 훌륭한 가독성과 예측 성을 제공합니다!

한 가지 더 – 행동. 말했듯이 행동은 돌연변이를 저지른다. 따라서 상점을 변경하지 않으며 이들이 동기화 될 필요가 없습니다. 그러나 추가 비동기 로직을 ​​관리 할 수 ​​있습니다!


0

actions를 들어을 호출 하는 추가 계층이 필요하지 않은 것처럼 보일 수 있습니다 mutations.

const actions = {
  logout: ({ commit }) => {
    commit("setToken", null);
  }
};

const mutations = {
  setToken: (state, token) => {
    state.token = token;
  }
};

전화를 actions걸면logout 하면 돌연변이 자체를 호출하는 것이 어떻습니까?

조치의 전체 아이디어는 하나의 조치 내부에서 여러 돌연변이를 호출하거나 Ajax 요청 또는 상상할 수있는 모든 종류의 비동기 논리를 작성하는 것입니다.

결국 여러 개의 네트워크 요청을하고 여러 가지 다른 변이를 호출하는 작업이있을 수 있습니다.

우리는 우리로부터 많은 복잡성으로 물건을 시도 그래서 Vuex.Store()우리에 가능한 한 actions이 잎 우리 mutations, state그리고 getters깨끗하고 간단하고 뷰와 같은 라이브러리를 만들고 인기 반작용 모듈 방식의 종류와 라인에 빠진다.


0

저는 약 3 년 동안 Vuex를 전문적으로 사용해 왔습니다. 여기에 제가 행동과 돌연변이의 근본적인 차이점, 함께 사용함으로써 얻을 수있는 이점, 그리고 어떻게하면 삶을 더 힘들게 만들 수 있는지에 대해 제가 생각한 것입니다 잘 사용하지 마십시오.

Vuex의 주요 목표는 애플리케이션의 동작을 제어하는 ​​새로운 패턴 인 반응성을 제공하는 것입니다. 아이디어는 응용 프로그램 상태의 오케스트레이션을 특수 객체 인 상점으로 오프로드하는 것입니다. 편리하게 사용할 수 있도록 구성 요소를 상점 데이터에 직접 연결하는 방법을 편리하게 제공합니다. 이를 통해 구성 요소는 사용자에게 제공 할 템플릿, 스타일 및 기본 구성 요소 동작 정의와 같은 작업에 집중할 수 있습니다. 한편, 상점은 과도한 데이터로드를 처리합니다.

그러나이 패턴의 유일한 장점은 아닙니다. 상점이 전체 애플리케이션에 대한 단일 데이터 소스라는 사실은 여러 구성 요소에서이 데이터를 재사용 할 수있는 큰 잠재력을 제공합니다. 이는 교차 컴포넌트 통신 문제를 해결하려는 첫 번째 패턴은 아니지만 기본적으로 컴포넌트가이 공유 데이터의 상태를 수정하지 못하도록하여 애플리케이션에 매우 안전한 동작을 구현하도록 강요하는 것입니다. 대신 '공개 엔드 포인트'를 사용하여 변경을 요청하십시오.

기본 아이디어는 다음과 같습니다.

  • 상점의 내부 상태는 구성 요소가 직접 액세스해서는 안됩니다 (mapState는 효과적으로 금지됨)
  • 상점에는 내부 상태에 대한 동기 수정 인 돌연변이가 있습니다. 돌연변이의 유일한 일은 상태를 수정하는 것입니다. 액션에서만 호출해야합니다. 상태 (ORDER_CANCELED, ORDER_CREATED)에 발생한 일을 설명하기 위해 이름을 지정해야합니다. 짧고 달콤하게 유지하십시오. Vue Devtools 브라우저 확장을 사용하여 단계별로 진행할 수 있습니다 (디버깅에도 좋습니다!)
  • 상점에는 또한 조치가 있으며, 비동기 또는 약속을 리턴해야합니다. 구성 요소는 응용 프로그램의 상태를 수정하려고 할 때 호출하는 작업입니다. 비즈니스 지향적 조치 (예 : cancelOrder, createOrder) 로 이름을 지정해야합니다 . 여기에서 요청을 확인하고 보냅니다. 상태를 변경해야하는 경우 각 조치는 다른 단계에서 다른 커밋을 호출 할 수 있습니다.
  • 마지막으로, 상점에는 상태가 구성 요소에 노출시키는 데 사용하는 게터가 있습니다. 응용 프로그램이 확장됨에 따라 여러 구성 요소에서 많이 사용될 것으로 예상됩니다. Vuex는 쓸모없는 계산 사이클을 피하기 위해 게터를 많이 캐시합니다 (게터에 매개 변수를 추가하지 않고 매개 변수를 사용하지 않는 한) 광범위하게 사용하는 것을 망설이지 마십시오. 응용 프로그램의 현재 상태를 가능한 한 가깝게 설명하는 이름을 지정하십시오.

즉, 마법은 우리가 이런 방식으로 응용 프로그램을 설계하기 시작할 때 시작됩니다. 예를 들면 다음과 같습니다.

  • 주문을 삭제할 수있는 주문 목록을 사용자에게 제공하는 구성 요소가 있습니다.
  • 구성 요소가 ID를 가진 오브젝트의 배열 인 상점 getter (deletableOrders)를 맵핑했습니다.
  • 구성 요소에는 각 주문 행에 버튼이 있으며 클릭은 주문 객체를 전달하는 상점 작업 (deleteOrder)에 매핑됩니다 (우리는 기억할 것입니다.
  • store deleteOrder 조치는 다음을 수행합니다.
    • 삭제 확인
    • 임시로 삭제하는 주문을 저장합니다.
    • ORDER_DELETED 돌연변이를 순서대로 커밋합니다.
    • 실제로 주문을 삭제하기 위해 API 호출을 보냅니다 (예, 상태를 수정 한 후!)
    • 호출이 끝날 때까지 대기하고 (상태가 이미 업데이트 됨) 실패하면 이전에 유지 한 순서대로 ORDER_DELETE_FAILED 변이를 호출합니다.
  • ORDER_DELETED 돌연변이는 삭제 가능한 주문 목록에서 주어진 주문을 간단히 제거합니다 (게터를 업데이트합니다)
  • ORDER_DELETE_FAILED 돌연변이는 단순히 그것을 되돌려 놓고 오류를 알리기 위해 상태로 수정합니다 (다른 구성 요소 인 오류 알림은 표시 할 때 알 수 있도록 해당 상태를 추적합니다)

결국, 우리는 "반응적인"것으로 간주되는 사용자 경험을 가지고 있습니다. 사용자 관점에서 항목이 즉시 삭제되었습니다. 대부분의 경우 엔드 포인트가 제대로 작동하기를 기대하므로 완벽합니다. 실패한 경우에도 애플리케이션이 어떻게 반응 할 것인지에 대한 제어권이 있습니다. 프론트 엔드 애플리케이션의 상태에 대한 우려와 실제 데이터를 성공적으로 분리했기 때문입니다.

항상 상점이 필요하지는 않습니다. 다음과 같은 상점을 작성하는 경우 :

export default {
  state: {
    orders: []
  },
  mutations: {
    ADD_ORDER (state, order) {
       state.orders.push(order)
    },
    DELETE_ORDER (state, orderToDelete) {
       state.orders = state.orders.filter(order => order.id !== orderToDelete.id)
    }
  },
  actions: {
    addOrder ({commit}, order) {
      commit('ADD_ORDER', order)
    },
    deleteOrder ({commit}, order) {
      commit('DELETE_ORDER', order)
    }
  },
  getters: {
    orders: state => state.orders
  }
}

나에게 그것은 당신이 데이터 저장소로만 저장소를 사용하고 있으며 아마도 응용 프로그램이 반응하는 변수를 제어하지 못하게함으로써 반응성 측면에서 누락되었을 것입니다. 기본적으로 구성 요소에 작성된 일부 코드 행을 상점에 오프로드 할 수 있으며 아마도 오프로드해야합니다.

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