vuex的5个属性值

Vuex基本使用及进阶

一、下载vuex依赖

npm install vuex -S

二、启用vuex

在src文件下创建store文件夹,在里面新建一个index.js文件,在文件里书写以下代码

import Vue from 'vue'
import Vuex from 'vuex'

// 启用vuex
Vue.use(Vuex)

// 声明vuex实例对象,创建四个对象属性
export default new Vuex.Store({
    state: {},
    mutations: {},
    actions: {},
    getters: {}
})

三、注入store

在main.js文件中全局注入store实列对象

// 引入store实例对象
import store from '@/store/index'

// 将store注入到vue实列对象中
new Vue({
  el: '#app',
  store,
  render: h => h(Counter)
})

四、vuex的使用

1、state的使用

用来存储数据的对象,对象中的数据可以在所有组件中使用

1.存储数据

const state = {
    newData: 5
}

2.在其他组件中获取数据

this.$store.state.newData
// 例如:输出结果为5
<p>{{$store.state.newData}}</p> 

3.获取state中多个数据

// 通过引入mapState辅助函数实现
import {mapState} from 'vuex'

注意mapState函数有两个方式赋值,需要结合计算属性
第一种是对象赋值

computed: mapState({
	// 箭头函数让代码简练
    count: state => state.count
    // 传字符串参数可以等价于箭头函数: 'count' == state => state.count
    countAlias: 'count'
})

案例演示:

// store>index.js
export default new Vuex.Store({
  state: {
    count: 1,
    sum: 10,
    add: 5
  }
})
    
// state.vue
<script>
    import {mapState} from 'vuex'
    export default new Vue({
        computed: mapState({
            count: state => state.count,
            sum: state => state.sum,
            add: state => state.add
        })
    })
</script>
    
<template>
    <div id="state">
    	<p>{{count}}</p> // 1
    	<p>{{sum}}</p> // 10
    	<p>{{add}}</p> // 5
    </div>
</template>

第二种是数组赋值(常用,推荐)

// 映射this.count为store.state.count
computed: mapState([
    'count'
])

案例演示:

// store>index.js
export default new Vuex.Store({
  state: {
    count: 3,
    sum: 6,
    add: 9
  }
})
    
// state.vue
<script>
    import {mapState} from 'vuex'
    export default new Vue({
        computed: mapState([
            'count',
            'sum',
            'add'
        ])
    })
</script>
    
<template>
    <div id="state">
    	<p>{{count}}</p> // 3
    	<p>{{sum}}</p> //6
    	<p>{{add}}</p> // 9
    </div>
</template>

第三种是展开运算符,在组件的方法中使用

// 使用对象展开运算符将此对象混入到外部对象中
computed: {
    ...mapState({
        count: 'count',
        sum: 'sum',
        add: 'add'
    })
}

2、mutations的使用

一个对象,保存的是更改state的函数,也只有它能更改state中的值,该函数可以传入两个参数,第一个参数为state,第二个参数为传入的数据,一般为一个对象

const mutations = {
    add (state, n) {
        state.count += n
    }
}

在其他组件中调用触发函数,改变state中变量的值

// 触发函数里有两个参数,第一个为调用的mutations里面的函数的函数名,第二个为数据
this.$store.commit('add', 2)

// 例如:
<button @click="$store.commit('add', 2)">点击改变count</button>

如果想要触发事件像正常函数那样,如:@click="add",则需要通过mapMutations辅助函数,需要结合methods对象

// 将 this.increment() 映射为 this.$store.commit('adds')
// 载荷:this.increment(amount) 映射为 this.$store.commit('adds', amount)

引入mapMutations辅助函数

import {mapMutations} from 'vuex'

第一种对象方式

// 注意命名不要和state中的变量重名
methods: mapMutations({
    adds: 'adds',
    reduce: 'reduce'
})

案例演示:


第二种数组方式

methods: mapMutations([
    'adds',
    'reduce'
])

第三种展开运算符,在组件的方法中使用

methods: {
    ...mapMutations({
        adds: 'adds',
        reduce: 'reduce'
    })
}

methods: {
    ...mapMutations([
        'adds',
        'reduce'
    ])
}

3、actions的使用

一个对象,保存的是触发mutations的函数,让mutations去修改state中的值,也可以是异步请求获取数据,获取数据后再通过context.commit()触发更改

// 相当于将$store.commit上的commit对象传进来,让方法体逻辑和代码更清晰明了
const actions = {
    addsAction: ({commit}) => commit('adds')
}

// 传递参数
const actions = {
    addsAction({commit}, n){commit('adds', n)}
}

// 传入任意参数,相当于store本身
const actions = {
    reduceAction: (context) => context.commit('reduce')
}

// 传递参数
const actions = {
    reduceAction(context,n){context.commit('reduce', n)}
}

在其他组件中触发actions函数

this.$store.dispatch('addsAction')

// 如果有参数的话,就传入参数,一般以对象的方式传入
this.$store.dispatch('addsAction', {
  amount: 10
})

// 例如:
<button @click="$store.dispatch('addsAction', 1)">点击改变p的值</button>
<button @click="$store.dispatch('reduceAction', 1)">点击改变p的值</button>

如果想要触发事件像正常函数那样,如:@click="add",则需要通过mapActions辅助函数,需要结合methods对象方法

引入mapActions辅助函数

import {mapActions} from 'vuex'

第一种对象方式

methods: mapActions({
    addsAction: 'addsAction',
    reduceAction: 'reduceAction'
})

案例演示:

<button @click="addsAction(1)">点击改变p的值</button>
<button @click="reduceAction(1)">点击改变p的值</button>

第二种数组方式

methods: mapActions([
    'addsAction',
    'reduceAction'
])

第三种展开运算符,需要在组件方法中使用

methods: {
    ...mapActions({
        addsAction: 'addsAction',
        reduceAction: 'reduceAction'
    })
}

// 或者数组形式
methods: {
    ...mapActions([
        'addsAction',
        'reduceAction'
    ])
}

4、getters的使用

getters相当于计算属性,用来重新修改state中变量的值,再返回对应的值,类似于vue的过滤器

const getters = {
    getUsername: state => state.username + '1'
    // 也可以这样写
    getUsername (state) {
        return state.username + '1'
    }
}

getters的使用方式同前面的差不多
第一种,正常使用方式

this.$store.getters.getUsername

第二种,就是数组模式

computed: {
    ...mapGetters([
        'getUsername'
    ])
}

第三种,就是对象模式

computed: {
    ...mapGetters({
        getUsername: 'getUsername'(前面是重新定义的方法名,后面是你定义在getters里面的方法名)
    })
}

五、属性变化监听

一般都是通过vue的watch来监听,watch监听分为普通监听和深度监听(对象)

// 例如,我们把state获取到并去监听数据变化来执行我们想要执行的事件
computed: {
    ...mapState([
        'username'
    ])
}
watch: {
    username (newVal, oldVal) {
        console.log('新值:' + newVal + '旧值:' + oldVal)
        // to do something here
    }
}

如果返回一个对象,我们要监听对象或者对象的某一个属性变化,则这样做

// 普通监听
computed: {
    ...mapGetters([
        'userInfo'
    ])
},
watch: {
    userInfo (newVal, oldVal) {
        console.log('新值:' + newVal + '旧值:' + oldVal)
        // to do something here 
    }
    // 必须
    deep: true
}
// 监听对象某个属性的变化
userInfo.username (newVal, oldVal) {
    console.log('新值:' + newVal + '旧值:' + oldVal)
    // to do something here 
}
// 如果想要对象中某个属性值改变时执行操作,可以通过computed来作为中间层来实现
computed: {
    username () {
        return userInfo.username
    }
}
watch: {
    username (newVal, oldVal) {
        console.log('新值:' + newVal + '旧值:' + oldVal)
        // to do something here
    }
}

六、注意事项

1、actions与mutations的区别

actions区别于mutations的地方在于mutations只能进行同步更改,而actions中的更改可以是异步执行。

所以基本上所有用户执行的直接数据更改都是触发mutations属性函数执行,而需要与后端进行数据交互的数据更改通常是通过actions属性函数去执行。

2、定义actions与mutations属性函数的注意事项

定义mutations属性函数时必须传递的第一个参数是state,因为要对state进行更改,第二个参数代表传入的新参数。

mutations属性函数只接受两个参数,如果要同时更改多个属性值,可以通过对象传入。

在actions属性函数中可以通过context.commit()方法触发mutations属性函数。定义actions属性函数时,必须传递的第一个参数是context,用于触发mutations函数。

3、触发actions与mutations属性函数的方法

在子组件中通过this.$store.commit()方法触发mutations属性函数。在注册store的Vue实例中(第三步中将会讲到)可以通过store.commit()触发。

commit函数第一个参数是mutations的属性函数名,第二个参数是传入的新值。

actions属性函数中可以进行异步操作,比如通过ajax或者Vue.Resource()进行数据获取,获取数据后再通过context.commit()触发更改。

触发actions属性函数使用this.$store.dispatch()或者store.dispatch() (在注册store的Vue实例中)函数。dispatch函数传递的一个参数是actions属性函数名称。

如果希望在Vue实例创建完成还未挂载时就从后端获取数据,则可以在created钩子函数中调用actions属性函数。

4、在组件中访问数据中心state的注意事项

在Vue实例中可以通过this.$store.state对象获取state中的数据。如果希望在state中的数据发生更改之后,组件会自动更新,则应该使用组件的computed属性定义数据,而不是通过data属性定义。

如果使用data定义组件数据,则state中的数据发生更改之后组件不会发生变化。

上一篇:vuex的核心概念和运行机制


下一篇:vuex 踩坑记之unknown local mutation type