在vue中实现antd的动态主题的代码示例

 更新时间:2024年07月17日 09:28:01   作者:淡淡的夏季  
在需求开发阶段,鉴于项目采用了antd作为基础组件库,确保组件外观与antd一致变得尤为重要,这包括颜色、字体大小及尺寸等样式的统一,然而,截至当前antd-vue尚未实现这一便捷的CSS变量特性,但理解其背后的实现机制后,我们可以自行构建这一功能,需要的朋友可以参考下

在需求开发阶段,鉴于项目采用了antd作为基础组件库,确保组件外观与antd一致变得尤为重要,这包括颜色、字体大小及尺寸等样式的统一。antd在其最新版本中,通过CSS变量(也称为CSS自定义属性)的形式,将所有样式整合至<style>标签内,极大地方便了开发者通过var(--antd-xxx)语法直接引用antd的样式设置。

然而,截至当前(版本4.2.3),antd-vue尚未实现这一便捷的CSS变量特性。但理解其背后的实现机制后,我们可以自行构建这一功能。

实现思路简述

  • 获取Antd样式:利用theme.userToken接口(或类似机制,具体依据antd-vue或自定义主题的接口而定),提取antd的样式定义。
  • 注入样式:将获取到的样式通过JavaScript动态地添加到HTML文档的<style>标签中,确保组件能够访问到这些CSS变量。
  • 动态更新:为了支持样式变量的动态变更(如主题切换),需监听theme.userToken或相关主题配置的变化,并实时更新DOM中的<style>标签内容,同时确保样式更新的单一性和高效性,避免冗余或冲突。

通过以上步骤,即使antd-vue当前版本未内置CSS变量支持,我们也能通过自定义实现来达成与antd样式的高度一致,提升开发效率和组件的可用性。

具体实现,下面代码复制到到本地,并允许即可

<!DOCTYPE html>
<html lang="zh-cn">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>

  <script src="https://registry.npmmirror.com/@babel/standalone/^7/files/babel.min.js"></script>
  <script src="https://registry.npmmirror.com/vue/3/files/dist/vue.global.js"></script>
  <script src="https://registry.npmmirror.com/dayjs/^1/files/dayjs.min.js"></script>
  <script src="https://registry.npmmirror.com/dayjs/1.11.11/files/plugin/customParseFormat.js"></script>
  <script src="https://registry.npmmirror.com/dayjs/1.11.11/files/plugin/advancedFormat.js"></script>
  <script src="https://registry.npmmirror.com/dayjs/1.11.11/files/plugin/weekday.js"></script>
  <script src="https://registry.npmmirror.com/dayjs/1.11.11/files/plugin/localeData.js"></script>
  <script src="https://registry.npmmirror.com/dayjs/1.11.11/files/plugin/weekOfYear.js"></script>
  <script src="https://registry.npmmirror.com/dayjs/1.11.11/files/plugin/weekYear.js"></script>
  <script src="https://registry.npmmirror.com/dayjs/1.11.11/files/plugin/quarterOfYear.js"></script>
  <script src="https://registry.npmmirror.com/ant-design-vue/4.2.3/files/dist/antd.min.js"></script>


  <style>
    .test {
      color: var(--antv-color-primary)
    }
  </style>
</head>

<body>
  <div id="root"></div>

  <script>
    Babel.registerPreset("env-plus", {
      presets: [
        [Babel.availablePresets["env"]],
        [Babel.availablePresets['react'], { pragma: 'h', pragmaFrag: "Fragment", }]
      ],
      plugins: [],
    });

    const toLine = (name) => {
      if (!name) return name
      return name.replace(/([A-Z])/g, '-$1').toLowerCase()
    }
  </script>


  <!-- 代码开始 -->
  <script type="text/babel" data-presets="env-plus">
    const { createApp, ref, h, watch } = Vue
    const { Button, ConfigProvider, theme, Table } = antd

    const { useToken } = theme

    
    const styleDom = document.createElement('style')
    document.head.appendChild(styleDom)

    const setCssVar = (data) => {
      const list = Object.entries((data)).map(([key, val]) => {
        return `--antv-${toLine(key)}: ${val}`
      }).join(';')

      const css = `:root { ${list} }`
      styleDom.textContent = css
    }


    const App = {
      setup() {

        const { token } = useToken()


        watch(token, (newToken) => {
          setCssVar(newToken)
        }, {
          immediate: true
        })
        
        
        const myTheme = ref({
          colorPrimary: 'red',
          colorTextHeading: 'red',
          colorText: 'red',
          fontWeightStrong: 400
        })

        const handleTheme = () => {
          myTheme.value.colorPrimary = myTheme.value.colorPrimary === 'red' ? 'green' : 'red'
        }

        const dataSource = [
          {
            key: '1',
            name: '胡彦斌',
            age: 32,
            address: '西湖区湖底公园1号',
          },
          {
            key: '2',
            name: '胡彦祖',
            age: 42,
            address: '西湖区湖底公园1号',
          },
        ];

        const columns = [
          {
            title: '姓名',
            dataIndex: 'name',
            key: 'name',
          },
          {
            title: '年龄',
            dataIndex: 'age',
            key: 'age',
          },
          {
            title: '住址',
            dataIndex: 'address',
            key: 'address',
          },
        ]

        return () => {
          return <ConfigProvider
            theme={{ token: myTheme.value }}
          >
            <Button type="primary" onClick={handleTheme}>切换主题</Button>
            <div class='test'>使用--antv-colorPrimary变量</div>

            <Table columns={columns} dataSource={dataSource} />
          </ConfigProvider>
        }
      },
    }



    const app = createApp(App)
    app.mount('#root')
  </script>
</body>

</html>

到此这篇关于在vue中实现antd的动态主题的代码示例的文章就介绍到这了,更多相关vue antd动态主题内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 在vue中实现禁止回退上一步,路由不存历史记录

    在vue中实现禁止回退上一步,路由不存历史记录

    这篇文章主要介绍了在vue中实现禁止回退上一步,路由不存历史记录,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-07-07
  • vue-cli系列之vue-cli-service整体架构浅析

    vue-cli系列之vue-cli-service整体架构浅析

    这篇文章主要介绍了vue-cli系列之vue-cli-service整体架构浅析,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-01-01
  • VUE页面中通过双击实现复制表格中内容的示例代码

    VUE页面中通过双击实现复制表格中内容的示例代码

    这篇文章主要介绍了VUE页面中通过双击实现复制表格中内容,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-06-06
  • vue开发利器之unplugin-auto-import的使用

    vue开发利器之unplugin-auto-import的使用

    unplugin-auto-import 解决了vue3-hook、vue-router、useVue等多个插件的自动导入,也支持自定义插件的自动导入,下面这篇文章主要给大家介绍了关于vue开发利器之unplugin-auto-import使用的相关资料,需要的朋友可以参考下
    2023-02-02
  • vue自定义实例化modal弹窗功能的实现

    vue自定义实例化modal弹窗功能的实现

    这篇文章主要介绍了vue自定义实例化modal弹窗,Vue.extend 属于Vue的全局 api,在实际业务开发中我们很少使用,因为相比常用的 Vue.component写法使用 extend 步骤要更加繁琐一些,本文结合实例代码给大家介绍的非常详细,需要的朋友参考下
    2022-09-09
  • vue 解决报错问题小结

    vue 解决报错问题小结

    最近入门vue,用字节跳动的arco初始化一个项目的时候报错自己解决后没来的及截图,从别人那拷贝个网图把,是一样的报错,本文给大家分享vue 解决报错问题小结,感兴趣的朋友一起看看吧
    2023-09-09
  • vue2与vue3下如何访问使用public下的文件

    vue2与vue3下如何访问使用public下的文件

    这篇文章主要介绍了vue2与vue3下如何访问使用public下的文件,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05
  • vue2移动端使用vue-qrcode-reader实现扫一扫功能的步骤

    vue2移动端使用vue-qrcode-reader实现扫一扫功能的步骤

    最近在使用vue开发的h5移动端想要实现一个调用摄像头扫描二维码的功能,所以下面这篇文章主要给大家介绍了关于vue2移动端使用vue-qrcode-reader实现扫一扫功能的相关资料,需要的朋友可以参考下
    2023-06-06
  • vue使用elementUI组件实现分页效果

    vue使用elementUI组件实现分页效果

    分页在展示数据列表的场景肯定是非常多的,一般的项目开发中,数据量特别大,一般都是后端接口直接处理分页返回,前端直接调用即可,本文给大家介绍了vue使用elementUI组件实现分页效果,需要的朋友可以参考下
    2023-12-12
  • vue+elementUI 实现内容区域高度自适应的示例

    vue+elementUI 实现内容区域高度自适应的示例

    这篇文章主要介绍了vue+elementUI 实现内容区域高度自适应的示例,帮助大家更好的理解和使用vue,感兴趣的朋友可以了解下
    2020-09-09

最新评论