vue.js 2 vuex에서 상점 값을 보는 방법


168

나는 함께 사용 vuex하고 vuejs 2있습니다.

나는 처음에 변수 변화 vuex를보고 싶습니다 store.

watch내 기능 을 추가하고 싶습니다vue component

이것이 지금까지 내가 가진 것입니다.

import Vue from 'vue';
import {
  MY_STATE,
} from './../../mutation-types';

export default {
  [MY_STATE](state, token) {
    state.my_state = token;
  },
};

변경 사항이 있는지 알고 싶습니다. my_state

어떻게 봐야하지 store.my_state내 vuejs 구성 요소?


크롬과 함께 제공되는 Vuejs 플러그인을 사용하면 편리 할 것입니다
AKASH PANDEY

답변:


206

의 당신은 과일 바구니를 가지고 있고, 추가 또는 바구니에서 과일을 제거 할 때마다, 당신은 과일 수에 대해 (1) 표시 정보를 원하는, 예를 들어 말을하자, 하지만 당신은 또한 (2) 통지 할 멋진 방식으로 과일의 수 ...

fruit-count-component.vue

<template>
  <!-- We meet our first objective (1) by simply -->
  <!-- binding to the count property. -->
  <p>Fruits: {{ count }}</p>
</template>

<script>
import basket from '../resources/fruit-basket'

export default () {
  computed: {
    count () {
      return basket.state.fruits.length
      // Or return basket.getters.fruitsCount
      // (depends on your design decisions).
    }
  },
  watch: {
    count (newCount, oldCount) {
      // Our fancy notification (2).
      console.log(`We have ${newCount} fruits now, yay!`)
    }
  }
}
</script>

에서 함수의 이름이 있음을 유의하시기 바랍니다 watch객체의에서 함수의 이름과 일치해야합니다 computed개체를. 위의 예에서 이름은 count입니다.

감시 속성의 새 값과 이전 값은 매개 변수로 시계 콜백 (카운트 함수)에 전달됩니다.

바구니 상점은 다음과 같습니다.

fruit-basket.js

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const basket = new Vuex.Store({
  state: {
    fruits: []
  },
  getters: {
    fruitsCount (state) {
      return state.fruits.length
    }
  }
  // Obviously you would need some mutations and actions,
  // but to make example cleaner I'll skip this part.
})

export default basket

다음 리소스에서 자세한 내용을 읽을 수 있습니다.


watch액션이 두 단계로 나뉘어 야 할 때 내가해야 할 일이 무엇인지 궁금 합니다. 1) 먼저 원하는 데이터가 캐시되는지 여부와 캐시 된 데이터를 반환하는지 확인하십시오. 2) 캐시가 실패하면 데이터를 가져 오기 위해 비동기 ajax 작업이 필요하지만 이것이 작업 인 것 같습니다 action. 내 질문이 이해되기를 바랍니다, 감사합니다!
1Cr18Ni9

micah5의 답변에 비해 이점은 무엇입니까?이 값은 구성 요소의 감시자를 상점 가치로 설정합니다. 유지할 코드가 적습니다.
Exocentric

@Exocentric 답을 쓸 때 질문이 명확하지 않았습니다. 속성을 감시해야하는 이유는 없습니다. "변수 X를보고 싶어서 Y를 할 수 있습니다."라고 생각하십시오. 아마도 이것이 대부분의 답변이 매우 다른 접근법을 제안하는 이유 일 것입니다. 그 의도가 무엇인지 아무도 모른다. 그래서 나는 대답에 "목표"를 포함 시켰습니다. 목표가 다르면 다른 대답이 적합 할 수 있습니다. 내 예제는 실험의 출발점 일뿐입니다. 플러그 앤 플레이 솔루션이 아닙니다. 혜택은 상황에 따라 다르므로 "혜택"은 없습니다.
Anastazy

@ 1Cr18Ni9 캐싱은 구성 요소 코드에 속하지 않는다고 생각합니다. 데이터를 가져 와서 뷰에 바인딩하는 것이 매우 간단한 무언가를 과도하게 엔지니어링하게됩니다. 캐싱은 이미 브라우저에서 구현되었습니다. 서버에서 올바른 헤더를 보내서이를 활용할 수 있습니다. 여기에 간단한 설명이 있습니다 : csswizardry.com/2019/03/cache-control-for-civilians . 인터넷에 연결하지 않아도 웹 사이트가 작동하도록하는 ServiceWorkers를 살펴볼 수도 있습니다.
Anastazy

61

상태 변경을 청취하기 위해 구성 요소 감시자를 사용해서는 안됩니다. getters 함수를 사용한 다음 컴포넌트 내부에 맵핑하는 것이 좋습니다.

import { mapGetters } from 'vuex'

export default {
  computed: {
    ...mapGetters({
      myState: 'getMyState'
    })
  }
}

당신의 상점에서 :

const getters = {
  getMyState: state => state.my_state
}

this.myState구성 요소에서 를 사용하여 상점의 변경 사항을들을 수 있어야합니다 .

https://vuex.vuejs.org/en/getters.html#the-mapgetters-helper


1
mapGetters를 구현하는 방법을 모르겠습니다. 예를 들어 주시겠습니까? 큰 도움이 될 것입니다. 나는 단지 지금 GONG 답변을 구현합니다. TY
Rbex

1
@Rbex "mapGetters"는 'vuex'라이브러리의 일부입니다. 구현할 필요가 없습니다.
Gabriel Robert

69
이 답변은 잘못되었습니다. 그는 실제로 계산 된 속성을 관찰해야합니다.
Juan

15
한 번 호출 된 getter는 해당 시점의 상태 만 검색합니다. 해당 속성이 다른 구성 요소의 상태 변경을 반영하도록하려면 해당 속성을 감시해야합니다.
C Tierney

3
왜 "구성 요소 감시자를 사용하여 상태 변경을 듣지 말아야합니까?" 다음은 상태에서 토큰을보고 싶을 때와 다른 페이지로 리디렉션하도록 변경되었을 때 생각할 수없는 예입니다. 그러니 몇 가지 경우가 있습니다. 아마 당신은 그것을 알고 더 많은 경험이 필요합니다.
Shlomi Levi

47

다음과 같이 간단합니다.

watch: {
  '$store.state.drawer': function() {
    console.log(this.$store.state.drawer)
  }
}

6
이것은 여기의 답변보다 더 직설적 인 광경입니다 ...이 작업에 반대하는 주장이 있습니까?
Inigo

19
너무 간단해서 js처럼 보이지 않습니다. js가 더 복잡해야합니다.
digout

1
그렇다면 더 function(n) { console.log(n); }
단순

2
슈퍼 쿨. 이 접근법의 단점에도 관심이 있습니다. 지금까지는 잘 작동하는 것 같습니다.
namero999

1
진심으로. 이것은 시계에서 계산되고 계산 된 함수 이름이 필요한 수락 된 답변보다 훨씬 낫습니다. 전문가가 왜 이런 식으로 그렇게하지 말아야하는지에 대해 논평 할 수 있습니까?
Exocentric

43

위에서 언급했듯이 상점에서 직접 변경 사항을 보는 것은 좋지 않습니다.

그러나 매우 드문 경우에 누군가에게 유용 할 수 있으므로이 답변을 남겨 두겠습니다. 다른 경우에는 @ gabriel-robert의 답변을 참조하십시오

를 통해이 작업을 수행 할 수 있습니다 state.$watch. created컴포넌트 의 (또는 이것을 실행 해야하는 곳) 메소드에 이것을 추가하십시오

this.$store.watch(
    function (state) {
        return state.my_state;
    },
    function () {
        //do something on data change
    },
    {
        deep: true //add this if u need to watch object properties change etc.
    }
);

자세한 내용은 https://vuex.vuejs.org/api/#watch


3
나는 국가를 직접 보는 것이 좋지 않다고 생각합니다. 우리는 게터를 사용해야합니다. vuex.vuejs.org/en/getters.html#the-mapgetters-helper
가브리엘 로버트

14
@GabrielRobert 나는 둘 다위한 장소가 있다고 생각합니다. 반응 적으로 템플릿 조건을 기반으로 변경해야하는 경우 mapState와 함께 계산 된 값을 사용하는 것이 좋습니다. 그러나 그렇지 않으면 구성 요소의 흐름 제어와 마찬가지로 전체 시계가 필요합니다. 당신은 맞습니다, 당신은 평범한 구성 요소 감시자를 사용해서는
안되지만

14
모두가 그것을 언급하지만 아무도 이유를 말하지 않습니다! 변경시 DB와 자동 동기화되는 vuex 스토어를 구축하려고합니다. 가게의 감시자가 가장 마찰이없는 방법이라고 생각합니다! 어떻게 생각해? 아직도 좋은 생각이 아니십니까?
mesqueeb 2016 년

16

나는 asker가 Vuex와 함께 시계를 사용하고 싶다고 생각합니다.

this.$store.watch(
      (state)=>{
        return this.$store.getters.your_getter
      },
      (val)=>{
       //something changed do something

      },
      {
        deep:true
      }
      );

13

이것은 게터에 대한 문제를 해결할 수없고 실제로 비가 아닌 제 3 자와 대화하기 위해 실제로 감시자가 필요한 모든 사람들을위한 것입니다 ( 감시자 를 사용할 때 Vue Watchers 참조 ).

Vue 구성 요소의 감시자 및 계산 된 값도 계산 된 값에서 작동합니다. 따라서 vuex와 다르지 않습니다.

import { mapState } from 'vuex';

export default {
    computed: {
        ...mapState(['somestate']),
        someComputedLocalState() {
            // is triggered whenever the store state changes
            return this.somestate + ' works too';
        }
    },
    watch: {
        somestate(val, oldVal) {
            // is triggered whenever the store state changes
            console.log('do stuff', val, oldVal);
        }
    }
}

로컬 및 글로벌 상태를 결합하는 것만이라면 mapState의 문서 도 예제를 제공합니다.

computed: {
    ...mapState({
        // to access local state with `this`, a normal function must be used
        countPlusLocalState (state) {
          return state.count + this.localCount
        }
    }
})

좋은 해킹이지만 너무 지루합니다.
Martian2049

2
문서에 있으면 해킹이 아닙니다. 그러나 그것은 vue / vuex에 대한 찬반론도 아닙니다
dube

8

typescript를 사용하면 다음을 수행 할 수 있습니다.

import { Watch } from "vue-property-decorator";

..

@Watch("$store.state.something")
private watchSomething() {
   // use this.$store.state.something for access
   ...
}


왜 이것이 정확하게 다운 보트 되었습니까? 해결책이 vue-class-component를위한 것이고 TO가 오래된 vue-class 스타일을 요구했기 때문입니까? 나는 전자가 바람직하다고 생각합니다. 어쩌면 @Zhang Sol은 소개에서 언급 할 수 있습니다. 이것은 vue-class-component에 대한 것입니까?
JackLeEmmerdeur

: 참고 있는지 이유를 타이프의 장식이 하나 간단 같은 VUE 기본 솔루션으로 바람직 할 것 stackoverflow.com/a/56461539/3652783
yann_yinn

6

값 변경을보고 설정하여 상점 변수 의 로컬 상태 를 작성하십시오 . form-input v-model 의 로컬 변수 변경으로 인해 store 변수가 직접 변경되지 않습니다 .

data() {
  return {
    localState: null
  };
 },
 computed: {
  ...mapGetters({
    computedGlobalStateVariable: 'state/globalStateVariable'
  })
 },
 watch: {
  computedGlobalStateVariable: 'setLocalState'
 },
 methods: {
  setLocalState(value) {
   this.localState = Object.assign({}, value);
  }
 }

5

상점 변경 사항을 보는 가장 좋은 방법 mapGetters은 Gabriel이 말한대로 사용 하는 것입니다. 그러나 당신이 그것을 할 수없는 경우가 있습니다 mapGetters: 예 를 들어 매개 변수를 사용하여 상점에서 무언가를 얻고 싶습니다 :

getters: {
  getTodoById: (state, getters) => (id) => {
    return state.todos.find(todo => todo.id === id)
  }
}

이 경우을 사용할 수 없습니다 mapGetters. 대신 다음과 같은 작업을 시도 할 수 있습니다.

computed: {
    todoById() {
        return this.$store.getters.getTodoById(this.id)
    }
}

그러나 불행히도 변경 todoById 된 경우에만 업데이트됩니다this.id

이러한 경우 구성 요소 업데이트를 원할 경우 this.$store.watch Gong에서 제공 하는 솔루션을 사용하십시오 . 또는 구성 요소를 의식적으로 처리하고 업데이트 this.id가 필요할 때 업데이트하십시오 todoById.


감사합니다. 그것은 정확히 나의 유스 케이스이며, 실제로 게터를 볼 수 없습니다 ...
pscheit

5

당신은 단순히하려면 시청 상태 속성 과 그 속성의 변화에 따라 구성 요소 내에서의 역할을 다음 아래의 예를 참조하십시오.

에서 store.js:

export const state = () => ({
 isClosed: false
})
export const mutations = {
 closeWindow(state, payload) {
  state.isClosed = payload
 }
}

이 시나리오에서는 다음 boolean과 같이 응용 프로그램의 다른 위치에서 변경할 상태 속성을 만듭니다 .

this.$store.commit('closeWindow', true)

이제 다른 구성 요소에서 해당 상태 속성을보고 로컬 속성을 변경 해야하는 경우 mounted후크에 다음을 작성합니다 .

mounted() {
 this.$store.watch(
  state => state.isClosed,
  (value) => {
   if (value) { this.localProperty = 'edit' }
  }
 )
}

먼저 state 속성에 감시자를 설정 한 다음 콜백 함수 value에서 해당 속성을 사용하여 를 변경합니다 localProperty.

도움이 되길 바랍니다!


3

상태 수준을보고 싶다면 다음과 같이 할 수 있습니다.

let App = new Vue({
    //...
    store,
    watch: {
        '$store.state.myState': function (newVal) {
            console.log(newVal);
            store.dispatch('handleMyStateChange');
        }
    },
    //...
});

이 동작은 해당 구성 요소를 사용하는 경우에만 작동하므로 구성 요소의 상태 작업 store.state별 변경 을 처리하는 것은 좋지 않습니다 dispatch. 또한 무한 루프로 끝날 수 있습니다. 시계하는 store.state당신이 구성 요소 또는 기반으로 어떤 행동해야 페이지가있는 경우, 예를 들어, 거의 사용을 변경 store.state하는 경우에만 당신이 비교할 수있는 mapState를 계산 사용하여 처리 할 수 없습니다 변경된 newValueoldValue
Januartha

@Januartha이 문제에 대한 당신의 제안은 무엇입니까?
Billal Begueradj

@ 앤디 물론 작동합니다. 전화 한 이유를 알고 싶 store.dispatch습니까? store.mutations`에 store.state대한 변경 을 처리 하려면 store' why not handle it inside ?
Januartha

@BillalBEGUERADJ 전 dube 솔루션이 더 깨끗해
졌습니다

@Januartha, 돌연변이를하기 전에 발생하는 아약스 호출이있을 수 있기 때문에 내가 store.dispatch먼저 사용하는 이유 입니다. 예를 들어, $store.state.country변경 될 때마다 한 국가에서 모든 도시를 가져오고 싶습니다 . 그래서이를 감시자에 추가합니다. 그런 다음 아약스 호출을 store.dispatch('fetchCities')작성합니다 : 내가 쓴 글 :axios.get('cities',{params:{country: state.country }}).then(response => store.commit('receiveCities',response) )
Andy

2

Vuex 조치 , getter , 계산 된 특성감시자 를 조합 하여 Vuex 상태 값의 변경 사항을 청취 할 수 있습니다.

HTML 코드 :

<div id="app" :style='style'>
  <input v-model='computedColor' type="text" placeholder='Background Color'>
</div>

자바 스크립트 코드 :

'use strict'

Vue.use(Vuex)

const { mapGetters, mapActions, Store } = Vuex

new Vue({
    el: '#app',
  store: new Store({
    state: {
      color: 'red'
    },
    getters: {
      color({color}) {
        return color
      }
    },
    mutations: {
      setColor(state, payload) {
        state.color = payload
      }
    },
    actions: {
      setColor({commit}, payload) {
        commit('setColor', payload)
      }
    }
  }),
  methods: {
    ...mapGetters([
        'color'
    ]),
    ...mapActions([
        'setColor'
    ])
  },
  computed: {
    computedColor: {
        set(value) {
        this.setColor(value)
      },
      get() {
        return this.color()
      }
    },
    style() {
        return `background-color: ${this.computedColor};`
    }
  },
  watch: {
    computedColor() {
        console.log(`Watcher in use @${new Date().getTime()}`)
    }
  }
})

JSFiddle 데모를 참조하십시오 .


1

상점 돌연변이를 구독 할 수도 있습니다.

store.subscribe((mutation, state) => {
  console.log(mutation.type)
  console.log(mutation.payload)
})

https://vuex.vuejs.org/api/#subscribe


컴포넌트의 beforeMount () 훅에서 이것을 발생시키고 if 문으로 들어오는 돌연변이를 필터링 할 수 있습니다. 예 : if (mutation.type == "names / SET_NAMES") {... 무언가를하세요}
Alejandro

1

컴포넌트 내부에서 계산 된 함수를 작성하십시오.

computed:{
  myState:function(){
    return this.$store.state.my_state; // return the state value in `my_state`
  }
}

이제 계산 된 함수 이름을 볼 수 있습니다.

watch:{
  myState:function(newVal,oldVal){
    // this function will trigger when ever the value of `my_state` changes
  }
}

vuex상태 에서 변경 한 내용은 my_state계산 된 기능에 반영되어 myState감시 기능을 트리거합니다.

상태 my_state에 중첩 된 데이터가 있으면 handler옵션이 더 도움이됩니다.

watch:{
  myState:{
    handler:function(newVal,oldVal){
      // this function will trigger when ever the value of `my_state` changes
    },
    deep:true
  }
}

이것은 상점의 모든 중첩 값을 감시합니다 my_state.


0

vue 구성 요소에서 mapState를 사용하여 상점에서 상태를 가져 오도록 지시 할 수도 있습니다.

컴포넌트에서 :

computed: mapState([
  'my_state'
])

my_state상점의 변수는 어디에 있습니까 ?


0

====== store =====
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    showRegisterLoginPage: true,
    user: null,
    allitem: null,
    productShow: null,
    userCart: null
  },
  mutations: {
    SET_USERS(state, payload) {
      state.user = payload
    },
    HIDE_LOGIN(state) {
      state.showRegisterLoginPage = false
    },
    SHOW_LOGIN(state) {
      state.showRegisterLoginPage = true
    },
    SET_ALLITEM(state, payload) {
      state.allitem = payload
    },
    SET_PRODUCTSHOW(state, payload) {
      state.productShow = payload
    },
    SET_USERCART(state, payload) {
      state.userCart = payload
    }
  },
  actions: {
    getUserLogin({ commit }) {
      axios({
        method: 'get',
        url: 'http://localhost:3000/users',
        headers: {
          token: localStorage.getItem('token')
        }
      })
        .then(({ data }) => {
          // console.log(data)
          commit('SET_USERS', data)
        })
        .catch(err => {
          console.log(err)
        })
    },
    addItem({ dispatch }, payload) {
      let formData = new FormData()
      formData.append('name', payload.name)
      formData.append('file', payload.file)
      formData.append('category', payload.category)
      formData.append('price', payload.price)
      formData.append('stock', payload.stock)
      formData.append('description', payload.description)
      axios({
        method: 'post',
        url: 'http://localhost:3000/products',
        data: formData,
        headers: {
          token: localStorage.getItem('token')
        }
      })
        .then(({ data }) => {
          // console.log('data hasbeen created ', data)
          dispatch('getAllItem')
        })
        .catch(err => {
          console.log(err)
        })
    },
    getAllItem({ commit }) {
      axios({
        method: 'get',
        url: 'http://localhost:3000/products'
      })
        .then(({ data }) => {
          // console.log(data)
          commit('SET_ALLITEM', data)
        })
        .catch(err => {
          console.log(err)
        })
    },
    addUserCart({ dispatch }, { payload, productId }) {
      let newCart = {
        count: payload
      }
      // console.log('ini dari store nya', productId)

      axios({
        method: 'post',
        url: `http://localhost:3000/transactions/${productId}`,
        data: newCart,
        headers: {
          token: localStorage.getItem('token')
        }
      })
        .then(({ data }) => {
          dispatch('getUserCart')
          // console.log('cart hasbeen added ', data)
        })
        .catch(err => {
          console.log(err)
        })
    },
    getUserCart({ commit }) {
      axios({
        method: 'get',
        url: 'http://localhost:3000/transactions/user',
        headers: {
          token: localStorage.getItem('token')
        }
      })
        .then(({ data }) => {
          // console.log(data)
          commit('SET_USERCART', data)
        })
        .catch(err => {
          console.log(err)
        })
    },
    cartCheckout({ commit, dispatch }, transactionId) {
      let count = null
      axios({
        method: 'post',
        url: `http://localhost:3000/transactions/checkout/${transactionId}`,
        headers: {
          token: localStorage.getItem('token')
        },
        data: {
          sesuatu: 'sesuatu'
        }
      })
        .then(({ data }) => {
          count = data.count
          console.log(count, data)

          dispatch('getUserCart')
        })
        .catch(err => {
          console.log(err)
        })
    },
    deleteTransactions({ dispatch }, transactionId) {
      axios({
        method: 'delete',
        url: `http://localhost:3000/transactions/${transactionId}`,
        headers: {
          token: localStorage.getItem('token')
        }
      })
        .then(({ data }) => {
          console.log('success delete')

          dispatch('getUserCart')
        })
        .catch(err => {
          console.log(err)
        })
    }
  },
  modules: {}
})


1
사이트에 오신 것을 환영합니다. 코드 스 니펫 만 넣으면 충분하지 않습니다. 코드에 대한 설명을 제공해주세요.
pgk

0

나는이 방법을 사용했으며 작동합니다.

store.js :

const state = {
  createSuccess: false
};

mutations.js

[mutations.CREATE_SUCCESS](state, payload) {
    state.createSuccess = payload;
}

actions.js

async [mutations.STORE]({ commit }, payload) {
  try {
    let result = await axios.post('/api/admin/users', payload);
    commit(mutations.CREATE_SUCCESS, user);
  } catch (err) {
    console.log(err);
  }
}

getters.js

isSuccess: state => {
    return state.createSuccess
}

그리고 상점의 상태를 사용하는 구성 요소에서 :

watch: {
    isSuccess(value) {
      if (value) {
        this.$notify({
          title: "Success",
          message: "Create user success",
          type: "success"
        });
      }
    }
  }

사용자가 양식을 제출하면 CREATE_SUCCESS 작성 성공 후 조치 STORE 가 호출됩니다. 후 그 이후 돌연변이가 커미트됩니다. 돌려 createSuccess를 사실이며, 구성 요소, 감시자는 값이 변경 및 트리거 통보했다 볼 수 있습니다.

isSuccessgetters.js에 선언 한 이름과 일치해야합니다.

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