Vuex 是一个专门为Vue.js应用程序开发的状态管理模式,就是为Vue管理状态的,状态可看做数据
Vuex作为Vue配套的公共数据管理工具,可以把一些共享的数据保存到vuex中,方便整个程序中的任何组件直接获取或修改我们的公共数据
为什么要使用vuex
父组件向子组件传值要使用属性绑定,子组件向父组件传值要使用事件调用的方式,这是父子两个组件间传值的方式
但如果组件A中有组件B,组件B中有组件C,A想获取C的数据,是不能直接获取的,需要通过B,那事件调用就要使用两次,这是挺麻烦的,而且B并不需要C的数据但还是要被牵扯进来,加上如果组件嵌套更多层,那这种数据层层传递的方式更是繁杂
另外还有种情况是,一个页面中有两个组件,这两个兄弟组件如果想获取对方的数据,需要vm实例来进行中转,一个组件通过事件调用传值给vm,vm再通过属性绑定传值给另一组件
vuex是为了保存组件间共享数据而诞生的,如果组件间有要共享的数据,可以直接挂载到vuex中-,没有"中间商赚差价"
data用来存放组件自身的数据,props存放父组件传来的数据,而vuex是一个全局的共享数据存储区域,一个仓库
安装
两种方式,网页中使用<script>标签引入,在vue之后引入vuex会自动进行安装
另一种方式是npm
示例
❶ 安装 npm i vuex
❷ 导包
❸ 使用Vue.use()注册
❹ 创建store实例
❺ 将store挂载到vm实例上
//导包
import Vue from 'vue'
import Vuex from 'vuex'
//注册vuex到vue中
Vue.use(Vuex)
//new Vuex.Store() 得到一个数据仓储对象
var store = new Vuex.Store({
//state就相当于组件中的data,专门用来存储数据
state:{
count:0
},
mutations:{
}
})
import App from './App.vue'
new Vue({
el:'#app',
render: c => c(App),
//将vuex创建的store挂载到vm实例上
store:store
})
只要将store挂载到vm实例上,任何组件都能使用store来存取数据
组件中想要访问或修改store中的数据可以通过 this.$store.state.*** 的方式
但修改数据是不推荐使用此方式,因为不符合vuex的设计理念,如果有几个组件操作了store的数据,万一数据紊乱就很难查出问题是哪个组件引起的
所以如果要操作store中的数据,只能通过调用mutations中的方法,才能操作对应的数据,不推荐直接操作state中的数据
mutations就好比仓库管理员,如果货物乱了出了问题,直接找管理员就行了,因为只有它接触过货物
如果组件想要调用mutations中的方法,只能使用 this.$store.commit('方法名')
这种调用mutatios方式,类似子组件的 this.$emit('父组件方法名') ,传参的话第二个是要传递的参数,但$emit()可传多个参数,而$commit()只能传一个参数
var store = new Vuex.Store({
//state就相当于组件中的data,专门用来存储数据
state:{
count:0
},
mutations:{
//自定义add()方法,然后在子组件中调用此方法即可操作store中的count数据
add(state){
state.count++
}
}
})
在store实例中还有个getters属性,此属性值负责对外提供数据,不负责修改数据,若想修改state中的数据,要去mutations
getters中的方法跟组件过滤器比较类似,因为两者都没有修改原数据,都是把原数据做了一层包装,提供给了调用者
其次getters也和computed比较像,只要state中的数据发生变化,如果getters正好引用了此数据,就会立即出发getters的重新求值
var store = new Vuex.Store({
state:{
count:0
},
mutations:{ },
getters:{
optCount: function(state) {
return '当前最新的count值是:' + state.count
}
}
})
总结
① state中的数据,不能直接修改,想要修改,必须通过mutations
② 如果组件想要直接从state上获取数据,需要 this.$store.state.***
③ 如果组件想要修改数据,必须使用mutations提供的方法,需要通过 this.$store.commit('方法名',按需求传递的唯一的一个参数)
④ 如果store中的state上的数据,在对外提供时候,需要做层包装,那推荐使用getters,若需要使用getters,则调用 this.$store.getters.***