我一起使用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
如何在我的vuejs组件中观看store.my_state
?
答案 0 :(得分:109)
比方说,你有一篮水果, 每次你从篮子里添加或删除水果,你 想要(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, yaay!`)
}
}
}
</script>
请注意,watch
对象中函数的名称必须与computed
对象中函数的名称匹配。在上面的示例中,名称为count
。
监视属性的新旧值将作为参数传递给监视回调(计数函数)。
篮子商店看起来像这样:
果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
}
}
// Obvously you would need some mutations and actions,
// but to make example cleaner I'll skip this part.
})
export default basket
您可以在以下资源中阅读更多内容:
答案 1 :(得分:62)
您不应该使用组件的观察者来听取状态变化。我建议您使用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
答案 2 :(得分:33)
如上所述,直接在商店中观看更改
并不是一个好主意但在一些非常罕见的情况下,它可能对某人有用,所以我会留下这个答案。对于其他情况,请参阅@ 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/en/api.html#vuex-store-instance-methods
答案 3 :(得分:12)
我认为提问者想要使用Vuex手表。
this.$store.watch(
(state)=>{
return this.$store.getters.your_getter
},
(val)=>{
//something changed do something
},
{
deep:true
}
);
答案 4 :(得分:7)
这适用于所有无法用吸气剂解决问题但真正需要观察者的人,例如:与非第三方的东西交谈(关于何时使用观察者,请参阅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
}
}
})
答案 5 :(得分:4)
为商店变量创建本地状态。 这样,对于 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);
}
}
答案 6 :(得分:4)
在组件内部,创建一个计算函数
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
中的所有嵌套值。
答案 7 :(得分:4)
观看商店变化的最佳方式是使用Error:(17, 0) Could not find method maven() for arguments [build_2rpdxydj6arlyq4m2v87kde3g$_run_closure1$_closure2$_closure3@70ca8e63] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.
,正如加布里埃尔所说。
但有一种情况是,您无法通过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)
}
}
will be updated only if this.id
is changed
如果您希望在这种情况下进行组件更新,请使用todoById
solution provided by Gong。或者有意识地处理您的组件,并在需要更新this.$store.watch
时更新this.id
。
答案 8 :(得分:2)
这很简单:
watch: {
'$store.state.drawer': function() {
console.log(this.$store.state.drawer)
}
}
答案 9 :(得分:1)
您可以结合使用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()}`)
}
}
})
答案 10 :(得分:1)
当你想在州一级观看时,可以这样做:
let App = new Vue({
//...
store,
watch: {
'$store.state.myState': function (newVal) {
console.log(newVal);
store.dispatch('handleMyStateChange');
}
},
//...
});
答案 11 :(得分:1)
You could also subscribe to the store mutations:
store.subscribe((mutation, state) => {
console.log(mutation.type)
console.log(mutation.payload)
})
答案 12 :(得分:1)
如果您只是想监视一个州财产,然后根据该财产的更改在主管内行事,则请参见以下示例。
在 @Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
baseViewFragmentImageView = inflater.inflate(R.layout.fragment_image_view, container, false);
unbinder = ButterKnife.bind(this, baseViewFragmentImageView);
getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
if (bundle != null) {
iv.setPhotoUri(Uri.fromFile(new File(bundle.getString("ImageFilePath"))));
iv.setTransitionName(bundle.getString("transition_name"));
ViewCompat.setTransitionName(iv, bundle.getString("transition_name"));
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
TransitionSet transitionSet = new TransitionSet();
transitionSet.addTransition(new ChangeBounds());
transitionSet.addTarget(iv);
getDialog().getWindow().setSharedElementEnterTransition(transitionSet);
this.setSharedElementReturnTransition(new ImageTransition());
}
return baseViewFragmentImageView;
}
中:
store.js
在这种情况下,我将创建一个export const state = () => ({
isClosed: false
})
export const mutations = {
closeWindow(state, payload) {
state.isClosed = payload
}
}
状态属性,该属性将在应用程序的不同位置进行更改,如下所示:
boolean
现在,如果我需要在其他组件中观察该state属性,然后更改local属性,则可以在this.$store.commit('closeWindow', true)
钩子中编写以下内容:
mounted
首先,我要在state属性上设置观察者,然后在回调函数中使用该属性的mounted() {
this.$store.watch(
state => state.isClosed,
(value) => {
if (value) { this.localProperty = 'edit' }
}
)
}
来更改value
。
希望对您有帮助!
答案 13 :(得分: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: {}
})
答案 14 :(得分: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"
});
}
}
}
用户提交表单时,将调用操作 STORE ,创建成功后,将进行 CREATE_SUCCESS 突变。将 createSuccess 设置为true,然后在组件中,观察者将看到值已更改并触发通知。
isSuccess 应该与您在 getters.js
中声明的名称匹配答案 15 :(得分:0)
您还可以在vue组件中使用mapState来指示从商店获取状态。
在您的组件中:
computed: mapState([
'my_state'
])
其中my_state
是商店的变量。
答案 16 :(得分:0)
我尽一切努力使它正常工作。
我发现由于某种原因,对$store
中的对象所做的更改不一定会触发.watch
方法。我的解决方法是
state
中创建一个递增计数器以用作标志,这样做在观看时会将更改传播到组件$store.mutators
中创建一个方法来更改复杂数据集并增加计数器标记$store.state
标志中的更改。检测到更改后,请从$store.state
复杂数据集中更新本地相关的反应性更改$store.state
方法对$store.mutators
的数据集进行更改这是这样实现的:
商店
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>
答案 17 :(得分:0)
字符串状态下的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
}
},
答案 18 :(得分:-1)
如果您使用打字稿,则可以:
import { Watch } from "vue-property-decorator";
..
@Watch("$store.state.something")
private watchSomething() {
// use this.$store.state.something for access
...
}