文章目录
求一键三连
希望大家看完觉得有用的话点赞、关注和收藏,感谢!!!
前言
关于状态管理的两个库——vuex/pinia
pinia是更适配vue3的,并且更好用,但是现在很多公司大量的项目用的是vuex,所以还是要了解。
后面pinia一定会占据主流。pinia相当于vuex5的版本,官方推荐也在推荐pinia。学完vuex再学pinia之后会更快,因为概念是一样的。
因为vue3(composition api)是适用pinia的,所以在vue3里面使用vuex就会特别别扭,很多不适配,所以vuex是了解就好,主要是记录主要的使用,在后面项目中用到的时候再来看就行,主要是要知道有哪些用法。
所以最好的办法就是除了setup语法之外,在多写一个options api的script,这样也是OK的,然后在里面写相关的操作。
一共五个核心点,记住这个目录
认识状态管理(前端数据库)
在我看来这不就是前端的“数据库”吗,就是创建一个store.js来存储数据,vuex负责管理(响应式)
在前面学父子组件间通信的时候就提到了状态管理,因为这样传数据是很麻烦的,并且当组件多了之后管理就很不方便,还是像数据库一样把数据单独抽出来管理是最合适的,这个抽取的思想很重要。
总的来说,状态是不断变化的,因为要遵循单向数据流,所以所有的数据变化还是要放在store.js里面完成,这样才方便对状态进行管理。
vuex使用
store=仓库=数据库
Vuex基本使用
- 安装vuex
- 创建store
- app.use(store)
- tempate -> $store.state.counter
创建store
单向数据流,组件里无法改变数据,需要commit提交到store中进行改变。
import {
createStore } from 'vuex'
const store = createStore({
state: () => ({
counter: 100,
name: "coderwhy",
level: 100,
avatarURL: "http://xxxxxx",
friends: [
{
id: 111, name: "why", age: 20 },
{
id: 112, name: "kobe", age: 30 },
{
id: 113, name: "james", age: 25 }
]
}),
组件中使用store
模板中使用:
可以直接拿,但这样比较繁琐,所以还是在computed里面封装一下再使用比较好
options api中使用 :
setup中使用:
必须要加toRefs才是响应式的,数据的改变还是要commit到store中改变
和vue-router一样
use是vue使用库会用的一个函数
在script中使用这些库(store和router)都是用hook的方式,useRouter,useStore
(hooks:钩子函数,回调函数,就是一些函数)
单一状态树
就是只有一个store状态库,但里面可以有很多对象。
vuex只能有一个store,但是可以有module,pinia则不一样,可以有多个store
组件获取状态
使用mapState(映射方法)拿到数据(了解,不行可以不用)
就是在computed里面使用mapState方法,这样就可以直接用state里的数据,不用写一长串了。
在options api中的写法:
在computed()里面去写,这里分别是数组语法和对象语法:
在template中使用就是:
对象语法的好处就是可以重新命名,这样就可以减少冲突:
在setup语法中使用mapState(麻烦,做个了解)
无法直接用,因为直接用mapState拿是函数,在视频里讲了好几个方法,就记一下最好用的方法吧:
这样就可以直接用了
这个是老师封装的一个方法。
geetters使用
某些属性需要变化才用,例如统计所有人的成绩,或者要乘一下再用,这些操作都放在getters里面完成
第二个参数可以是getters
在getters中处理:
具体使用:
那么其实在这里这么长的表示都应该放到computed里面封装一下
例:
computed:{
message(){
return $store.getters.message
}
}
geetters的映射使用——mapGetters(麻烦 大可不用)
options api写法
直接写好就可以唉template里用了,就很方便
setup写法(也很不方便)
记住这些操作就是为了方便去使用store里的数据
方法1:加toRefs变成响应式
方法2:
Mutation基本使用
这些都是在options api里面进行操作的
这个就像父子组件里在父组件的methods里面进行操作,只不过是用state,没有tihs了
别忘了在方法()里加上state
传入的参数名是payload(可以随便命名。但是一般叫这个),还有就是可以传入一个对象,这样可以做的修改就更多的,最后一个就是传入了一个对象,叫newInfo
所以在子组件里面也要传出相应的事件:commit
这里最后传入的就是一个对象,可以进行的操作就更多。
此外,要记住这个和之前的父子通信一样,传入的是事件名,可以随便写,但是一般和子组件的方法名相同,这样也好理解,同时也要和在mutation中的方法名也要保持一致
常量类型(多次一举的规范,了解)
多加一步,为了防止在某一个地方写错,导致无法使用,引用常量,只要在常量里没有写错就不会写错
创建一个mutation_types的js文件,在里面创建变量并导出,只要这里的事件名没有写错就不会出错
在组件中导入这个变量并使用
在store的js文件中也导入变量并使用
关于中括号:就是使用这个变量名而已
感觉是多次一举,主要是防止出错吧
mapMutation辅助函数(了解)
一样都行,就是语法糖。
options api:
不用写方法了
setup api:
极其麻烦
mutation 重要原则(重要)
不要在里面写异步操作
actions使用( 重要从参数:context)
向后端发送网络请求
因为真实的数据都是从网络请求拿到的(要放到store里面),由于异步操作的需要,引出actions
所以actions是用来进行网络数据请求的。
要特别记住actions和mutation的区别,面试会问到
actions提交的是mutation,但是mutation是直接变更状态
接受的不一样 是context(上下文),里面有很多东西,就是像一个store
store中书写actions
执行事件操作必须要context.commit(‘事件名’),调用的还是mutation里的事件处理方法
可以看到传入的是context,在处理事件的时候还是要commit调用store里面的函数来处理
特别注意:在actions中的事件名要加一个Action用以区别,否则名字就都是一样的了,不好理解。
在组件中使用action
action——dispatch(派发)
options:
setup:
mapActions也是做一个了解就好了:
数据方案
两种方案
1.数据在页面中进行维护
(获取的数据和自己创建的数据混在一起,就会不好)
2.数据在vuex里面维护(这里面还有模块,这样数据结构更加清晰)
这样感觉结构更清晰,那就是数据和页面是分开的 不会揉在一起
在actions中获取数据
步骤
- 在actions中创建 fetchHomeMultidataAction(context) 函数用fetch拿到数据并最后用json返回成data
- 要赋值给state中的数据,这样后面页面才可以使用到,依然是commit并传入参数提交到mutation里
- 在state中声明要使用的的数据
- 在mutation中赋值banners
(这里有一个问题,那就是不应该把数据分开传进去,还不如直接传一个object对象data进去,不然还要写好多遍,太麻烦)
看完视频最后发现它把数据的获取抽成了单独的一个组件module(简单来说就是单独的一个js文件,export然后在主index.js里面导入即可)
看完它的抽取就发现写的清晰多了,确实舒服多,如果放在大的store里面,会看起来很累。
fetch拿到数据,返回一个promise(res),然后转换成json格式,再返回一个promise(data)
这里是不同的几种获取方式,我觉得第一种最方便
fetchHomeMultidataAction(context) {
// 1.返回Promise, 给Promise设置then
fetch("http://123.207.32.32:8000/home/multidata").then(res => {
res.json().then(data => {
console.log(data)
})
})
//写法3 这一块在es6没有好好了解
//手动返回promise 这里主要是缺少相关知识点了解
return new Promise(async (resolve, reject) => {
// 3.await/async 异步函数自动返回promise
const res = await fetch("http://123.207.32.32:8000/home/multidata")
const data = await res.json()
// 修改state数据,这里也是要传mutation里面处理,把数据传进去
context.commit("changeBanners", data.data.banner.list)
context.commit("changeRecommends", data.data.recommend.list)
resolve("aaaaa")
组件中使用获取到的数据
要先把数据导进来,所以要使用actions里获取数据的方法,dispatch,这个也可以在onMounted这样的生命周期函数里面写好。
这里还有一点就是在执行之后会在控制台打印。
页面上:
所这里也可以看到要获取的数据要提前在state里声明才可以使用
promise一定要学好 ,现在前端对promise要求很高
忘记是很正常的,重要的是到时候用的时候回顾起来就行了
因为东西学了不用就会忘很正常,所以之前学的时候要做好笔记,到时候捡起来就快了。
多写作记多背,跟自己比较,最重要的是每天都有进步,不要焦虑。
module的基本使用
module就比较好理解,主要是为了抽取逻辑出来,比如说之前的从服务器获取数据那一个逻辑,当时揉在index.js的store里面看起来就特别的累,这个时候把它抽出来(home.js),叫做homeModule,再导入进去,这样就看起来清晰多了,把一个逻辑的东西放到一起,这个时候维护起来也方便
在index.js里:
store的modules: 这里是进行重命名
在组件中使用:
ps:在setup里的内容就不用改了
module的局部状态
也特别好理解,就是这里面的state不是index.js里的state,就是在这个文件里的state,如果要用外面的数据,要用rootState
组件中使用:默认是不用加模块名的,但是这样就是在全局去找,因为模块也是在全局的
此外,在模块里命名要特别小心,注意不要和store里的重复了,一旦重复,调用的就是store里的,而非模块里的,因为在调用的时候是不用加模块的,所以这个时候就有命名空间来解决这个问题
这个时候拿的时候就要加上模块名:
到这里就结束了,把模块的这个用法掌握就好了。
这个随便看看吧