1、store是一个状态管理工具 (vueX中只有惟一 一个store)
用途 :存数据 取数据 改数据
把须要共享的数据放在store里 不须要共享的数据仍是放在组件里
从state中取出数据渲染到view层------>view层再经过action改变数据------>action在将数据存入state (vuex的处理流程是一个单向的数据流 必须先发动动做才可以改数据)
Vuex就是提供一个仓库,Store仓库里面放了不少对象。其中state就是数据源存放地,对应于与通常Vue对象里面的data(后面讲到的actions和mutations对应于methods)。
在使用Vuex的时候一般会建立Store实例new Vuex.store({state,getters,mutations,actions})有不少子模块的时候还会使用到modules。
总结,Store类就是存储数据和管理数据方法的仓库,实现方式是将数据和方法已对象形式传入其实例中。要注意一个应用或是项目中只能存在一个Store实例!!
Vuex 的思想是 当咱们在页面上点击一个按钮,它会触发(dispatch)一个action, action 随后会执行(commit)一个mutation, mutation 当即会改变state, state 改变之后,咱们的页面会state 获取数据,页面发生了变化。 Store 对象,包含了咱们谈到的全部内容,action, state, mutation,因此是核心了。
store 对象注入到根实例后,在全部的子组件中,就能够用this.$store 来指向store 对象,获取state。在子组件中,computed 属性是根据它的依赖自动更新的。因此只要store中的state发生变化,它就会自动变化。
经过computed属性能够获取到状态值,可是组件中每个属性(如:count)都是函数,若是有10个,那么就要写10个函数,且重复写10遍return this.$store.state,不是很方便。vue 提供了 mapState 函数,它把state 直接映射到咱们的组件中。
store就是一个实例其中存放了不少对象,每一个对象又有不一样的职责,有的存放数据,有的调用方法
创建新项目的步骤:
一、新建一个vue项目
二、把数据存到state里 在文件路径下 cnpm i vuex --save
三、启动项目 npm run dev
四、在src文件夹中新建一个文件夹 store---->index.js----->main.js引入store----->App.vue 取数据渲染到页面上
index.js (向store中存数据)
import Vue from 'vue' //引入两个插件
import Vuex from 'vuex'
Vue.use(Vuex)
var store = new Vuex.Store({ //向store中存入数据
state:{
n:1000,
age:12,
lessions:["java","html"], //数组
haha:{ //对象
yi:'mm'
}
}
})
export default store //将数据暴露出去
main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import store from '@/store/index' //引入index
Vue.config.productionTip = false
new Vue({
el: '#app',
router,
store, //注册
components: {
App
},
template: '<App/>'
})
App.vue (从state中取数据)
<template>
<div id="app">
<img src="./assets/logo.png">
<router-view/>
{{n}} {{age}} {{lessions}} {{haha}} <!--渲染数据-->
</div>
</template>
<script>
export default {
name: 'App',
computed:{ //取数据
n(){
return this.$store.state.n
},
age(){
return this.$store.state.age
},
lessions(){
return this.$store.state.lessions[0]
},
haha(){
return this.$store.state.haha["yi"]
}
}
}
</script>
2、getters计算属性
Vuex 容许咱们在 store 中定义“getter”(能够认为是 store 的计算属性)。就像计算属性同样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被从新计算。
Getter 接受 state 做为其第一个参数, 也能够接受其余 getter 做为第二个参数
经过属性访问
Getter 会暴露为 store.getters 对象,你能够以属性的形式访问这些值
注意:getter 在经过属性访问时是做为 Vue 的响应式系统的一部分缓存其中的。(会产生缓存)
经过方法访问
也能够经过让 getter 返回一个函数,来实现给 getter 传参。在你对 store 里的数组进行查询时很是有用。
注意,getter 在经过方法访问时,每次都会去进行调用,而不会缓存结果。(不会产生缓存)
store.getters.getTodoById(2)
3、mutations 同步的方法更改数据
更改 Vuex 的 store 中的状态的惟一方法是提交 mutation。 惟一修改状态的事件的回调函数
mutation中放的是处理数据逻辑的方法,它可以使数据和视图分离,起到更改数据(状态)的做用。
(1)mutation 同步更改数据
每个mutation都有一个字符串类型的事件类型(type)和回调函数(handler),先注册事件type,当触发响应类型的时候调用handler();
(2)payload 提交载荷
简单的理解就是往handler(state)中传参handler(state,payload);通常是个对象。
state 是存放数据的地方
payload 至关于一个参数
(3)commit 调用mutation中的type
能够在组件中使用 this.$store.commit.("type名") 提交 通过mutation操做后作出改动的数据
commit是同步函数,并且只能是同步执行
4、actions 异步的方法更改数据
Action 提交的是 mutation,而不是直接变动状态。而且能够包含任何的异步操做。actions将mutations里面只能同步处里数据的方法变成了能够异步处理数据的方法。
Action 函数接受一个与 store 实例具备相同方法和属性的 context 对象,所以你能够调用context.commit来提交一个mutation(由于mutation中的type是经过 $store.commit方法被提交的,action中的mutation能够经过context.commit被提交 )
在组件中使用this.$store.dispatch("xxx") 分发 action
总结一下就是 同步提交mutation用 this.$store.commit("mutation中的type名")
异步提交mutation用 context.commit("mutation中的type名",参数)
异步分发action用 this.$store.dispatch("action中的type名")
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
Vue.use(Vuex)
var store = new Vuex.Store({
state:{ //存数据
n:10000,
age:12,
lesson:['aaaa','bbbbbb']
},
mutations:{ //同步的方法更改数据
changeAge1(state,payload){
//type:changeAge1,handler的第一个参数是state;
state.age=state.age+1 // 变动状态
},
changeNum1(state,payload){ // 提交载荷 payload 简单的理解就是往handler(state)中传参handler(state,payload);通常是个对象。
state.n+=payload
//这个payload至关于一个参数
},
addlesson(state,payload){
state.lesson=state.lesson.concat(payload) //在已有课程以后拼接新的课程
②payload接收到了从actions中的getlesson中甩出来的数据
}
},
actions:{
//异步的方法定义和调用数据
getlesson(context){ //context是自带的上下文对象
axios.get("http://localhost:3000/lessons").then((res)=>{
//从data.json中获取数据
context.commit("addlesson",res.data.map((item)=>item.lesson)) //
①第一个参数用于调用mutation中的方法 第二个参数至关因而payload 是将从json中获取到的值甩出去
})
}
}
})
export default store
App.vue
<template>
<div id="app">
<router-view/>
{{age}} <button @click='changeAge'>年龄</button>
<button @click='changeNum(1)'>+</button>{{n}}<button @click='changeNum(-1)'>-</button>
<p v-for='item in lesson'>{{item}}</p>
<button @click='getlesson'>添加数据</button>
<!--渲染数据-->
</div>
</template>
<script>
export default {
name: 'App',
computed:{ //取数据
n(){
return this.$store.state.n
},
age(){
return this.$store.state.age
},
lesson(){
return this.$store.state.lesson
}
},
methods:{ //调用方法改变数据
changeAge(){
this.$store.commit("changeAge1")
},
changeNum(n){
this.$store.commit("changeNum1",n)
},
getlesson(){
this.$store.dispatch("getlesson")
}
}
}
</script>
5、modules分模块
因为使用单一状态树,应用的全部状态会集中到一个比较大的对象。当应用变得很是复杂时,store 对象就有可能变得至关臃肿。
为了解决以上问题,Vuex 容许咱们将 store 分割成模块(module)。每一个模块拥有本身的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行一样方式的分割:
操做步骤:
在src文件目录下新建一个store文件夹----->在store中新建一个index.js----->在store目录下新建一个demo文件夹 ------>在demo中新建state.js 、mutation.js、action.js、getter.js文件----->在demo/index文件中引入以上几个js文件,并将其暴露出去------>store/index 引入demo文件夹而且建立store实例 引入modules----->App.vue中调用方法----->main.js引入store中的index.js 注册store
state.js
export default{ //不须要写state:{}
n:1000,
age:12,
lesson:['math','english']
}
mutations.js
export default{
changeAge(state,payload){
state.age=state.age+1
},
changeNum(state,payload){
state.n+=payload
},
addlesson(state,payload){
state.lesson=state.lesson.concat(payload)
}
}
actions.js
import axios from 'axios'
export default{
getlesson(context){
axios.get("http://localhost:3000/lessons").then((res)=>{
context.commit('addlesson',res.data.map((item)=>item.lesson))
})
}
}
demo/index.js
import state from './state'
import mutations from './mutations'
import actions from './actions'
export default{
state,
mutations,
actions
}
store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
import axios from 'axios'
import demo from './demo'
Vue.use(Vuex)
var store = new Vuex.Store({ //建立store实例
modules:{ //引入模块
demo
}
})
export default store
App.vue
<template>
<div id="app">
<button @click='changeNum(1)'>+</button>{{n}}<button @click='changeNum(-1)'>+</button>
<button @click='changeAge'>改变年龄</button>{{age}}
<p v-for='item in lesson'>{{item}}</p>
<button @click='getlesson'>添加课程</button>
</div>
</template>
<script>
export default {
name: 'App',
computed:{
n(){
return this.$store.state.demo.n //注意路径
},
age(){
return this.$store.state.demo.age
},
lesson(){
return this.$store.state.demo.lesson
}
},
methods:{
changeAge(){
this.$store.commit('changeAge')
},
changeNum(inc){
this.$store.commit('changeNum',inc)
},
getlesson(){
this.$store.dispatch('getlesson')
}
}
}
</script>
main.js
import Vue from 'vue'
import App from './App'
import router from './router'
import store from '@/store/index'
Vue.config.productionTip = false
new Vue({
el: '#app',
router, //把router和store放在实例上
store,
components: { App },
template: '<App/>'
})
6、四个辅助函数
mapstate //将state中的数据映射到组件中去
mapmutations
mapactions
mapgetters
<template>
<div>
{{Counter.arr[idx]}}<button @click="inc(idx)">+</button>
</div>
</template>
import {mapState,mapMutations} from ‘vuex’ //引入
computed:{
props:["idx"],
...mapState(["counter","arr"]) //这表示counter中的arr
},
mathods:{
...mapMutations(["inc"])
}