状态管理应用

@ Pinia
一切皆仓库
远程应用
[] 商品仓库
使用商品 goods
单个商品 good
获取所有商品 getGoods()
根据 id 获取所有商品 getGoodById()
其它:分页获取商品。。。
[] 购物车仓库
购物车 items
拉取/保存购物车 fetchCart()
添加到购物车 addToCart()
从购物车移除 deleteFromToCart()
清空购物车 clearCart()
总价 getTotalPrice/reduce() - 后期由 监听 实现
[] 点赞仓库 - 多组件共享
创建任意仓库,并创建一个状态 num
组件A中引入并使用;采用简单模板语法 {{num}}
组件B中引入并使用;采用双向绑定 v-mode
入口组件中引入并使用组件A、组件B,查看双向绑定时状态的共享变化
[]用户状态
[]访问量统计仓库
[]位置仓库
本地应用
[] 标签页仓库
导航时,添加标签页;便于快速打开历史页面/视图
多见于后台管理系统
思路同购物车:如果没有,则添加;否则激活
[] 页面导航仓库
创建仓库 - 商品 goods、状态 isLoading、请求 fetchGoods
请求商品数据 - 分别使用 fetch 和 axios
请求中,给出提示;请求结束,渲染数据
使用条件渲染追踪过程
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
export const useGoodStore = defineStore('good', () => {
  const goods = ref([])
  const isLoading = ref(false)
  const fetchGoods = async () => {
    isLoading.value = true
    let res = await fetch('http://127.0.0.1:3000/goods')
    let data = await res.json()
    goods.value = data
    isLoading.value = false
  }
  return { goods, isLoading, fetchGoods, }
})
import { onMounted } from 'vue';
import { useGoodStore } from '@/stores/good';
const store = useGoodStore();
onMounted(() => {
  store.fetchGoods();
})
<div v-if="store.isLoading">    loading    </div>
<div v-else>
    //
</div>
[] 模态框仓库
侦听仓库变化显示提示信息
商品仓库和购物车仓库都有数据加载。可以通过侦听仓库的 isLoading 给前端相应的提示
msg 可以提供给模态框使用
watch(() => goodStore.isLoading, (newVal, oldVal) => {
    if (newVal) {
        msg.value = '正在加载中...'
    } else {
        msg.value = '加载完成'
    }
    show.value = true;
})
[] 汉堡菜单仓库
项目从桌面端切换到移动端时,菜单折叠,由汉堡按钮控制折叠和展开;单击菜单项时,折叠菜单
1. 创建仓库 - 仓库参考代码 menu.js
import { ref } from 'vue'
import { defineStore } from 'pinia'

export const useMenuStore = defineStore('menu', () => {
  const flag = ref(false)
  const switchFlag = () => {
    flag.value ? flag.value = false : flag.value = true
  }

  return { flag, switchFlag }
})
2. 在使用仓库的组件结构中,引入仓库,通过汉堡按钮的单击,由标记 flag 控制动态类的应用,达到菜单的折叠和展开
改进:单击菜单项,折叠菜单
提示:在路由配置中,引入仓库,在导航前置守卫中实例化仓库并切换标记switchFlag;请查看 路由 - 导航守卫
[]主题切换仓库

主题切换/换肤/日夜模式

通过为 html 指定自定义属性实现 CSS 变量的更新达到切换效果

主题样式 - 这里仅给出需要变化的 CSS 变量,其它变量可以在额外的 :root 单独定义
:root {
    --txt-color: #303133;
    --bg-color: #f1f1f1;
    --shadow-color: rgba(0, 0, 0, 0.1);
}

// 类形式
.data-theme {
    --txt-color: #f1f1f1;
    --bg-color: #131313;
    --shadow-color: rgba(255, 255, 255, 0.1);
}

// 属性形式
[data-theme="dark"] {
    --txt-color: #f1f1f1;
    --bg-color: #131313;
    --shadow-color: rgba(255, 255, 255, 0.1);
}
主题仓库
import { defineStore } from 'pinia'
import { ref, onMounted } from 'vue'
export const useThemeStore = defineStore('theme', () => {

  const isDarkMode = ref(false);

  const toggleDarkMode = () => {
    isDarkMode.value = !isDarkMode.value;
    document.documentElement.setAttribute('data-theme', isDarkMode.value ? 'dark' : 'light');
  };

  return { isDarkMode, toggleDarkMode }
})
在SFC中引入仓库,并使用相应的图标展示暗黑和白天,最后绑定主题切换事件
import { useThemeStore } from '@/stores/theme';
const themeStore = useThemeStore();
<div class="theme-icon" @click="themeStore.toggleDarkMode">
    <span v-if="themeStore.isDarkMode" class="iconfont icon-night-mode-fill"></span>
    <span v-else class="iconfont icon-daytime-mode-fill"></span>
</div>