如何从 vuex 中查看存储值?
How to watch store values from vuex?
我同时使用 vuex
和 vuejs 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
?
如上所述,直接在商店中观看变化并不是个好主意
但在极少数情况下它可能对某些人有用,所以我会留下这个答案。对于其他情况,请参阅@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.
}
);
您不应该使用组件的观察器来监听状态变化。我建议您使用 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) 想以某种奇特的方式收到水果数量的通知...
水果数-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
.
watched 的新值和旧值 属性 将作为参数传递给 watch 回调(计数函数)。
购物篮店可能看起来像这样:
水果-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 与 Vuex 一起使用。
this.$store.watch(
(state)=>{
return this.$store.getters.your_getter
},
(val)=>{
//something changed do something
},
{
deep:true
}
);
观察商店变化的最佳方式是使用 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
will be updated only if this.id
is changed
如果您希望在这种情况下更新组件,请使用 this.$store.watch
solution provided by Gong。或者有意识地处理你的组件,当你需要更新todoById
.
时更新this.id
这适用于所有无法使用 getter 解决问题并且实际上确实需要观察者的人,例如与非 Vue 第三方对话(参见 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's doc也提供了一个例子:
computed: {
...mapState({
// to access local state with `this`, a normal function must be used
countPlusLocalState (state) {
return state.count + this.localCount
}
}
})
您可以结合使用 Vuex actions, getters, computed properties and watchers 来监听 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()}`)
}
}
})
如果你想在州级观看,可以这样做:
let App = new Vue({
//...
store,
watch: {
'$store.state.myState': function (newVal) {
console.log(newVal);
store.dispatch('handleMyStateChange');
}
},
//...
});
通过观察和设置值的变化,为您的商店变量创建一个本地状态。
这样 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);
}
}
您还可以订阅商店变更:
store.subscribe((mutation, state) => {
console.log(mutation.type)
console.log(mutation.payload)
})
如果你使用打字稿,那么你可以:
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' }
}
)
}
首先,我在状态 属性 上设置一个观察者,然后在回调函数中我使用 属性 的 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
}
并且在您使用商店状态的组件中:
watch: {
isSuccess(value) {
if (value) {
this.$notify({
title: "Success",
message: "Create user success",
type: "success"
});
}
}
}
当用户提交表单时,将调用操作STORE,创建成功后,CREATE_SUCCESS 突变被提交.转 createSuccess 为真,在组件中,watcher 将看到值已更改并触发通知。
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
}
},
在计算中使用你的 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的格式。
希望你今天过得愉快。
我同时使用 vuex
和 vuejs 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
?
如上所述,直接在商店中观看变化并不是个好主意
但在极少数情况下它可能对某些人有用,所以我会留下这个答案。对于其他情况,请参阅@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.
}
);
您不应该使用组件的观察器来监听状态变化。我建议您使用 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) 想以某种奇特的方式收到水果数量的通知...
水果数-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
.
watched 的新值和旧值 属性 将作为参数传递给 watch 回调(计数函数)。
购物篮店可能看起来像这样:
水果-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 与 Vuex 一起使用。
this.$store.watch(
(state)=>{
return this.$store.getters.your_getter
},
(val)=>{
//something changed do something
},
{
deep:true
}
);
观察商店变化的最佳方式是使用 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
will be updated only if this.id
is changed
如果您希望在这种情况下更新组件,请使用 this.$store.watch
solution provided by Gong。或者有意识地处理你的组件,当你需要更新todoById
.
this.id
这适用于所有无法使用 getter 解决问题并且实际上确实需要观察者的人,例如与非 Vue 第三方对话(参见 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's doc也提供了一个例子:
computed: {
...mapState({
// to access local state with `this`, a normal function must be used
countPlusLocalState (state) {
return state.count + this.localCount
}
}
})
您可以结合使用 Vuex actions, getters, computed properties and watchers 来监听 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()}`)
}
}
})
如果你想在州级观看,可以这样做:
let App = new Vue({
//...
store,
watch: {
'$store.state.myState': function (newVal) {
console.log(newVal);
store.dispatch('handleMyStateChange');
}
},
//...
});
通过观察和设置值的变化,为您的商店变量创建一个本地状态。 这样 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);
}
}
您还可以订阅商店变更:
store.subscribe((mutation, state) => {
console.log(mutation.type)
console.log(mutation.payload)
})
如果你使用打字稿,那么你可以:
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' }
}
)
}
首先,我在状态 属性 上设置一个观察者,然后在回调函数中我使用 属性 的 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
}
并且在您使用商店状态的组件中:
watch: {
isSuccess(value) {
if (value) {
this.$notify({
title: "Success",
message: "Create user success",
type: "success"
});
}
}
}
当用户提交表单时,将调用操作STORE,创建成功后,CREATE_SUCCESS 突变被提交.转 createSuccess 为真,在组件中,watcher 将看到值已更改并触发通知。
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
}
},
在计算中使用你的 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的格式。 希望你今天过得愉快。