我同时使用 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
?
例如,假设您有一篮水果,每次从篮子中添加或移除水果时,您希望 (1) 显示有关水果数量的信息,但您还 (2) 希望收到通知以某种花哨的方式数水果……
水果计数组件.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
。
监视属性的新旧值将作为参数传递给监视回调(计数函数)。
篮子商店可能如下所示:
水果篮.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
您可以在以下资源中阅读更多内容:
计算属性和观察者
API 文档:计算
API 文档:观看
它很简单:
watch: {
'$store.state.drawer': function() {
console.log(this.$store.state.drawer)
}
}
如果商店在一个模块中,请使用:
'$store.state.myModule.drawer'
对于嵌套文件,请使用:
'$store.state.fileOne.fileTwo.myModule.drawer'
function(n) { console.log(n); }
会更简单
'$store.state.module.something'
你不应该使用组件的观察者来监听状态变化。我建议您使用 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
如上所述,直接在商店中查看更改并不是一个好主意
但在一些非常罕见的情况下,它可能对某人有用,所以我会留下这个答案。对于其他情况,请参阅@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
我认为提问者想将手表与 Vuex 一起使用。
this.$store.watch(
(state)=>{
return this.$store.getters.your_getter
},
(val)=>{
//something changed do something
},
{
deep:true
}
);
this
访问 Vue 实例的地方。比如,一个 created
钩子。基本上,您需要的任何组件
这适用于所有无法使用 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
}
}
})
我确实尝试了一切以使其正常工作。
理论
我发现由于某种原因,从 $store
对对象的更改不一定会触发 .watch
方法。我的解决方法是
Store 创建一个复杂的数据集,它应该但不将更改传播到组件 在状态中创建一个递增计数器以充当标志,在监视时将更改传播到组件 在 $store.mutators 中创建一个方法以更改复杂数据集并增加计数器标志
创建一个复杂的数据集,该数据集应该但不会将更改传播到组件
在状态中创建一个递增计数器以充当标志,它会在监视时将更改传播到组件
在 $store.mutators 中创建一个方法来更改复杂数据集并增加计数器标志
组件监视 $store.state 标志的变化。当检测到更改时,从 $store.state 复杂数据集中更新本地相关的响应式更改 使用我们的 $store.mutators 方法对 $store.state 的数据集进行更改
注意 $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, // 对 objectData 的更改会在添加键时触发监视, // 但不会在修改值时触发? votes: { 'people ': 0, 'companies': 0, 'total': 0, }, }, 突变:{ 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() { // 在本地克隆相关数据 this.votesForPeople = this.$store .state.votes.people this.votesForCompanies = this.$store.state.votes.companies } } },方法:{ vote(event) { if (this.pendingVote) { this.$store.commit('vote', this.pendingVote) } } } })
如果您只是想观察一个状态属性,然后在组件内根据该属性的变化采取行动,请参见下面的示例。
在 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
。
我希望它有帮助!
如果您使用打字稿,那么您可以:
从“vue-property-decorator”导入{ Watch }; .. @Watch("$store.state.something") private watchSomething() { // 使用 this.$store.state.something 进行访问 ... }
通过观察和设置值变化来创建存储变量的本地状态。这样表单输入 v-model 的局部变量更改不会直接改变存储变量。
data() {
return {
localState: null
};
},
computed: {
...mapGetters({
computedGlobalStateVariable: 'state/globalStateVariable'
})
},
watch: {
computedGlobalStateVariable: 'setLocalState'
},
methods: {
setLocalState(value) {
this.localState = Object.assign({}, value);
}
}
在计算中使用你的getter然后观察它并做你需要的
computed:{
...mapGetters(["yourGetterName"])
},
watch: {
yourGetterName(value) {
// Do something you need
},
}
在组件内部,创建一个计算函数
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
中的所有嵌套值。
观察商店变化的最佳方式是使用 Gabriel 所说的 mapGetters
。但在某些情况下,您无法通过 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
。
return this.$store.getters.getTodoById({id: this.id})
不确定是否是导致 this 不响应的对象......但它不是响应的。
您还可以订阅存储突变:
store.subscribe((mutation, state) => {
console.log(mutation.type)
console.log(mutation.payload)
})
https://vuex.vuejs.org/api/#subscribe
当您想在状态级别观看时,可以通过以下方式完成:
let App = new Vue({
//...
store,
watch: {
'$store.state.myState': function (newVal) {
console.log(newVal);
store.dispatch('handleMyStateChange');
}
},
//...
});
dispatch
状态操作的 store.state
更改不是一个好主意,因为此行为仅在您使用该组件时才有效。你也可能以无限循环结束。观察到 store.state
更改很少使用,例如,如果您有一个组件或页面应该根据 store.state
执行某些操作更改,而仅在您无法比较 newValue
与 oldValue
的情况下使用计算的 mapState 无法处理
store.dispatch
?如果您想处理 store' why not handle it inside
store.mutations` 的 store.state
更改?
store.dispatch
的原因。例如,我想在 $store.state.country
更改时从一个国家/地区获取所有城市,因此我将其添加到观察者。然后我会写一个 ajax 调用:在 store.dispatch('fetchCities')
我写:axios.get('cities',{params:{country: state.country }}).then(response => store.commit('receiveCities',response) )
您可以使用 Vuex actions、getters、computed properties 和 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()}`)
}
}
})
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
}
},
你也可以在你的 vue 组件中使用 mapState 来直接从 store 中获取状态。
在您的组件中:
computed: mapState([
'my_state'
])
其中 my_state
是来自商店的变量。
====== store ===== import Vue from 'vue' import Vuex from 'vuex' import axios from 'axios' Vue.use(Vuex) export default new Vuex.Store({ state: { showRegisterLoginPage: true , 用户: null, allitem: null, productShow: null, userCart: null }, 突变: { 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 } },操作:{ 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.fi le) 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 has been 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 has已添加 ', 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}`,标题:{ token: localStorage.getItem('token') },数据:{ sesuatu: 'sesuatu' } }) .then(({ data }) => { count = data.count console.log(count, data) dispatch('getUserCart') }) .catch(err => { console.log(err) }) }, deleteTransactions({ dispatch }, transactionId) { axios( { 方法:'delete',url:`http://localhost:3000/transactions/${transactionId}`,标题:{ token: localStorage.getItem('token') } }) .then(({ data }) => { console.log('成功删除') dispatch('getUserCart') }) .catch(err => { console.log(e rr) }) } },模块:{} })
我用这种方式,它的工作原理:
商店.js:
const state = {
createSuccess: false
};
突变.js
[mutations.CREATE_SUCCESS](state, payload) {
state.createSuccess = payload;
}
动作.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 设为 true,并且在组件中,watcher 将看到 value 已更改并触发通知。
isSuccess 应该与您在 getters.js 中声明的名称匹配
也可以用 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 的格式。希望你有一个美好的一天。
不定期副业成功案例分享
watch
操作应该分为两个步骤时我应该做什么:1)首先,检查所需数据是否被缓存以及它是否只是返回缓存的数据; 2) 如果缓存失败,我需要一个异步 ajax 操作来获取数据,但这似乎是action
的工作。希望我的问题有意义,谢谢!