vue3+antd动态修改主题

主要代码文件

head-seeting.vue

<script setup lang="ts">
import { ref } from 'vue'
import { useGlobalStore } from '@/stores/global'
import ColorPicker from '@/components/base-color-picker/index.vue'

const open = ref(false)
/**
 * 打开layout布局抽屉
 */
const showLayoutDrawer = () => {
  open.value = true
}

// 整体风格设置
const sideStyleList = [
  {
    tips: '亮色主题风格',
    value: 'light',
    url: 'https://gw.alipayobjects.com/zos/antfincdn/NQ%24zoisaD2/jpRkZQMyYRryryPNtyIC.svg',
  },
  {
    tips: '暗色主题风格',
    value: 'dark',
    url: 'https://gw.alipayobjects.com/zos/antfincdn/XwFOFbLkSM/LCkqqYNmvBEbokSDscrm.svg',
  },
]

/**
 * 子组件传递的颜色
 * @param color 颜色
 */
function updateColor(color: any) {
  useGlobalStore().setTagColor(color)
}
</script>
<template>
  <div class="layout">
    <LayoutOutlined @click="showLayoutDrawer" />
  </div>
  <a-drawer
    v-model:open="open"
    placement="right"
    :closable="false"
    size="default"
  >
    <div>
      <h3>整体风格设置</h3>
      <div class="layout-icon">
        <a-tooltip v-for="(item, index) in sideStyleList" :key="index">
          <template #title>
            <span>{{ item.tips }}</span>
          </template>
          <img
            :src="item.url"
            :alt="item.tips"
            @click="useGlobalStore().setSideStyle(item.value)"
          />
          <div class="checkbox">
            <check-outlined
              v-if="useGlobalStore().theme === item.value"
              class="checkbox-select"
            />
          </div>
        </a-tooltip>
      </div>
      <a-divider />
      <div class="theme-color">
        <h3>主题色</h3>
        <div class="theme-color-content">
          主题颜色:
          <color-picker
            :open="open"
            :color="useGlobalStore().themeColor"
            @update:color="updateColor"
          ></color-picker>
        </div>
      </div>
      <a-divider />
      <a-form class="text-right">
        <a-form-item label="灰色模式">
          <a-switch
            :checked="useGlobalStore().isGrey"
            @change="useGlobalStore().setGrey(!useGlobalStore().isGrey)"
          />
        </a-form-item>
        <a-form-item label="模块坞图标">
          <a-switch
            :checked="useGlobalStore().moduleUnfoldIconOpen"
            @change="useGlobalStore().setModuleUnfoldIcon()"
          />
        </a-form-item>
        <a-form-item label="显示LOGO">
          <a-switch
            :checked="useGlobalStore().logoOpen"
            @change="useGlobalStore().setLogo()"
          />
        </a-form-item>
        <a-form-item label="折叠菜单">
          <a-switch
            :checked="useGlobalStore().collapsed"
            @change="useGlobalStore().setMenusState()"
          />
        </a-form-item>
      </a-form>
      <a-alert
        message="以上配置可实时预览,不建议在生产环境下开放布局设置"
        type="warning"
      />
    </div>
  </a-drawer>
</template>
<style lang="less" scoped>
@import '@/style/theme.css';
.layout {
  min-width: 40px;
  padding: 8px;
  color: #666;
  font-size: 18px;
  text-align: center;
  cursor: pointer;

  &:hover {
    background-color: #e2e2e2;
    border-radius: 5px;
  }
}
.layout-icon {
  display: flex;
  margin-bottom: 20px;
  cursor: pointer;
  img {
    z-index: 999;
    width: 50px;
    height: 42px;
    margin-right: 16px;
    overflow: hidden;
    border-radius: 2px;
  }
  .checkbox {
    position: relative;
    .checkbox-select {
      position: absolute;
      right: 27px;
      bottom: 12px;
      color: var(--themeColor);
      font-weight: 700;
      font-size: 14px;
      pointer-events: none;
    }
  }
}
.theme-color {
  .theme-color-content {
    display: flex;
    margin-top: 20px;
    line-height: 30px;
  }
}
.text-right {
  text-align: right;
}
</style>

global.ts

import { defineStore } from 'pinia'

/**
 * 主题
 */
export const useGlobalStore = defineStore({
  id: 'global',
  /**
   * state
   */
  state: () => ({
    /**
     * 整体风格设置
     */
    theme: localStorage.getItem('theme') || 'light',
    /**
     * 主题色
     */
    themeColor: localStorage.getItem('themeColor') || '#1890FF',
    /**
     * 灰色模式
     */
    isGrey: false,
    /**
     * 模块坞图标
     */
    moduleUnfoldIconOpen: false,
    /**
     * 显示LOGO
     */
    logoOpen: true,
    /**
     * 菜单是否折叠
     */
    collapsed: false,
  }),
  actions: {
    /**
     * 设置整体风格主题
     * @param value value
     */
    setSideStyle(value: any) {
      this.theme = value
      localStorage.setItem('theme', value)
    },

    /**
     * 切换颜色
     * @param value value
     */
    setTagColor(value: any) {
      this.themeColor = value
      document.documentElement.style.setProperty('--themeColor', value)
      localStorage.setItem('themeColor', value)
    },

    /**
     * 灰色模式
     * @param value value
     */
    setGrey(value: any) {
      this.isGrey = !this.isGrey
      const body = document.body
      body.removeAttribute('style')
      if (!value) return
      body.setAttribute('style', 'filter: grayscale(1)')
    },

    /**
     * 模块坞图标
     */
    setModuleUnfoldIcon() {
      this.moduleUnfoldIconOpen = !this.moduleUnfoldIconOpen
    },

    /**
     * 显示LOGO
     */
    setLogo() {
      this.logoOpen = !this.logoOpen
    },

    /**
     * 初始化主题色
     */
    initThemeColor() {
      document.documentElement.style.setProperty(
        '--themeColor',
        this.themeColor,
      )
    },

    /**
     * 展开折叠菜单
     */
    setMenusState() {
      this.collapsed = !this.collapsed
    },
  },
})

app.vue

<template>
  <a-config-provider
    :locale="zhCN"
    :theme="{
      token: {
        colorPrimary: useGlobalStore().themeColor,
      },
    }"
  >
    <vue3-progress-bar></vue3-progress-bar>
    <router-view></router-view>
  </a-config-provider>
</template>

<script lang="ts" setup>
import { useGlobalStore } from '@/stores/global'



useGlobalStore().initThemeColor()
</script>

<style lang="less">
@import '@/style/theme.css';
#app {
  /* app style */
  .vue3-progress-bar-container {
    .vue3-progress-bar {
      background-color: var(--themeColor);
    }
  }
  a {
    color: var(--themeColor);
  }
}
</style>

效果图

好的,针对你的问题,我们可以通过以下步骤实现: 1. 在Vue3项目中引入Antd和Axios:在Vue3项目中,可以通过npm或yarn安装Antd和Axios,并在main.js中引入。 2. 定义章节列表和当前章节索引:在Vue3组件中,我们可以使用data属性定义章节列表和当前章节索引。 3. 通过Axios获取小说章节列表:在mounted钩子中,使用Axios发送请求获取小说章节列表,并将结果存储在章节列表中。 4. 实现切换章节的方法:在Vue3组件中定义一个方法,通过修改当前章节索引实现切换小说章节。 5. 实现按钮点击事件:在Vue3组件中,可以使用Antd的Button组件实现按钮,并绑定点击事件调用切换章节的方法。 下面是具体实现代码示例: ```vue <template> <div> <h2>{{ chapter.title }}</h2> <p>{{ chapter.content }}</p> <div> <a-button type="primary" @click="prevChapter">上一章</a-button> <a-button type="primary" @click="nextChapter">下一章</a-button> </div> </div> </template> <script> import axios from 'axios'; import { Button } from 'ant-design-vue'; export default { components: { 'a-button': Button, }, data() { return { chapters: [], // 章节列表 currentChapterIndex: 0, // 当前章节索引 }; }, mounted() { // 获取小说章节列表 axios.get('/api/chapters').then(res => { this.chapters = res.data; }); }, computed: { chapter() { return this.chapters[this.currentChapterIndex]; }, }, methods: { prevChapter() { if (this.currentChapterIndex > 0) { this.currentChapterIndex--; } }, nextChapter() { if (this.currentChapterIndex < this.chapters.length - 1) { this.currentChapterIndex++; } }, }, }; </script> ``` 以上就是一个简单的实现小说章节切换的示例代码。需要注意的是,这只是一个简单的示例,实际项目中可能需要更复杂的逻辑和交互效果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值