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"])
}