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를 계산 사용하여 처리 할 수 없습니다 변경된 newValue대oldValue
— 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를 사실이며, 구성 요소, 감시자는 값이 변경 및 트리거 통보했다 볼 수 있습니다.

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

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