如何从vuex观看存储值?

我同时使用了vuexvuejs 2

我是vuex的新手,我想观察一个store变量的变化。

我想在我的vue component中添加watch函数

这是我目前所拥有的:

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


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

我想知道在my_state中是否有任何变化

我如何在我的vuejs组件中观看store.my_state ?

381141 次浏览

如上所述,直接在商店中观察变化并不是一个好主意

但在一些非常罕见的情况下,它可能对某人有用,所以我将留下这个答案。其他情况请参见@gabriel-robert answer

你可以通过state.$watch来做到这一点。在component的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

你不应该使用组件的监视器来监听状态的变化。我建议您使用getter函数,然后在组件中映射它们。

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

您还可以在vue组件中使用mapState来直接从存储中获取状态。

在你的组件中:

computed: mapState([
'my_state'
])

其中my_state是来自存储的变量。

例如,你有一篮子水果, 每次你从篮子里添加或取出一个水果,你 想要(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

被监视属性的新值和旧值将作为参数传递到监视回调(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

你可以在以下资源中阅读更多:

我想提问者想用带有Vuex的手表。

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


},
{
deep:true
}
);
观察商店变化的最好方法是使用mapGetters,正如Gabriel所说。 但在某些情况下,你不能通过mapGetters来实现,例如,你想使用参数

从store中获取一些东西
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 龚提供的解决方案。或者有意识地处理你的组件,并在需要更新todoById时更新this.id

这是为所有不能用getter解决他们的问题并且实际上确实需要一个监视器的人准备的,例如与非vue第三方的东西对话(关于何时使用监视器,请参阅Vue观察家)。

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
}
}
})

你可以使用Vuex 行动getter计算属性观察人士的组合来监听Vuex状态值的变化。

HTML代码:

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

JavaScript代码:

'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演示

当你想要在状态级别上观看时,可以这样做:

let App = new Vue({
//...
store,
watch: {
'$store.state.myState': function (newVal) {
console.log(newVal);
store.dispatch('handleMyStateChange');
}
},
//...
});
通过观察和设置值变化来创建存储变量的本地状态。 这样,表单输入v模型的局部变量的变化不会直接改变存储变量.

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

你也可以订阅商店突变:

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

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

如果你使用typescript,那么你可以:

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


..


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

其实很简单:

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

如果存储在一个模块中,使用:

'$store.state.myModule.drawer'

对于嵌套文件,使用:

'$store.state.fileOne.fileTwo.myModule.drawer'

如果你只是想一个国家财产,然后在组件中根据该属性的变化进行相应的操作,那么请参阅下面的示例。

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

我希望这能有所帮助!

====== 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: {}
})

我用了这种方法,它很有效:

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
}

在你使用state from store的组件中:

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

当用户提交表单时,动作商店将被调用,创建成功后,在此之后提交CREATE_SUCCESS突变。Turn createSuccess为true,在组件中,监控器将看到值已更改并触发通知。

isSuccess应该与你在getters.js中声明的名称匹配

在组件内部,创建一个计算函数

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中的所有嵌套值。

我想尽了一切办法让它运转起来。

理论

我发现,出于某种原因,对$store对象的更改不一定会触发.watch方法。我的解决办法是

    <李>存储
    • 创建一个复杂的数据集,其中应该将更改传播到组件
    • state中创建一个递增计数器作为标志,当监视时,将更改传播到组件
    • $store.mutators中创建一个方法来更改复杂的数据集并增加计数器标志
    <李>组件
    • 注意$store.state标志的变化。当检测到更改时,从$store.state复杂数据集中更新本地相关的响应性更改
    • 使用$store.mutators方法对$store.state的数据集进行更改

实现

它的实现是这样的:

商店

let store = Vuex.Store({
state: {
counter: 0,
data: { someKey: 0 }
},
mutations: {
updateSomeKey(state, value) {
update the state.data.someKey = value;
state.counter++;
}
}
});

组件

  data: {
dataFromStoreDataSomeKey: null,
someLocalValue: 1
},
watch: {
'$store.state.counter': {
immediate: true,
handler() {
// update locally relevant data
this.someLocalValue = this.$store.state.data.someKey;
}
}
},
methods: {
updateSomeKeyInStore() {
this.$store.commit('updateSomeKey', someLocalValue);
}

可运行演示

这很复杂,但基本上在这里我们正在观察一个要更改的标志,然后更新本地数据以反映存储在$state中的对象的重要更改

Vue.config.devtools = false


const store = new Vuex.Store({
state: {
voteCounter: 0,
// changes to objectData trigger a watch when keys are added,
// but not when values are modified?
votes: {
'people': 0,
'companies': 0,
'total': 0,
},
},
mutations: {
vote(state, position) {
state.votes[position]++;
state.voteCounter++;
}
},
});




app = new Vue({
el: '#app',
store: store,
data: {
votesForPeople: null,
votesForCompanies: null,
pendingVote: null,
},
computed: {
totalVotes() {
return this.votesForPeople + this.votesForCompanies
},
peoplePercent() {
if (this.totalVotes > 0) {
return 100 * this.votesForPeople / this.totalVotes
} else {
return 0
}
},
companiesPercent() {
if (this.totalVotes > 0) {
return 100 * this.votesForCompanies / this.totalVotes
} else {
return 0
}
},
},
watch: {
'$store.state.voteCounter': {
immediate: true,
handler() {
// clone relevant data locally
this.votesForPeople = this.$store.state.votes.people
this.votesForCompanies = this.$store.state.votes.companies
}
}
},
methods: {
vote(event) {
if (this.pendingVote) {
this.$store.commit('vote', this.pendingVote)
}
}
}
  

})
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.12"></script>
<script src="https://unpkg.com/vuex@3.5.1/dist/vuex.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/css/bootstrap.min.css">




<div id="app">
<form @submit.prevent="vote($event)">
<div class="form-check">
<input
class="form-check-input"
type="radio"
name="vote"
id="voteCorps"
value="companies"
v-model="pendingVote"
>
<label class="form-check-label" for="voteCorps">
Equal rights for companies
</label>
</div>
<div class="form-check">
<input
class="form-check-input"
type="radio"
name="vote"
id="votePeople"
value="people"
v-model="pendingVote"
>
<label class="form-check-label" for="votePeople">
Equal rights for people
</label>
</div>
<button
class="btn btn-primary"
:disabled="pendingVote==null"
>Vote</button>
</form>
<div
class="progress mt-2"
v-if="totalVotes > 0"
>
<div class="progress-bar"
role="progressbar"
aria-valuemin="0"
:style="'width: ' + peoplePercent + '%'"
:aria-aluenow="votesForPeople"
:aria-valuemax="totalVotes"
>People</div>
<div
class="progress-bar bg-success"
role="progressbar"
aria-valuemin="0"
:style="'width: ' + companiesPercent + '%'"
:aria-valuenow="votesForCompanies"
:aria-valuemax="totalVotes"
>Companies</div>
</div>
</div>

Vue手表处于字符串状态

状态:

$store.state.local_store.list_of_data

内部组件

  watch: {
       

'$store.state.local_store.list_of_data':{//<----------your state call in string
handler(){
console.log("value changeing in party sales entry"); //<---do your stuff here
},
deep:true
}


},

在computed中使用你的getter,然后观察它并做你需要做的事情

    computed:{
...mapGetters(["yourGetterName"])
},
watch: {
yourGetterName(value) {
// Do something you need
},


}

你也可以使用debouncedWatch (vue使用函数)安全地观看它

  debouncedWatch(
lines,
() => {
console.log('changed');
},
500,
);

我使用的一个非常简单的计算方法是这样的。也许这对你有帮助。

  const variable_name = computed(
() => store.state.[name_of_state].property_name
);

你可以这样做的另一个版本是

computed: {
name () {
return this.$store.state.[name_of_state].property
}
}
这是从存储中访问getter的一种格式。