vue重度使用vuex和watch的解决方法

项目中重度依赖vuex和watch,组件化非常方便,但是组件之间的数据、状态共享一直非常难处理,所以在使用了vuex后便重度依赖,并且大量使用了watch,在vue官网中一直不推荐使用watch,而是使用computed代替,但是现在也找不到一个合适的方法,下面用一个例子展示。

a页面和b页面,b页面中有5段文字,点击文字后,a页面的数据会加上选择的数据,一直累加。类似
图片描述

现在的解决方法是,每次点击文字,通过commit修改state的变量,a页面使用watch监听state变量的变化,如果改变则添加上新的数据。

代码使用了decorator和typescript

//a页面的监听
@Watch("content")
  ChangeContent(x: string) {
    if (!x) return;
    this.text += this.content;
  }

//b页面发送
 ChooseText(x: string) {
    this.ChangeContent(x);
  }

//state
content:null

//mutation
ChangeContent(state,x){
    state.content=x
}
其中代码有部分省略,但是无关紧要。

其中方法还有部分逻辑没有写,比如2次选中相同数字,watch是不会执行。现在想知道除了使用watch能监听到变化,并执行相应逻辑,还有没有其他的方法。例如computed。这只是其中的一小部分,以后碰到像是这样的问题,代码的设计思路是什么。谢谢。

阅读 10.2k
5 个回答

你这种需求,state 里存的应该是个数组,里边是被点击的元素(这里就可以直接做去重了)。

然后就不需要 watch 了,因为 state 里就是被点击的所有元素,计算属性中直接根据这个数组计算出文本返回即可。

感觉你没有理解vuex;

clipboard.png
基本上用了vuex来储存数据以后,watch这个方法根本不会用。
https://vuex.vuejs.org/zh/guide
你可以在看一下栗子,也许会有不一样的收获.

上述说的例子是个简单的父子组件通信,没必要用vuex

如果使用了vuex,因为store中state属性是响应式(reactive),可以在页面直接使用,所以一般情况下没必要使用watch了。为了使用方便,一般会用mapState或mapGetters,将state的属性映射为计算属性,见下文中组件A的代码。

父组件:

<template>
    <div>
        <component-a></component-a>
        <component-b></component-b>
    </div>
</template>
<script>
    import store from './store.js'
    import ComponentA from './ComponentA.vue'
    import ComponentB from './ComponentB.vue'

    export default {
        data () {
            return {}
        },
        store,
        components: {
            'component-a': ComponentA,
            'component-b': ComponentB
        }
    }
</script>

组件A:

<template>
    <div> Count is : {{count}} </div>
</template>

<script>
    import { mapState } from 'vuex'

    export default {
        name: 'ComponentA',
        data () {
            return {}
        },
        computed: mapState([
            'count'
        ])
    }
</script>

组件B

<template>
    <div>
        <ul v-for="i in 5">
            <li @click="increment(i)">{{i}}</li>  
        </ul>
    </div>
</template>

<script>
    export default {
        name: 'ComponentB',
        data () {
            return {}
        },
        methods: {
            increment(n) {
                console.log(n)
                this.$store.commit('increment', n)
            }
        }
    }
</script>

<style>
    ul > li {
        width: 100px;
        text-align: center;
        border-bottom: 1px solid gray;
        cursor: pointer;
        list-style: none;
    }
</style>

store.js

import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)

export default new Vuex.Store({
    strict: true,
    state: {
        count: 0
    },
    mutations: {
        increment(state, value) {
            state.count += value;
        }
    }
})
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏