一披诗、store是一個(gè)狀態(tài)管理工具 (vueX中只有唯一 一個(gè)store)
用途 :存數(shù)據(jù) 取數(shù)據(jù) 改數(shù)據(jù)
把需要共享的數(shù)據(jù)放在store里 不需要共享的數(shù)據(jù)還是放在組件里
從state中取出數(shù)據(jù)渲染到view層------>view層再通過action改變數(shù)據(jù)------>action在將數(shù)據(jù)存入state (vuex的處理流程是一個(gè)單向的數(shù)據(jù)流 必須先發(fā)動(dòng)動(dòng)作才能夠改數(shù)據(jù))
Vuex就是提供一個(gè)倉庫,Store倉庫里面放了很多對(duì)象立磁。其中state就是數(shù)據(jù)源存放地呈队,對(duì)應(yīng)于與一般Vue對(duì)象里面的data(后面講到的actions和mutations對(duì)應(yīng)于methods)。
在使用Vuex的時(shí)候通常會(huì)創(chuàng)建Store實(shí)例new Vuex.store({state,getters,mutations,actions})有很多子模塊的時(shí)候還會(huì)使用到modules唱歧。
總結(jié)宪摧,Store類就是存儲(chǔ)數(shù)據(jù)和管理數(shù)據(jù)方法的倉庫,實(shí)現(xiàn)方式是將數(shù)據(jù)和方法已對(duì)象形式傳入其實(shí)例中颅崩。要注意一個(gè)應(yīng)用或是項(xiàng)目中只能存在一個(gè)Store實(shí)例<赣凇!
Vuex 的思想是 當(dāng)我們?cè)陧撁嫔宵c(diǎn)擊一個(gè)按鈕沿后,它會(huì)觸發(fā)(dispatch)一個(gè)action, action 隨后會(huì)執(zhí)行(commit)一個(gè)mutation, mutation 立即會(huì)改變state, state 改變以后,我們的頁面會(huì)state 獲取數(shù)據(jù)沿彭,頁面發(fā)生了變化。 Store 對(duì)象尖滚,包含了我們談到的所有內(nèi)容喉刘,action, state, mutation,所以是核心了漆弄。
store 對(duì)象注入到根實(shí)例后睦裳,在所有的子組件中,就可以用this.store.state撼唾,不是很方便廉邑。vue 提供了 mapState 函數(shù),它把state 直接映射到我們的組件中倒谷。
store就是一個(gè)實(shí)例其中存放了很多對(duì)象蛛蒙,每個(gè)對(duì)象又有不同的職責(zé),有的存放數(shù)據(jù)恨锚,有的調(diào)用方法
建立新項(xiàng)目的步驟:
1宇驾、新建一個(gè)vue項(xiàng)目
2、把數(shù)據(jù)存到state里 在文件路徑下 cnpm i vuex --save
3猴伶、啟動(dòng)項(xiàng)目 npm run dev
4课舍、在src文件夾中新建一個(gè)文件夾 store---->index.js----->main.js引入store----->App.vue 取數(shù)據(jù)渲染到頁面上
index.js (向store中存數(shù)據(jù))
import Vue from 'vue' //引入兩個(gè)插件
import Vuex from 'vuex'
Vue.use(Vuex)
var store = new Vuex.Store({ //向store中存入數(shù)據(jù)
state:{
n:1000,
age:12,
lessions:["java","html"], //數(shù)組
haha:{ //對(duì)象
yi:'mm'
}
}
})
export default store //將數(shù)據(jù)暴露出去
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, //注冊(cè)
components: {
App
},
template: '<App/>'
})
App.vue (從state中取數(shù)據(jù))
<template>
<div id="app">
<img src="./assets/logo.png">
<router-view/>
{{n}} {{age}} {{lessions}} {{haha}} <!--渲染數(shù)據(jù)-->
</div>
</template>
<script>
export default {
name: 'App',
computed:{ //取數(shù)據(jù)
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>
二、getters計(jì)算屬性
Vuex 允許我們?cè)?store 中定義“getter”(可以認(rèn)為是 store 的計(jì)算屬性)他挎。就像計(jì)算屬性一樣筝尾,getter 的返回值會(huì)根據(jù)它的依賴被緩存起來,且只有當(dāng)它的依賴值發(fā)生了改變才會(huì)被重新計(jì)算办桨。
Getter 接受 state 作為其第一個(gè)參數(shù)筹淫, 也可以接受其他 getter 作為第二個(gè)參數(shù)
通過屬性訪問
Getter 會(huì)暴露為 store.getters 對(duì)象,你可以以屬性的形式訪問這些值
注意:getter 在通過屬性訪問時(shí)是作為 Vue 的響應(yīng)式系統(tǒng)的一部分緩存其中的呢撞。(會(huì)產(chǎn)生緩存)
store.getters.doneTodos
通過方法訪問
也可以通過讓 getter 返回一個(gè)函數(shù)损姜,來實(shí)現(xiàn)給 getter 傳參饰剥。在你對(duì) store 里的數(shù)組進(jìn)行查詢時(shí)非常有用。
注意摧阅,getter 在通過方法訪問時(shí)汰蓉,每次都會(huì)去進(jìn)行調(diào)用,而不會(huì)緩存結(jié)果棒卷。(不會(huì)產(chǎn)生緩存)
store.getters.getTodoById(2)
三顾孽、mutations 同步的方法更改數(shù)據(jù)
更改 Vuex 的 store 中的狀態(tài)的唯一方法是提交 mutation。 唯一修改狀態(tài)的事件的回調(diào)函數(shù)
mutation中放的是處理數(shù)據(jù)邏輯的方法比规,它能夠使數(shù)據(jù)和視圖分離若厚,起到更改數(shù)據(jù)(狀態(tài))的作用。
(1)mutation 同步更改數(shù)據(jù)
每一個(gè)mutation都有一個(gè)字符串類型的事件類型(type)和回調(diào)函數(shù)(handler)蜒什,先注冊(cè)事件type测秸,當(dāng)觸發(fā)響應(yīng)類型的時(shí)候調(diào)用handler();
(2)payload 提交載荷
簡單的理解就是往handler(state)中傳參handler(state,payload)吃谣;一般是個(gè)對(duì)象乞封。
state 是存放數(shù)據(jù)的地方
payload 相當(dāng)于一個(gè)參數(shù)
(3)commit 調(diào)用mutation中的type
可以在組件中使用 this.$store.commit.("type名") 提交 經(jīng)過mutation操作后做出改動(dòng)的數(shù)據(jù)
commit是同步函數(shù),而且只能是同步執(zhí)行
四岗憋、actions 異步的方法更改數(shù)據(jù)
Action 提交的是 mutation,而不是直接變更狀態(tài)锚贱。并且可以包含任何的異步操作咬摇。actions將mutations里面只能同步處里數(shù)據(jù)的方法變成了可以異步處理數(shù)據(jù)的方法管削。
Action 函數(shù)接受一個(gè)與 store 實(shí)例具有相同方法和屬性的 context 對(duì)象,因此
你可以調(diào)用context.commit來提交一個(gè)mutation(因?yàn)閙utation中的type是通過 $store.commit方法被提交的,
action中的mutation可以通過context.commit被提交 )在組件中使用this.$store.dispatch("xxx") 分發(fā) action總結(jié)一下就是 同步提交mutation用 this.$store.commit("mutation中的type名")
異步提交mutation用 context.commit("mutation中的type名"迹缀,參數(shù))
異步分發(fā)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:{ //存數(shù)據(jù)
n:10000,
age:12,
lesson:['aaaa','bbbbbb']
},
mutations:{ //同步的方法更改數(shù)據(jù)
changeAge1(state,payload){ //type:changeAge1,handler的第一個(gè)參數(shù)是state烟阐;
state.age=state.age+1 // 變更狀態(tài)
},
changeNum1(state,payload){ // 提交載荷 payload 簡單的理解就是往handler(state)中傳參handler(state,payload)辣卒;一般是個(gè)對(duì)象。
state.n+=payload //這個(gè)payload相當(dāng)于一個(gè)參數(shù)
},
addlesson(state,payload){
state.lesson=state.lesson.concat(payload) //在已有課程之后拼接新的課程 ②payload接收到了從actions中的getlesson中甩出來的數(shù)據(jù)
}
},
actions:{ //異步的方法定義和調(diào)用數(shù)據(jù)
getlesson(context){ //context是自帶的上下文對(duì)象
axios.get("http://localhost:3000/lessons").then((res)=>{ //從data.json中獲取數(shù)據(jù)
context.commit("addlesson",res.data.map((item)=>item.lesson)) //①第一個(gè)參數(shù)用于調(diào)用mutation中的方法 第二個(gè)參數(shù)相當(dāng)于是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'>添加數(shù)據(jù)</button>
<!--渲染數(shù)據(jù)-->
</div>
</template>
<script>
export default {
name: 'App',
computed:{ //取數(shù)據(jù)
n(){
return this.$store.state.n
},
age(){
return this.$store.state.age
},
lesson(){
return this.$store.state.lesson
}
},
methods:{ //調(diào)用方法改變數(shù)據(jù)
changeAge(){
this.$store.commit("changeAge1")
},
changeNum(n){
this.$store.commit("changeNum1",n)
},
getlesson(){
this.$store.dispatch("getlesson")
}
}
}
</script>
五倦春、modules分模塊
由于使用單一狀態(tài)樹户敬,應(yīng)用的所有狀態(tài)會(huì)集中到一個(gè)比較大的對(duì)象。當(dāng)應(yīng)用變得非常復(fù)雜時(shí)睁本,store 對(duì)象就有可能變得相當(dāng)臃腫尿庐。
為了解決以上問題,Vuex 允許我們將 store 分割成模塊(module)呢堰。每個(gè)模塊擁有自己的 state抄瑟、mutation、action枉疼、getter皮假、甚至是嵌套子模塊——從上至下進(jìn)行同樣方式的分割:
操作步驟:
在src文件目錄下新建一個(gè)store文件夾----->在store中新建一個(gè)index.js----->在store目錄下新建一個(gè)demo文件夾 ------>在demo中新建state.js 鞋拟、mutation.js、action.js惹资、getter.js文件----->在demo/index文件中引入以上幾個(gè)js文件贺纲,并將其暴露出去------>store/index 引入demo文件夾并且創(chuàng)建store實(shí)例 引入modules----->App.vue中調(diào)用方法----->main.js引入store中的index.js 注冊(cè)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({ //創(chuàng)建store實(shí)例
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放在實(shí)例上
store,
components: { App },
template: '<App/>'
})
六、四個(gè)輔助函數(shù)
[http://www.reibang.com/p/6e253340952e](http://www.reibang.com/p/6e253340952e)
mapstate //將state中的數(shù)據(jù)映射到組件中去
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"])
}