vuex: 状态管理工具
使用场景:用户登录状态 购物车 地理位置 等
数据位置:内存
安装? 项目根目录??
yarn add vuex
?在src目录下新建store文件夹 下面新建index.js
src/store/index.js
在main.js中引入并使用
// 导入状态管理工具vuex
import store from './store'
const app = createApp(App)
app.use(store)
app.mount('#app');
核心组件就是这5个
?
state用来定义数据,设置数据的默认数据,一般为了数据的安全性,通常不直接修改state数据,而是通过mutations修改
state的简单用法
home.vue
<template>
<span>{{$store.state.goods}} {{$store.state.num}}</span>
</template>
?页面显示? 电脑 100
用来处理数据,对state中的数据进行处理,如果需要多组件使用这种数据。可以理解为计算组件,即getters的返回值会根据的它的依赖被缓存起来。
样例 通过getters增加或计算?state中数据
修改index.js
计算组件:给state中foods增加20? ? ?goodsDate(state)函数
大于20岁的学生? ?more20(state)函数
state: {
//状态管理器中定义的数据源
goods: '电脑',
num: 100,
foods: 10,
students: [{name:'mly',age:18},{name:'momo',age:22},{name:'morey',age:21}]
},
getters: {
//类似计算属性,必须return
goodsDate(state){
return state.foods+20
},
more20 (state){
return state.students.filter(item => item.age >= 20)
}
},
home.vue组件中展示
<template>
<span>State所有数据 : {{$store.state}}</span>
<h2>小于20岁学生: {{$store.getters.more20}}</h2>
<h3>食品数量增加20: {{$store.getters.goodsDate}}</h3>
</template>
效果:
?
?
?
mutations通常为修改state中的数据而使用,避免直接修改state的数据,唯一可以修改同步state的地方
更新 vuex中的数据
修改store/index.js
state: {
//状态管理器中定义的数据源
goods: '电脑',
num: 100,
foods: 10,
apple: 20,
}
mutations:{
//state更新的唯一方式 同步操作
increment(state){
state.foods++
},
// 有参数的方式更新vuex 参数为num
sum (state, num){
state.apple += num
}
}
?home.vue中展示? ?mutations同步更新vuex中的数据 即state的数据
点击一次 苹果数量加1
<template>
<span>mutations用法 foods+1:{{$store.commit("increment")}}</span>
<span>苹果数量:{{$store.state.apple}}</span>
<button @click="plusApple(1)">点击++</button>
</template>
<script>
import {reactive} from 'vue'
import {useStore} from "vuex";
export default {
name: "Home",
setup() {
const plusApple = (num) =>{
store.commit('sum',num) // mutation中定义的sum方法
}
const store = useStore()
store.commit('increment') //state中的方法名
console.log(store)
return{
plusApple
}
}
}
</script>
效果:
?
?
?
异步修改State 本质还是通过mutations修改?
?dispatch和commit的区别:两个方法都是传值给vuex的mutation改变state。dispatch是异步操作,commit是同步操作。dispatch在actions中使用。执行完mutations之后还可以做其他事情。
在store/index.js中定义actions
import {createStore} from "vuex";
export default createStore({
//状态管理器中定义的数据源
state: {
count: 0,
},
// mutations用于变更store中的数据
mutations:{
sum (state){
state.count++;
},
},
//action提交的mutation 而不是直接变更状态
actions: {
increment(context,payload){
//需要通过context.commit 触发某个mutation
context.commit('sum',payload.num)
}
}
getters{},
home.vue中展示
template中显示state中count数量??
点击一次调用 setup()中的函数plusCount方法
plusCount方法异步调用vuex中action组件中的increment方法
action中的incrment方法提交mutation中的sum方法 来变更state中的数据
<template>
<span>总数数量:{{$store.state.count}}</span>
<button @click="plusCount(1)">点击++</button>
</template>
<script>
import {reactive, computed} from 'vue'
import {useStore} from "vuex";
name: "Home",
setup() {
const store = useStore(),
function plusCount (num){
store.dispatch('increment',num)
}
return{
plusCount
}
</script>
?
后端数据接口地址? ? ?可以直接访问??
http://iwenwiki.com/api/blueberrypai/getIndexBanner.php
{
"success": true,
"msg": "",
"banner": [
{
"title": "\u6211\u5728\u7231\u5c14\u5170",
"content": "\u7231\u5c14\u5170\uff08\u7231\u5c14\u5170\u8bed\uff1aPoblacht na h\u00c9ireann\uff1b\u82f1\u8bed\uff1aRepublic of Ireland\uff09, \u662f\u4e00\u4e2a\u897f\u6b27\u7684\u8bae\u4f1a\u5171\u548c\u5236\u56fd\u5bb6\uff0c\u897f\u4e34\u5927\u897f\u6d0b\uff0c\u4e1c\u9760\u7231\u5c14\u5170\u6d77\uff0c\u4e0e\u82f1\u56fd\u9694\u6d77\u76f8\u671b\uff0c\u662f\u5317\u7f8e\u901a\u5411\u6b27\u6d32\u7684\u901a\u9053\u7231\u5c14\u5170\u81ea\u7136",
"img": "http:\/\/www.wwtliu.com\/sxtstu\/blueberrypai\/indexImg\/banner1.jpg"
},
{
"title": "\u4e00\u4e2a\u4eba\u7684\u4e1c\u4eac",
"content": "\u4e1c\u4eac(Tokyo)\u662f\u65e5\u672c\u56fd\u7684\u9996\u90fd\uff0c\u662f\u4e9a\u6d32\u7b2c\u4e00\u5927\u57ce\u5e02\uff0c\u4e16\u754c\u7b2c\u4e8c\u5927\u57ce\u5e02\u3002\u5168\u7403\u6700\u5927\u7684\u7ecf\u6d4e\u4e2d\u5fc3\u4e4b\u4e00\u3002\u4e1c\u4eac\u7684\u8457\u540d\u89c2\u5149\u666f\u70b9\u6709\u4e1c\u4eac\u94c1\u5854\u3001\u7687\u5c45\u3001\u56fd\u4f1a\u8bae\u4e8b\u5802\u3001\u6d45\u8349\u5bfa\u3001\u6d5c\u79bb\u5bab\u3001\u4e0a\u91ce\u516c\u56ed\u4e0e\u52a8\u7269\u56ed",
"img": "http:\/\/www.wwtliu.com\/sxtstu\/blueberrypai\/indexImg\/banner2.jpg"
},
{
"title": "\u666e\u7f57\u65fa\u65af\u7684\u68a6",
"content": "\u666e\u7f57\u65fa\u65af(Provence)\u4f4d\u4e8e\u6cd5\u56fd\u4e1c\u5357\u90e8\uff0c\u6bd7\u90bb\u5730\u4e2d\u6d77\u548c\u610f\u5927\u5229\uff0c\u4ece\u5730\u4e2d\u6d77\u6cbf\u5cb8\u5ef6\u4f38\u5230\u5185\u9646\u7684\u4e18\u9675\u5730\u533a\uff0c\u4e2d\u95f4\u6709\u5927\u6cb3\u201cRhone\u201d\u6d41\u8fc7\u3002\u81ea\u53e4\u5c31\u4ee5\u9753\u4e3d\u7684\u9633\u5149\u548c\u851a\u84dd\u7684\u5929\u7a7a\uff0c\u8ff7\u4eba\u7684\u5730\u4e2d\u6d77\u548c\u5fc3\u9189",
"img": "http:\/\/www.wwtliu.com\/sxtstu\/blueberrypai\/indexImg\/banner3.jpg"
},
{
"title": "\u76f8\u7ea6\u590f\u5a01\u5937\u4e4b\u590f",
"content": "\u590f\u5a01\u5937\u5dde\u4f4d\u4e8e\u5317\u592a\u5e73\u6d0b\u4e2d\uff0c\u8ddd\u79bb\u7f8e\u56fd\u672c\u571f3,700\u516c\u91cc\uff0c\u603b\u9762\u79ef16,633\u5e73\u65b9\u516c\u91cc\uff0c\u5c5e\u4e8e\u592a\u5e73\u6d0b\u6cbf\u5cb8\u5730\u533a\u3002\u9996\u5e9c\u4e3a\u6a80\u9999\u5c71\u3002\u57281778\u81f31898\u5e74\u95f4\uff0c\u590f\u5a01\u5937\u4e5f\u88ab\u79f0\u4e3a\u201c\u4e09\u660e\u6cbb\u7fa4\u5c9b\u201d(Sandwich Islands)",
"img": "http:\/\/www.wwtliu.com\/sxtstu\/blueberrypai\/indexImg\/banner2.jpg"
}
]
}
编写 index.js 文件
state中定义数据源 一个banner数组
mutaion中用于变更store中的数据?
actions中获取后端数据url? 将响应数据提交给mutation 来变更数据
import {createStore} from "vuex";
import axios from "axios";
export default createStore({
namespaced: true,
state: {
banner:[],
},
mutations:{
setBanner(state,banner){
state.banner = banner
},
},
//action提交的mutation 而不是直接变更状态
actions: {
asyncSetBanner(context, url){
axios.get(url).then(res =>{
context.commit('setBanner',res.data.banner)
})
}
}
home.vue
循序遍历state中banner中的标题和内容
<template>
<div>
<el-aside>
<button @click="getBannerHandle">获取数据</button>
<ul>
<li v-for="(item,index) in $store.state.banner" :key="index">
<h3>{{ item.title }}</h3>
<p>{{ item.content }}</p>
</li>
</ul>
</el-aside>
</div>
</template>
<script>
import {useStore} from "vuex";
export default {
name: "Home",
setup() {
const store = useStore()
},
methods:{
getBannerHandle(){
this.$store.dispatch("asyncSetBanner","http://iwenwiki.com/api/blueberrypai/getIndexBanner.php")
}
}
</script>
效果
?
?
?
vuex将store分割成模块,store对象分割成模块 每个模块包含(state,mutation action,getter)
?