Vuex基础学习

一、Vuex单界面到多界面状态管理切换:

①安装配置vuex:

step1.下载vuex

npm install vuex --save

step2.因为所有文件导入都堆积在main.js里太过繁杂,所以新建一个store文件夹 里面存放index.js:

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

// 1.安装插件
Vue.use(Vuex)

// 2.创建对象
const store = new Vuex.Store({
  state: {
    counter: 1000
  },
  mutations: {

  },
  actions: {

  },
  modules: {

  }
})

// 3.导出store对象
export default store

3.将store挂载到main.js在这里插入图片描述4.使用方法:$store.state
通过这个方式,能直接使用state里的数据。

<template>
 <div>
   <h2>{{$store.state.counter}}</h2>
 </div>
</template>

<script>
 export default {
  name: 'HelloVueX' ,
 data () {
 return {
  }
 }
}

</script>
<style scope>
</style>


二、Vuex-devtools和mutations

①devtools插件

在Chrome安装devtools插件打开项目之后:
在这里插入图片描述

就可以看见vue项目的基本结构:
在这里插入图片描述

可以看到和实时监控state的数据
在这里插入图片描述

 <h2>{{$store.state.counter}}</h2>
 <button @click="$store.state.counter++">+</button>
 <button @click="$store.state.counter--">-</button>

在这里插入图片描述

可以发现,我们直接通过$store.state.counter++来处理数据是不会对state里的counter有影响的。

②mutations:

所以要想修改state的数据必须通过mutations
step1.在mutation里写方法:

const store = new Vuex.Store({
  state: {
    counter: 1000
  },
  mutations: {
    // 方法
    increment() {
      this.state.counter++
    },
    decrement() {
      this.state.counter--
    }
  },
  actions: {

  },
  modules: {

  }
})

step2.在组件里写方法提交:

methods: {
        addition() {
          this.$store.commit('increment')
        },
        subtraction() {
          this.$store.commit('decrement')
        }
      },
<template>
  <div id="app">
    <h2>App里的内容————————————————————————————————</h2>
    <h2>{{$store.state.counter}}</h2>
    <button @click="addition">+</button>
    <button @click="subtraction">-</button>

    <hello-vuex/>
  </div>
</template>
<script>
import HelloVuex from './components/HelloVuex'
  export default {
    name: 'App',
    data() {
        return {
          massage: '我是App里的massage',
        }
      },
      methods: {
        addition() {
          this.$store.commit('increment')
        },
        subtraction() {
          this.$store.commit('decrement')
        }
      },
    components: {
      HelloVuex
    }
  }
</script>

在这里插入图片描述


三、Vuex核心概念:

在这里插入图片描述

Vuex有几个比较核心的概念:

  • State
  • Getters
  • Mutation
  • Action
  • Module
①Vuex-state单一状态树:

(单一数据源)
一个项目只有一个store

  • 如果你的状态信息是保存到多个Store对象中的,那么之后的管理和维护等等都会变得特别困难。
  • 所以Vuex也使用了单一 状态树来管理应用层级的全部状态。
  • 单一状态树能够让我们最直接的方式找到某个状态的片段,而且在之后的维护和调试过程中,也可以非常方便的管理和维护。

②vuex-getters的使用:

其实可以当成组件共享的计算属性

例:写一个对象数组,找出里面age>20的对象
普通写法:

state: {
    counter: 1000,
    students: [
      {id:110, name: 'he' , age: 18},
      {id:111, name: 'li' , age: 20},
      {id:112, name: 'ha' , age: 21},
      {id:113, name: 'ss' , age: 19},
    ]
  }
 computed: {
        moreThan20() {
          return this.$store.state.students.filter(s => s.age > 20)
        }
      }
<h2>{{moreThan20}}</h2>

但这种写法只能在需要的每个组件里都写上这个计算属性
如果写在getters里面 每个组件都可以直接使用:
getters:

const store = new Vuex.Store({
  state: {
    students: [
      {id:110, name: 'he' , age: 18},
      {id:111, name: 'li' , age: 20},
      {id:112, name: 'ha' , age: 21},
      {id:113, name: 'ss' , age: 19},
    ]
  },
  getters: {
    //这里要传参
    moreThan20(state) {
      return state.students.filter(s => s.age > 20)
    }
  }
})

使用方法:

<h2>{{$store.getters.moreThan20}}</h2>

另外,在getters的方法里也可以将getters作为参数,调用getters里的其他方法:

 		moreThan20(state) {
      return state.students.filter(s => s.age > 20)
    },
    moreThan20Length(state, getters) {
      return getters.moreThan20.length
    }

如何传入一个参数呢?
moreThan20Length(state, age)
不能这样写,这样写第二个参数还是会被当成getters。
正确方法:

moreAgeStu(state) {
      return function(age) {
        return state.students.filter(s => s.age > age)
      }
  
//箭头函数写法:
return age => { 
	return state.students.filter(s => s.age >age) 
}

moreAgeStu(8)

③Mutation状态更新:

state里的数据改变只能通过Mutation!

有参数传递的例子
参数被称为mutation的payload(载荷)
index.js中:

mutations: {
    // 方法
    incrementCount(state,count) {
      state.counter += count
    }
  }

组件中:

methods: {
	addCount(count){
  	this.$store.commit('incrementCount',count)
	}
}
<button @click="addCount(5)">+5</button>

在这里插入图片描述

mutation的提交风格:
之前的commit只是一种普通的提交风格
特殊的提交风格:
Vue还提供了另外-种风格,它是一个包含type属性的对象

this.$store.commit({
   type: 'changeCount',
   count
})

Mutation中的处理方式是将整个commit的对象作为payload使用,所以代码没有改变,依然如下:

changeCount(state,payload){
  state.count = payload.count
}

④Vuex的响应式原理:

Vuex的store中的state是响应式的,当state中的数据发生改变时, Vue组件会自动更新.
这就要求我们必须遵守一些Vuex对应的规则:
提前在store中初始化好所需的属性.
当给state中的对象添加新属性时,使用下面的方式:
➢方式一: 使用Vue.set(obj, ‘newProp’, 123)
➢方式二:用新对象给旧对象重新赋值

//info是一个对象
//如果想往这个对象里面添加新的属性并做到响应式 只能用vue.set
vue.set(state.info, 'address' , '洛杉矶')

//同样的如果想删除这个属性:
vue.delete(state.info, 'address')

⑤vue-mutations的类型常量:

可以在store里加一个js文件:
在这里插入图片描述

然后通过这样的方式定义常量:

export const INCREMENT = 'increment'

别的文件中导入后即可使用:
在这里插入图片描述

导入:

import{
  INCREMENT
} from './mutations-type'

使用:

mutations: {
    // 方法
    [INCREMENT]() {
      this.state.counter++
    }
}
methods: {
  addition() {
  this.$store.commit(INCREMENT)
  }
}

⑥vuex-actions的使用:

mutation里的所有代码都不能有异步操作:
如果有异步操作,就用actions来替代Mutations
但是actions任然不能直接修改state里的数据,如果有一个异步操作需要修改state里的数据,那么正确的方法应该是:
index.js:

state: {
    info:{
      name: 'he',
      age: 18
    }
  }
mutations: {
    updateInfo(state) {
      state.info.name = 'hels'
    }
  }
actions: {
    // 默认属性context 上下文
    aUpdateInfo(context) {
      setTimeout(() => {
        context.commit('updateInfo')
      }, 1000);
    }
  }

组件中:

 methods: {
    updataInfo() {
       this.$store.dispatch('aUpdateInfo')
    }
 }

dispatch:
在这里插入图片描述

context后面也可以接一个传递参数payload:

aUpdateInfo(context,payload) {
      setTimeout(() => {
        context.commit('updateInfo');
        console.log(payload);
      }, 1000);
    }
 this.$store.dispatch('aUpdateInfo','我是携带的信息')

但是通常携带的信息不只一个的时候怎么办呢:可以将payload作为一个对象:

updataInfo() {
  this.$store.dispatch('aUpdateInfo',{
  massage: '我是携带的信息',
  success: () => {
  	console.log('里面已经完成')
  }
  })
}
aUpdateInfo(context,payload) {
        setTimeout(() => {
          context.commit('updateInfo');
          console.log(payload.massage)
          payload.success()
        }, 1000);
    }

更简洁优雅的写法:Promise:

aUpdateInfo(context,payload) {
      return new Promise((resolve,reject) => {
        setTimeout(() => {
          context.commit('updateInfo');
          console.log(payload.massage)
          payload.success()
          resolve('1111')
        }, 1000);
      })
    }
this.$store
.dispatch('aUpdateInfo','我是携带的信息')
.then(res => {
   console.log('里面完成了提交')
   console.log(res)
})

⑦vuex-modules的使用:

Vue使用单-状态树,那么也意味着很多状态都会交给Vuex来管理.
当应用变得非常复杂时,store对象就有可能变得相当臃肿,为了解决这个问题,Vuex允许我们将store分割成模块(Module),而每个模块拥有自己的state. mutations、actions, getters等。
在这里插入图片描述

1.modules的state:
const moduleA = {
  state: {
    name: 'jing'
  },
  mutations: {},
  actions: {},
  getters: {},

}
const store = new Vuex.Store({
  state: {},
  mutations: {},
  actions: {},
  getters: {},
  modules: {
    a: moduleA
  }
})
 <h2 style="color:#FF8484">{{$store.state.a.name}}</h2>

这里只能用
$store.state.a.name
而不是.modules.a
因为在Devtools里可以看到 a会自动变成state的一个对象:
在这里插入图片描述

2.modules的mutation:
const moduleA = {
  state: {
    name: 'jing'
  },
  mutations: {
    updateName(state,payload) {
      state.name = payload
    }
  },
  actions: {},
  getters: {},

}
const store = new Vuex.Store({
  state: {
    name: 'jing'
  },
  mutations: {},
  actions: {},
  getters: {},
  modules: {
    a: moduleA
  }
})
 methods: {
   updateName() {
     //这里还是commit
      this.$store.commit('updateName','yang')
   }
 }
<h2 style="color:#FF8484">{{$store.state.a.name}}</h2>
<button @click="updateName">修改名字</button>

在这里插入图片描述

在这里插入图片描述

3.modules的getters:

无论是定义在store里的getters还是定义在modules里的getters 调用的方法都相同:

const moduleA = {
  state: {
    name: 'jing'
  },
  mutations: {},
  getters: {
    fullname(state) {
      return state.name + 'hahaha'
    }
  },
  actions: {}
}
<h2>{{$store.getters.fullname}}</h2>

我们都知道getters里的方法可以将本身getters作为参数来调用里面的其他函数:

 getters: {
    fullname(state) {
      return state.name + 'hahaha'
    },
    fullname2(state,getters) {
      return getters.fullname + '33'
    }
 }

而且,在modules中的getters还可以将store里的state作为参数:

getters: {
    fullname(state) {
      return state.name + 'hahaha'
    },
    fullname2(state,getters) {
      return getters.fullname + '33'
    },
    fullname3(state,getters,rootState) {
      return getters.fullname2 + rootState.counter
    }
  }
const store = new Vuex.Store({
  state: {
    counter: 1000
  }
})

4.modules的actions:

跟store的actions没什么差别:
在这里插入图片描述

写在modules里的actions commit时是commit的modules的mutation
但是如果想要commit store的mutation的话:

context.rootGetters

⑧vuex-store文件夹的目录组织:

1.state的抽离:
const state =  {
  counter: 1000,
  students: [
    {id:110, name: 'he' , age: 18},
    {id:111, name: 'li' , age: 20},
    {id:112, name: 'ha' , age: 21},
    {id:113, name: 'ss' , age: 19},
  ],
  info:{
    name: 'he',
    age: 18
  }
}
const store = new Vuex.Store({
  state,
}

2.mutations的抽离:

新建一个mutations.js:
在这里插入图片描述

import{
  INCREMENT
} from './mutations-type'

export default {
  // 方法
  [INCREMENT]() {
    this.state.counter++
  },
  decrement() {
    this.state.counter--
  },
  incrementCount(state,count) {
    state.counter += count
  },
  addStudent(state,stu) {
    state.students.push(stu)
  },
  updateInfo(state) {
    state.info.name = 'hels'
  }
}

然后:
在这里插入图片描述

import mutations from './mutations';

const store = new Vuex.Store({
  state,
  mutations,
}

3.actions的抽离:

和mutation一样可以抽离成一个函数:

export default {
  // 默认属性context 上下文
  aUpdateInfo(context,payload) {
    setTimeout(() => {
      context.commit('updateInfo');
      console.log(payload);
    }, 1000);
  },
  aUpdateInfo(context,payload) {
    return new Promise((resolve,reject) => {
      setTimeout(() => {
        context.commit('updateInfo');
        console.log(payload.massage)
        payload.success()
        resolve('1111')
      }, 1000);
    })
  }
}

import actions from './actions'

const store = new Vuex.Store({
  state,
  mutations,
  actions,
}

4.getters的抽离:

同理:

export default{
  powerCounter() {
    return this.state.counter * this.state.counter
  },
  moreThan20(state) {
    //这里要传参
    return state.students.filter(s => s.age > 20)
  },
  moreThan20Length(state, getters) {
    return getters.moreThan20.length
  },
  moreAgeStu(state) {
    // return function(age) {
    //   return state.students.filter(s => s.age > age)
    // }
    return age => { return state.students.filter(s => s.age >age) }
  }
}
import getters from './getters';

const store = new Vuex.Store({
  state,
  mutations,
  actions,
  getters,
}

5.modules的抽离:

新建一个modules文件夹:
在下面创建一个moduleA文件:
在这里插入图片描述

moduleA.js:

export default {
  state: {
    name: 'jing'
  },
  mutations: {
    updateName(state,payload) {
      state.name = payload
    }
  },
  getters: {
    fullname(state) {
      return state.name + 'hahaha'
    },
    fullname2(state,getters) {
      return getters.fullname + '33'
    },
    fullname3(state,getters,rootState) {
      return getters.fullname2 + rootState.counter
    }
  },
  actions: {
    aupdateName(context) {
      setTimeout(() => {
        context.commit('updateName','hels33')
      }, 1000);
    }
  }
}

import moduleA from './modules/moduleA';

const store = new Vuex.Store({
  state,
  mutations,
  actions,
  getters,
  modules: {
    a: moduleA
  }
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值