能够在vuex中集中管理共享的数据,易于开发和后期维护
能够高效地实现组件之间的数据共享, 提高开发效率
存储在 vuex中的数据都是响应式的,能够实时保持数据与页面的同步
一般情况下,只有组件之间共享的数据,才有必要存储到vuex中;
对于组件中的私有数据,依旧存储在组件自身的data中即可.
安装:
npm i vuex --save
导入:
import Vuex from "vuex"
Vue.use(Vuex)
创建仓库:
const store=new Vuex.Store({
state:{msg:"我就是所有共享的数据"}
})
把仓库挂载到vm对象:
new Vue({
render(h){return h(app)},
router,
store//挂载以后 所有的组件就可以直接从store中获取全局数据
}).$mount( "#app")
vue create init
选更多选项
选择Babel、router、vuex、scss、linter
选择2.x
scss
取消lint on save
1.创建state状态
状态就是那个存数据的对象const store=new Vuex.store({ state:{msg:"我就是所有共享的数据"} })
2.组件中访问数据
this.$store.state.msg
PS:this.$store.state.msg =“修改” ==>官方不建议使用此方法去修改,应该用官方提供的 mutation
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
new Vue({
router,
store,//让整个vue项目仓库生效
render: h => h(App)
}).$mount('#app')
router下的index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
Vue.use(VueRouter)
const routes = [{
path: '/',
name: 'home',
component: () => import("../views/home/index.vue")
},
{
path: '/home',
name: 'home2',
component: () => import("../views/home/index.vue")
},
{
path: '/login',
name: 'login',
component: () => import("../views/login/index.vue")
},
{
path: '/car',
name: 'car',
component: () => import("../views/car/index.vue")
},
{
path: '/news',
name: 'news',
component: () => import("../views/news/index.vue"),
beforeEnter(to,from,next){
console.log("beforeEnter",1111)
next()
}
},
{
path: '/*',
name: 'err',
component: () => import("../views/err/index.vue")
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
store下的index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)//让组件的原型链中 有仓库的工具代码
export default new Vuex.Store({
state: {
msg:"仓库中的数据",
arr:[{price:18,count:2,id:123},{price:15,count:2,id:124},{price:12,count:2,id:127}]
},
getters: {
total(state){
//笔试题: 字符串去前后空格 数组去重 求总价
return state.arr.reduce(function(n1,n2){return n1+n2.price*n2.count},0)
}
},
mutations: {
change1(state,agr2){
console.log(agr2,6666)
state.msg=agr2.a
},
change3(state,arg){
state.arr[0].count =arg.n
// mutations中修改仓库数据 只能在同步代码中实现 不要再异步函数中实现 否则会出现不刷新页面的情况
}
},
actions: {
},
modules: {
}
})
home下面的components下的Box2.vue
<template>
<div>
box2组件---{{$store.state.msg}}
<button @click="change1">box2的按钮修改msg(直接改 不推荐)</button>
<button @click="change2">box2的按钮修改msg(提交mutation)</button>
<button @click="change3">box2的按钮修改数量(提交mutation)</button>
</div>
</template>
<script>
export default {
methods:{
change1(){
// this.$store.state.msg="box2修改了仓库数据"//官方说的 不要这样直接去修改数据
},
change2(){
//提交载荷
//第1种. this.$store.commit("change1","hello,box2修改了数据")
//第2种. this.$store.commit("change1",{a:"hello,box2修改了数据"})
//也是2种的另外一种写法,
this.$store.commit({type:"change1",a:"hello,box2修改了数据"})
},
change3(){
this.$store.commit({type:"change3",n:10})
// this.$store.state.arr[0].count=200
}
}
}
</script>
<style>
</style>
getter就就像是store的计算属性,它会传入state对象供我们操作
state: { msg: "仓库中的数据", arr: [{ price: 18,count: 2,id: 123 },{ price: 15,count: 2,id: 124 },{ price: > 12,count: 2,id: 127 }] }, getters: { total(state) { // getter就就像是store的计算属性,它会传入state对象供我们操作 //笔试题: 字符串去前后空格 数组去重 求总价 return state.arr.reduce(function (n1,n2) { return n1 + n2.price * n2.count },0) } },
使用:
this.$store.getters.total
mutation中修改仓库数据,只能在同步代码中实现,不要在异步函数中实现,否则会出现不刷新页面的情况
修改状态的唯一方式就是提交mutations,而且是同步的
如果要异步的修改数据,就可以使用actions异步的提交mutations
组件中希望更改 Vuex 的 store 中的状态(数据)的唯一方法是提交 mutation
不要用赋值表达式直接在组件中给store设置新数据
这样设计的原因是,只有通过mutation来更新数据,它才会去帮我们通知所有使用数据的组件更新数据 刷新UI
mutations: { // 只有通过mutation来更新数据,它才会去帮我们通知所有使用数据的组件>更新数据 刷新UI change1(state,agr2) { //默认传第一个参数传state // this.$store.commit("change1",{a:"hello,box2修改了数据"}) console.log(agr2,6666) state.msg = agr2.a }, change3(state,arg) { state.arr[0].count = arg.n // mutations中修改仓库数据 只能在同步代码中实现 不要再异步函数中>实现 否则会出现不刷新页面的情况 } },
methods:{
change1(){
// this.$store.state.msg="box2修改了仓库数据"//官方说的 不要这样直接去修改数据
},
change2(){
//提交载荷
//第1种. this.$store.commit("change1","hello,box2修改了数据")
//第2种. this.$store.commit("change1",{a:"hello,box2修改了数据"})
//也是2种的另外一种写法,
this.$store.commit({type:"change1",a:"hello,box2修改了数据"})
},
}
注意:一条重要的原则就是要记住 mutation 必须是同步处理
下面是错误的方式:mutations: { increment (state,obj) { //如果fnAsync函数是一个异步业务函数,就会导致更新失败 fnAsync(() => { state.count=obj.n }) } }
Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作。
如果要异步的修改数据,就可以使用actions异步的提交mutations
Vue-vuex-Action
使用
1.直接分发
this.$store.dispatch(‘increment’,{n:100})
2.以对象形式分发this.$store.dispatch({ type: 'increment', n:100 })
可用于业务分块开发:
由于使用单一状态树,应用的所有状态会集中到一个比较大的对象。当应用变得非常复杂时,store 对象就有可能变得相当臃肿。
为了解决以上问题,Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter
使用
import Vue from 'vue'
import Vuex from 'vuex'
import Model1 from "./Model1.js"
import Model2 from "./Model2.js"
import Model3 from "./Model3.js"
import Model4 from "./Model4.js"
Vue.use(Vuex) //让组件的原型链中 有仓库的工具代码
export default new Vuex.Store({
state: {
},
getters: {
},
mutations: {
},
actions: {
},
modules: {
Model1,
Model2:Model2,
Model3,
Model4
}
})
store下的Model1.js
export default {
namespaced: true,//局部命名空间(让state的中变量与其他模块中的同名变量不冲突)
state: {
x:"张三的公共数据"
},
getters: {
getx(){
return x+"6666"
}
},
mutations: {
setxsync(state,obj){
state.x=obj.x
}
},
actions: {
setxasync(ctx,obj){
setTimeout(()=>{
ctx.commit("setxsync",obj)
},1000)
}
}
}