一、vue-router
1.路由发展
路由是网络工程的一个术语:
- 路由器主要维护一个映射表
- 映射表会决定数据的流向
- 路由器给每台电脑分配IP地址,即消息 -> IP地址 -> Mac地址
后端路由的映射方案:
- 一个url对应一个网页
- url发送网络请求,服务器正则对url匹配,交给controller进行处理
- 生成HTML或数据返回给前端
前端路由: 页面操作修改不同的url 显示 不同的组件,页面不进行刷新
- 修改hash值
hash模式的原理就是 onhashChange事件 - HTML5的history
history模式的原理就是 onpopstate函数 + pushState函数 + replaceState函数
history模式需要后端进行对应的配置
向浏览器历史记录中新增一条数据(地址栏中的地址会改变),但是页面不会刷新,但是如果我们给定的地址是不存在的,当我们页面手动刷新的时候,当前地址会报404错误,所以browser router需要服务器的支持(一般给予的支持:即使请求地址不存在,也是把首页的内容返回给客户端,而不是404)
SPA VS MPA
# SPA VS MPA
- spa:single page application 单页面应用
- iframe
- AMD/CMD + 打包工具
- 专业的路由管理模块vue-router / react-router-dom
- MPA:multi page application 多页面应用
>区别一:应用构成
+ 多页面:由多个完整页面构成
+ 单页面:一个外科页面和多个页面片段构成
>区别二:跳转方式
+ 多页面:页面之间的跳转是从一个页面到另一个页面
+ 单页面:一个页面片段删除或者隐藏,加载另一个页面片段并显示。片段键的模拟跳转,没有开壳页面
>区别三:跳转后公共资源是否重新加载
+ 多页面: http://xxx/page1.html和http://xxx/page2.html
+ 单页面: http://xxx/shell.html#page1 和http://xxx/shell.html#page2
>区别四:用户体验
+ 多页面:页面间切换加载慢,不流畅
+ 单页面:页面片段键切换快,用户体验好
>区别五:能否实现转场动画
+ 多页面: 否
+ 单页面:可以
>区别六:页面间传递数据
+ 多页面: 依赖URL、cookie、localstorage,实现麻烦
+ 单页面:页面传递数据容易(Vuex、Vue中的父子组件通讯props对象)
2.路由的基本使用
2.1 VUE2 ROUTER
import Vue from 'vue';
import VueRouter from 'vue-router';
import Home from './pages/Home';
import Custom from './pages/Custom';
import System from './pages/System';
Vue.use(VueRouter);
export default new VueRouter({
//=>设置路由模式 hash/history,如果是history,告诉服务端404页面需要处理
mode:"hash",
//=>配置一级路由
routes:[
{
//=>请求的是一个/,我们让其重定向到/home
path: '/',
redirect: '/home'
//component: Home
},
{
//=>HASH路径
path: './home',
//=>渲染的组件
component: Home
},
{
path: './custom',
component: Custom,
//=>配置某一个一级路由下面的二级路由
children:[{
path: '/custom/list',
component: CustomList
},{
path: 'handle', //=>可以简写,但是不能写斜杠了,否则认为是根目录下访问了
component: CustomHandle
}]
},
{
path: './system',
component: System
}
]
});
<div id="app">
<header class="headerBox">
<el-menu active-text-color="xx" default-active="1">
<el-menu-item :index="1">
//实现路由的切换和跳转
<router-link to='/home'>首页</router-link>
</el-menu-item>
<el-menu-item :index="2">
<router-link to='/custom'>客户管理</router-link>
</el-menu-item>
<el-menu-item :index="3">
<router-link to='/system'>系统设置</router-link>
</el-menu-item>
</el-menu>
</header>
//展示一级路由中各组件的内容(呈现组件的视图容器)
<router-view></router-view>
</div>
2.2 VUE3 ROUTER
2.3 router-link的属性
3.路由懒加载
4.动态路由
$route.params = $router.currentRoute.value.params
获取:当前地址下刷新页面,params中的信息也不会消失
5.NotFount页面
6.编程式路由跳转
//=>vue2通过this.$router跳转
this.$router
go(n): 回退或者前进
back() =>go(-1)
forward()=>go(1)
push():跳转到指定的路由,实现路由切换
=> 编程式导航
//=>vue3通过useRouter返回值跳转
import { useRouter } from 'vue-router'
const router = useRouter()
router.go(n):
.back() =>go(-1)
.forward()=>go(1)
.push()
基于地址直接params问号传参和对象path方式跳转
vue3 router共同点:
1.传递的信息都会在地址栏中显示
2.都可以通过$route.query或 $route.currentRoute.value.query获取
区别:
1.params方式传参基于问号传参,对象方式只能基于query对象方式传参
<router-link to='/custom/list'></router-link>
<router-link to='/custom/list?lx=my'></router-link>
<router-link :to="{path:'/custom/list'}"></router-link>
<router-link :to="{path:'/custom/list',query:{lx:'my'}}"></router-link>
7.命名路由
//=>命名路由(给每一个路由设置一个名字,后期可以基于名字实现跳转)
{
path:'/custom',
name:'custom',
component:Custom,
children:[{
path:'/custom/list',
name:'customList',
component:CustomList
},{
path:'handle',
name:'customHandle',
component:CustomHandle
}]
}
<router-link :to="{name:'customList'}"></router-link >
<router-link :to="{name:'customList',query:{lx:'my'}}"></router-link >
<router-link :to="{name:'customList',params:{lx:'my'}}"></router-link >
new Vue({
router, //=>this.$router this.$route===$router.currentRoute
store, //=>this.$store
render:h=>h(app)
}).$mount('#app');
配置路由
components:{
default:Home,
view2:System
}
跳转
<router-view></router-view>
<router-view name="view2"></router-view>
8.动态管理路由-根据判断动态添加路由
8.1 删除路由的三种方法
- 方式一:添加一个name相同的路由:
- 方式二:通过removeRoute方法,传入路由的名称
- 方式三:通过addRoute方法的返回值回调
8.2 路由的其他方法
- router.hasRoute(): 检测路由是否存在
- router.getRoutes(): 获取一个包含所有路由记录的数组
9.路由导航守卫
9.1 登录逻辑的导航守卫
/**
* 全局前置钩子:不管路由匹配哪一个地址,渲染了哪一个组件,都会触发
* 参数:
* + to:将要跳转的到的路由对象(query/params..)
* + from:从那个路由来,存储的是这个路由对象,即将要离开的路由
* 返回值:
* + false:取消当前导航
* + 不返回或undefined:进行默认导航
* + 返回一个路由地址: 当前导航中断,进入到下一个导航(和$router.push一样)
* 可以是一个string类型的路径
* 可以是一个对象,对象中包含path、query、params等信息
* 可选的第三个参数:next(不推荐使用)
* + 在vue2中我们是通过next函数来决定如何进行跳转的
* + 但是在vue3中我们是通过返回值来控制的,不在推荐使用next函数,这是因为开发中很容易调用多次next
*/
// 需求:进入到订单页面时,判断用户是否登录
// 一:没有登录,跳转到登录页面,进行登录的操作
// 二:已经登录,那么直接进入到订单页面
router.beforeEach((to, from) => {
const token = localStorage.getItem("token")
if (!token && to.path === "/order") {
return '/login'
}
});
9.2 导航守卫的整个解析
官方描述:
导航被触发
1.在失活的组件里调用 beforeRouteLeave 组件内守卫
2.调用全局的 beforeEach 路由前置守卫
return '/login
3.在重用的组件里调用 beforeRouteUpdate 组件内守卫(2.2+)
/user/123 /user/321
4.在路由配置里调用beforeEnter 路由独享守卫
coutes:[path,component,beforeEnter(){}]
5.解析异步路由组件
()=>import("about.vue") -> js文件
6.在被激活的组件里调用beforeRouteEnter 组件内守卫
about组件:beforeRouterEnter 没有this
beforeRouueEnter(next){
//没有this
next((instance)=>{})
}
7.调用全局的beforeResolve 全局解析守卫(导航被确认跳转之前,同时在所有组件内守卫和异步路由组件被解析之后,解析守卫就被调用)(2.5+)
8.导航被确认
9.调用全局的afterEach钩子
10.触发DOM更新
about template -> DOM
11.调用beforeRouteEnter 守卫中传给next的回调函数,创建好的组件实例会作为回调函数的参数传入
有this
- 进入组件
全局beforeEach -> 路由独有beforeEnter -> 组件独有beforeRouteEnter -> 全局beforeResolve ->全局afterEach -> beforeCreate —> data -> created -> beforeMount -> Mounted
- 离开组件进入另一个组件
组件独有beforeRouteLeave -> 全局beforeEach -> 路由独有beforeEnter -> 组件独有beforeRouteEnter -> 全局beforeResolve -> 全局afterEach ->beforeCreate —> data -> created -> beforeMount ->(在新组件进入渲染之前上一个组件销毁) beforedestory -> destoryed -> Mounted -> beforeUpdate ->Updataed
二、Vuex状态管理
1.注册使用Vuex
1.1 在vue2中注册使用Vuex
//=>在vue2中注册Vuex
import Vue from 'vue';
import App from './App.vue';
import store from './store/index';
Vue.config.productionTip = false;
new Vue({
// 在每一个组件的实例中都会挂载一个$store的属性,所有的组件都可以基于this.$store获取store容器
store,
render: h => h(App),
}).$mount('#app');
//vue2中使用Vuex
import Vue from 'vue';
import Vuex from 'vuex';
//=>Vuex是vue中的一个插件
Vue.use(Vuex);
//=>创建store容器并且导出
const store = new Vuex.Store({
state: {},
//=>存储的方式等价于computed计算属性:监听当前容器中state中的计算属性
getters: {},
//=>mutations存储sync function,这些方法修改state的状态信息
mutations: {},
//=>actions存储async function:这些方法首先异步获取需要的数据,再基于commit触发mutations中的方法,从而改变state
actions:{},
modules:{}
});
export default store;
1.2 在vue3中注册使用Vuex
//=>在vue3中注册Vuex
import { createApp } from 'vue';
import vuex from './store'
import App from './App.vue'
const app = createApp(App);
app.use(vuex);
app.mount('#app');
//vue2中使用Vuex
import { createStore } from 'vuex'
export default createStore({
state: {
},
mutations: {
},
actions: {
},
modules: {
}
})
2.vuex的执行流程
3.Vuex的基本使用
4.Vuex的state
4.1 state的基本使用
一个Vuex应用的核心就是store(仓库):
- store本质上是一个容器,它包含着你的应用中大部分的状态(state)
Vuex和单纯的全局对象有什么区别?
1. Vuex的状态存储是响应式的
- 当Vue组件从store中读取状态的时候,若store中的状态发生变化,那么相应的组件也会被更新
- 这样得到的state不会响应式的
- 解构之后也不是响应式的,可以toRefs
2. 不能直接改变store中的状态
- 要通过Vuex中的mutations改变state
4.2 store的状态映射到组件中
# 1.单一状态树SSOT, Single Source of Truth
- 用一个对象包含了全部的应用层级的状态
- 这就意味着,每个应用将仅仅包含一个store实例
- 单状态树和模块化并不冲突,后面会有module的概念
# 2.单一状态树的优势
- 如果状态保存到多个store对象中,管理会困难,所以Vuex采用单一状态树管理应用层级的全部状态
- 最直接的找到某个状态的片段
- 方便管理和维护
vue2中使用state状态
Vue3 setup中使用state状态
- 一步一步操作
- 封装hooks函数
- 解构state并toRefs
5. getters
5.1 基本使用
5.2 getters的映射
<template>
<div class="home">
<button @click="changeName">修改name</button>
<h2>doubleCounter:{{ doubleCounter }}
</h2>
<h2>friendsTotalAge:{{ totalAge }}</h2>
<h2>message:{{ message }}</h2>
<!-- 根据ID获取某一个朋友 的信息 -->
<h2>id-111的朋友信息:{{ getFriendById(111) }}</h2>
<h2>id-112的朋友信息:{{ getFriendById(112) }}</h2>
</div>
</template>
<script>
import { mapGetters } from 'vuex';
export default {
computed: {
// 对象
// ...mapGetters({
// doubleCounter: "doubleCounter",
// totalAge: "totalAge"
// }),
// 数组
...mapGetters(["doubleCounter", "totalAge"]),
...mapGetters(["getFriendById"])
}
}
</script>
<script setup>
import { computed, toRefs } from 'vue'
import { mapGetters, useStore } from 'vuex'
const store = useStore()
// const { message: messageFn } = mapGetters(["message"])
// const message = computed(messageFn.bind({ $store: store }))
const { message } = toRefs(store.getters)
function changeName() {
store.state.name = "Hezi"
}
</script>
6.mutations
6.1 mutations的基本使用
- 更改Vuex中的store中的状态的唯一方法:提交mutation
在组件中使用
<template>
<div class="home">
<button @click="changeName">修改name</button>
<button @click="incrementLevel">递增level</button>
<button @click="changeInfo">修改info</button>
<h2>Store Name:{{ $store.state.name }}</h2>
<h2>Store Level:{{ $store.state.level }}</h2>
</div>
</template>
<script setup>
import { useStore } from 'vuex';
import { CHANGE_INFO } from '../../store/mutation_types'
const store = useStore()
function changeName() {
// store.state.name = "xxx"
store.commit("changeName", "小王")
}
function incrementLevel() {
store.commit("incrementLevel")
}
function changeInfo() {
store.commit(CHANGE_INFO, {
name: "王二",
level: 99
})
}
</script>
定义常量
export const CHANGE_INFO = "CHANGE_INFO"
在Vuex中定义方法
import { createStore } from 'vuex'
import { CHANGE_INFO } from './mutation_types'
const store = createStore({
state: () => ({
counter: 100,
name: 'wx',
level: 100,
avatarURL: "http://xxxx",
friends: [
{ id: 111, name: "wx", age: 20 },
{ id: 112, name: 'we', age: 30 },
{ id: 113, name: "wr", age: 25 }
]
}),
getters: {
// 1.基本使用
doubleCounter(state) {
return state.counter * 2
},
totalAge(state) {
return state.friends.reduce((preValue, item) => {
return preValue + item.age
}, 0)
},
// 2.在getters属性中,获取其他的getters
message(state, getters) {
return `name:${state.name}; level:${state.level}; friendTotalAge:${getters.totalAge}`
},
// 3.getters支持返回一个函数
getFriendById(state) {
return function (id) {
const friend = state.friends.find(item => item.id === id)
return friend
}
}
},
mutations: {
increment(state) {
state.counter++
},
incrementLevel(state) {
state.level++
},
changeName(state, payload) {
state.name = payload
},
[CHANGE_INFO](state, payload) {
state.level = payload.level
state.name = payload.name
}
},
actions: {
},
modules: {
}
})
export default store
6.2 mutations的映射
vue2
<template>
<div class="home">
<button @click="changeName('小王')">修改name</button>
<button @click="incrementLevel">递增level</button>
<button @click="changeInfo({ name: '大王', level: 99 })">修改info</button>
<h2>Store Name:{{ $store.state.name }}</h2>
<h2>Store Level:{{ $store.state.level }}</h2>
</div>
</template>
<script>
import { mapMutations } from 'vuex';
import { CHANGE_INFO } from '../../store/mutation_types'
export default {
methods: {
...mapMutations(["changeName", "incrementLevel", CHANGE_INFO])
}
}
</script>
vue3
<template>
<div class="home">
<button @click="changeName('小王')">修改name</button>
<button @click="incrementLevel">递增level</button>
<button @click="changeInfo({ name: '大王', level: 99 })">修改info</button>
<h2>Store Name:{{ $store.state.name }}</h2>
<h2>Store Level:{{ $store.state.level }}</h2>
</div>
</template>
<script setup>
import { useStore, mapMutations } from 'vuex';
import { CHANGE_INFO } from '../../store/mutation_types'
const store = useStore()
// 手动的映射和绑定
/**
* 原则:mutation 必须是同步函数
* + devtools会记录mutation的日记
* + 每一条mutation被记录,devtools都需要捕捉到前一状态和后一状态的快照
* + 如果执行异步操作,就无法追踪到数据的变化
*/
const mutations = mapMutations(["changeName", "incrementLevel", CHANGE_INFO])
const newMutations = {}
Object.keys(mutations).forEach(key => {
newMutations[key] = mutations[key].bind({ $store: store })
})
const { changeName, incrementLevel, changeInfo } = newMutations
</script>
7.actions
7.1 基本使用
7.2 actions的映射
vue2
<template>
<div class="home">
<h2>当前计数:{{ $store.state.counter }}</h2>
<h2>name:{{ $store.state.name }}</h2>
<button @click="incrementAction">发起action修改counter</button>
<button @click="changeNameAction('Hezi')">发起action修改name</button>
</div>
</template>
<script>
import { mapActions } from 'vuex';
export default {
methods: {
...mapActions(["incrementAction", "changeNameAction"])
}
}
</script>
vue3
<template>
<div class="home">
<h2>当前计数:{{ $store.state.counter }}</h2>
<h2>name:{{ $store.state.name }}</h2>
<button @click="increment">发起action修改counter</button>
<button @click="changeName">发起action修改name</button>
</div>
</template>
<!-- <script>
import { mapActions } from 'vuex';
export default {
methods: {
...mapActions(["incrementAction", "changeNameAction"])
}
}
</script> -->
<script setup>
import { toRefs } from 'vue';
import { mapActions, useStore } from 'vuex';
const store = useStore()
/*
1. 在setup中使用辅助函数
const actions = mapActions(["incrementAction", "changeNameAction"])
const newActions = {}
Object.keys(actions).forEach(key =>{
newActions[key] = actions[key].bind({ $store: store})
})
const { incrementAction, changeNameAction } = newActions
*/
// 2.使用默认的用法
function increment() {
store.dispatch("incrementAction")
}
function changeName() {
store.dispatch("changeNameAction", "Hezi")
}
</script>
7.3 发送网络请求
home页面
<template>
<div class="home">
<h2>Home Page</h2>
<ul>
<template v-for="item in $store.state.banners" :key="item.acm">
<li>{{ item.title }}</li>
</template>
</ul>
</div>
</template>
<script setup>
import { useStore } from 'vuex';
const store = useStore()
// 告诉Vuex发起网络请求
// 要使得dispatch能返回promise,则在actions中异步请求的时候要返回promise,调用resolve返回数据,然后在组件中then的时候就知道代码调用了
store.dispatch("fetchHomeMultidataAction").then(res => {
console.log("home中的then被回调:", res);
})
</script>
8.module模块
8.1 基本使用
vuex
home模块
export default {
state: () => ({
// 服务器数据
banners: [],
recommends: []
}),
mutations: {
changeBanners(state, banners) {
state.banners = banners
},
changeRecommends(state, recommends) {
state.recommends = recommends
}
},
actions: {
fetchHomeMultidataAction(context) {
// fetch("http://123.207.32.32:8000/home/multidata").then(res => {
// return res.json()
// }).then(data => {
// console.log(data);
// })
return new Promise(async (resolve, reject) => {
const res = await fetch("http://123.207.32.32:8000/home/multidata")
const data = await res.json()
// 修改state的数据
context.commit("changeBanners", data.data.banner.list)
context.commit("changeRecommends", data.data.recommend.list)
resolve("sss")
})
}
}
}
home页面
<template>
<div class="home">
<h2>Home Page</h2>
<ul>
<!-- 获取数据:需要从模块中获取 -->
<template v-for="item in $store.state.home.banners" :key="item.acm">
<li>{{ item.title }}</li>
</template>
</ul>
</div>
</template>
<script setup>
import { useStore } from 'vuex';
const store = useStore()
store.dispatch("fetchHomeMultidataAction").then(res => {
console.log("home中的then被回调:", res);
})
</script>
8.2 模块默认和命名空间
模块默认
vuex
count模块
const counter = {
state: ()=> ({
count: 99
}),
getters: {
doubleCount(state, getters, rootState) {
return state.count + rootState.rootCounter
}
},
mutations: {
incrementCount(state) {
state.count++
}
},
actions: {
incrementCountAction({state, commit, rootState}) {
commit("incrementCount")
}
}
}
export default counter
home页面
<template>
<div class="home">
<h2>Home Page</h2>
<!--
1.使用state时,是需要state.moduleName.xxx
2.使用getters时,是直接getters.xxx
3.mutations、actions和getters一样,默认已经合并在Vuex里面了
-->
<h2>Count模块的count:{{ $store.state.count.count }}</h2>
<h2>Count模块的doubleCount:{{ $store.getters.doubleCount}}</h2>
<button @click="incrementCount">count模块+1</button>
</div>
</template>
<script setup>
import { useStore } from 'vuex';
const store = useStore()
// 派发事件和提交mutation时,默认也是不需要跟模块名称
function incrementCount(){
store.dispatch("incrementCountAction")
}
</script>
命名空间
vuex
count模块
const counter = {
namespaced: true,
state: ()=> ({
count: 99
}),
getters: {
doubleCount(state, getters, rootState) {
return state.count + rootState.rootCounter
}
},
mutations: {
incrementCount(state) {
state.count++
}
},
actions: {
incrementCountAction({state, commit, rootState}) {
commit("incrementCount")
}
}
}
export default counter
home页面
<template>
<div class="home">
<h2>Home Page</h2>
<!--
加上命名空间:$store.getters["模块名/xxx"]
-->
<h2>Count模块的count:{{ $store.state.count.count }}</h2>
<h2>Count模块的doubleCount:{{ $store.getters["count/doubleCount"] }}</h2>
<button @click="incrementCount">count模块+1</button>
</div>
</template>
<script setup>
import { useStore } from 'vuex';
const store = useStore()
// 派发事件和提交mutation时,需要跟模块名称
function incrementCount() {
store.dispatch("count/incrementCountAction")
}
</script>
8.3 module修改或派发根组件
三、pinia
1.pinia和Vuex的区别
1.mutations不再存在
2.更友好的typeScript支持,
3.不再有module是的嵌套结构
可以灵活使用每一个store,他们是通过扁平化的方式相互使用的
4.没有命名空间的概念
2.pinia的基本使用
- 创建store
- 什么是store
- 定义一个store
- 使用store
3.操作state
home页面
<template>
<div class="home">
<h2>home page</h2>
<h2>name:{{ name }}</h2>
<h2>age:{{ age }}</h2>
<h2>level:{{ level }}</h2>
<button @click="changeState">修改state</button>
<button @click="resetState">重置state</button>
</div>
</template>
<script setup>
import { storeToRefs } from 'pinia';
import useUser from '@/stores/user'
const userStore = useUser()
const { name, age, level } = storeToRefs(userStore)
// 修改state
function changeState() {
// 1.一个个的修改状态
// userStore.name = "Hezi"
// userStore.age = 20
// userStore.level = 200
// 2.一次性修改多个状态
// userStore.$patch({
// name: "Hezi",
// age: 30
// })
// 3.替换state为新的对象:这样只是改掉内存中的属性值,不是改变内存地址
const oldState = userStore.$state
userStore.$state = {
name: "jom",
level: 300
}
// console.log(oldState === userStore.$state);//true
}
// 重置state
function resetState() {
userStore.$reset()
}
</script>
<style scoped>
</style>
user store
import { defineStore } from "pinia";
const useUser = defineStore("user", {
state: ()=> ({
name: "wx",
age: 18,
level: 100
})
})
export default useUser
4.操作getters
home组件
<template>
<div class="home">
<h2>home page</h2>
<h2>doubleCount:{{ counterStore.doubleCount }}</h2>
<h2>doubleCountAddOne:{{ counterStore.doubleCountAddOne }}</h2>
<h2>friend-111:{{ counterStore.getFriendById(111) }}</h2>
<h2>showMessage:{{ counterStore.showMessage }}</h2>
</div>
</template>
<script setup>
import { storeToRefs } from 'pinia';
import useCounter from '@/stores/counter';
const counterStore = useCounter()
</script>
<style scoped>
</style>
userStore 演示getters
// 定义关于counter的store
import { defineStore } from "pinia";
import useUser from "./user";
const useCounter = defineStore("counter", {
state: () => ({
count: 99,
friends: [
{ id: 111, name: 'wx' },
{ id: 112, name: 'wy' },
{ id: 113, name: 'wz' },
]
}),
getters: {
// 1.基本使用
doubleCount(state) {
return state.count * 2
},
// 2.一个getter引入另外一个getter
doubleCountAddOne(state, getters) {
return this.doubleCount + 1
},
// 3.getters支持返回一个函数
getFriendById(state) {
return function (id) {
return state.friends.find(item => item.id === id)
}
},
// 4.getters中用到别的store的数据
showMessage(state) {
// 1.获取user信息
const useStore = useUser()
// 2.获取自己的信息
// 3.拼接信息
return `name:${useStore.name}-count:${state.count}`
}
}
})
export default useCounter
5.操作actions
home
<template>
<div class="home">
<h2>home page</h2>
<h2>count:{{ counterStore.count }}</h2>
<button @click="changeState">修改state</button>
<!-- 展示数据 -->
<h2>轮播的数据</h2>
<ul>
<template v-for="item in homeStore.banners">
<li>{{ item.title }}</li>
</template>
</ul>
</div>
</template>
<script setup>
import useCounter from '@/stores/counter';
import useHome from '@/stores/home'
const counterStore = useCounter()
function changeState() {
// counterStore.increment()
counterStore.incrementNum(10)
}
const homeStore = useHome()
homeStore.fetchHomeMultidata().then(res => {
console.log("fetchHomeMultidata的action已经完成了:", res);
})
</script>
<style scoped>
</style>
home.js
import { defineStore } from "pinia";
const useHome = defineStore("home", {
state: () => ({
banners: [],
recommends: []
}),
actions: {
/*
async fetchHomeMultidata(){
const res = await fetch("http://123.207.32.32:8000/home/multidata")
const data = await res.json()
this.banners = data.data.banner.list
this.recommends = data.data.recommend.list
return 'aaa' // 相当于promise.resolve(aaa)
}
*/
fetchHomeMultidata() {
return new Promise(async (resolve, reject) => {
const res = await fetch("http://123.207.32.32:8000/home/multidata")
const data = await res.json()
this.banners = data.data.banner.list
this.recommends = data.data.recommend.list
resolve('aaa')
})
}
}
})
export default useHome
counter.js
// 定义关于counter的store
import { defineStore } from "pinia";
import useUser from "./user";
const useCounter = defineStore("counter", {
state: () => ({
count: 99,
friends: [
{ id: 111, name: 'wx' },
{ id: 112, name: 'wy' },
{ id: 113, name: 'wz' },
]
}),
getters: {
// 1.基本使用
doubleCount(state) {
return state.count * 2
},
// 2.一个getter引入另外一个getter
doubleCountAddOne(state, getters) {
return this.doubleCount + 1
},
// 3.getters支持返回一个函数
getFriendById(state) {
return function (id) {
return state.friends.find(item => item.id === id)
}
},
// 4.getters中用到别的store的数据
showMessage(state) {
// 1.获取user信息
const useStore = useUser()
// 2.获取自己的信息
// 3.拼接信息
return `name:${useStore.name}-count:${state.count}`
}
},
actions: {
increment(){
this.count++
},
incrementNum(num){
this.count += num
}
}
})
export default useCounter