Vuetify3特征(二)持续更新


Vuetify3特征

一、可访问性(a11y)

辅助功能(a11y)
Web 辅助功能(a11y)简称,指的是确保没有障碍物阻碍残疾人士与世界互联网上的网站进行交互或访问的包容性实践。Vuetify 组件的设计目的是为所有基于鼠标的操作提供键盘交互,并在适用的情况下利用 HTML5 语义化元素。

激活器插槽
Vuetify在许多组件中使用激活器插槽,例如v-menu、v-dialog等等。在某些情况下,这些激活器元素应该具有特定的辅助功能属性,将它们与对应内容关联起来。为了实现这一目的,我们通过插槽范围传递必要的辅助功能选项。

src/components/HelloWorld.vue

<template>
  <v-menu>
    <!-- 使用激活器插槽定义激活器元素 -->
    <template v-slot:activator="{ props }">
      <v-btn  v-bind="props">Click me</v-btn>
      <p>{{ props }}</p>
    </template>

    <!-- 下拉菜单内容 -->
    <v-list>
      <v-list-item @click="method">
        <v-list-item-title>Option 1</v-list-item-title>
      </v-list-item>

      <v-list-item disabled>
        <v-list-item-title>Option 2 (disabled)</v-list-item-title>
      </v-list-item>

      <v-list-item @click="method">
        <v-list-item-title>Option 3</v-list-item-title>
      </v-list-item>
    </v-list>
  </v-menu>
</template>

<script lang="ts">
export default {
  methods: {
    method() {
      // 处理选项点击时的操作
      console.log('Option clicked!');
    }
  }
}
</script>

在这里插入图片描述
aria-haspopup: “menu”
这个属性表示元素触发的行为会显示一个菜单或下拉框。当用户与这个元素交互时,屏幕阅读器和辅助技术可以根据这个信息告诉用户该元素与菜单相关联。

aria-expanded: “false”
这个属性表示当前元素的状态是否展开(expanded)或折叠(collapsed)。在这里,值为 “false” 表示元素是折叠状态,即相关内容当前不可见。

aria-owns: “v-menu-0”
这个属性指示当前元素拥有(owns)ID为 “v-menu-0” 的元素。这通常用于关联一个控制元素(比如按钮)与被控制的元素(比如菜单),让辅助技术能理解这种关系。

焦点管理和键盘交互

除了属性之外,诸如此类的组件还支持通过按下和在选项之间导航进行交互。v-menu↑↓
当处于 v-menu 内部时,将自动配置为具有菜单项(menuitem)的角色。

src/components/HelloWorld.vue

<template>
  <div class="text-center">
    <v-menu>
      <template v-slot:activator="{ props: activatorProps }">
        <v-btn text="Click me" v-bind="activatorProps"></v-btn>
      </template>

      <v-list>
        <v-list-item @click="onClick">
          <v-list-item-title>Option 1</v-list-item-title>
        </v-list-item>

        <v-list-item disabled>
          <v-list-item-title>Option 2</v-list-item-title>
        </v-list-item>

        <v-list-item @click="onClick">
          <v-list-item-title>Option 3</v-list-item-title>
        </v-list-item>
      </v-list>
    </v-menu>
  </div>
</template>
<script>
  export default {
    methods: {
      onClick () {
        // Perform an action
      },
    },
  }
</script>

在这里插入图片描述

二、别名

别名和虚拟组件
使用自定义别名对内置的 Vuetify 组件进行扩展,创建虚拟组件。

src/plugins/vuetify.js

import { createVuetify } from 'vuetify'
import { VBtn } from 'vuetify/components/VBtn'

export default createVuetify({
  aliases: {
    MyButton: VBtn,
    MyButtonAlt: VBtn,
  },
})

src/components/HelloWorld.vue

<template>
  <MyButton>自定义别名</MyButton>
  <MyButtonAlt>自定义别名</MyButtonAlt>
  <VBtn>原生按钮</VBtn>
</template>

<script lang="ts">

</script>

运行效果:
在这里插入图片描述

虚拟组件默认值

虚拟组件可以访问 Vuetify 的 全局配置。别名的默认配置和内置组件相同,并不需要额外步骤。在下面的示例中,MyButton 使用了 v-btn 属性来改变它默认的 variant 属性。

src/plugins/vuetify.js

import { createVuetify } from 'vuetify'
import { VBtn } from 'vuetify/components/VBtn'

export default createVuetify({
  aliases: {
    MyButton: VBtn,
  },
  defaults: {
    VBtn: { variant: 'flat' },// 简单、扁平的风格
    MyButton: { variant: 'tonal' },// 色调的
  },
})

src/components/HelloWorld.vue

<template>
  <MyButton>MyButton</MyButton>
  <VBtn>VBtn</VBtn>
</template>

<script lang="ts">

</script>

运行效果:
在这里插入图片描述
嵌套默认值

根据组件的阶层关系,可以设定对应组件的默认的属性来改变样式。在下面的示例中,
V-BTN型和 MyButton 嵌套在V卡组件内时的颜色。

src/plugins/vuetify.js

import { createVuetify } from 'vuetify'
import { VBtn } from 'vuetify/components/VBtn'

export default createVuetify({
  aliases: {
    MyButton: VBtn,
  },
  defaults: {
    MyButton: {
      color: 'primary',
      variant: 'tonal',
    },
    VBtn: {
      color: 'secondary',
      variant: 'flat',
    },
    VCard: {
      MyButton: { color: 'secondary' },
      VBtn: { color: 'primary' },
    },
  },
})

src/components/HelloWorld.vue

<template>
  <MyButton>MyButton</MyButton>
  <VBtn>VBtn</VBtn>
  <v-card>
    <MyButton>MyButton</MyButton>
    <VBtn>VBtn</VBtn>
  </v-card>
</template>

<script lang="ts">

</script>

运行效果:
在这里插入图片描述

三、应用程序布局

应用布局

Vuetify 提供了一个应用布局系统以便于轻松创建复杂的网站设计。

该系统是秉承着由外向内的原则建立的,每个应用程序布局组件都在四个方向(左、 右、上、下)之一的位置保留了空间,以此来为随后的其它布局组件留下可用空间。

以下构件与布局系统兼容:

v-app-bar
一个放置导航组件、品牌展示、搜索栏和操作按钮的容器

v-system-bar
取代原生手机系统栏的系统栏

v-navigation-drawer
一个持有站点导航链接的持久性或临时性的容器

v-footer
一个替换默认的 html 页脚的通用组件

v-bottom-navigation
一个具有导航链接且通常用于较小设备的持久性或临时性的容器

布局系统的最后部分是 v-main 组件。在这里放置页面内容。它将使用页面上所有布局组件保留其空间后剩余的空闲空间。

在以下示例中,v-app 已被 v-layout 替换。这是因为 v-app 的默认最小高度为 100vh。在您自己的应用程序中,您始终应该使用 v-app 作为根布局。

放置组件

默认情况下,布局组件试图保留空间的顺序只是它们在您的标记中出现的顺序。 为了说明这一概念, 查看以下两个示例:一个 v-app-bar 和 v-navigation-drawer 交换了位置。

src/components/HelloWorld.vue

<template>
  <v-layout class="rounded rounded-md">
    <!--    bar在drawer之前,bar占满一行  -->
    <v-app-bar title="Application bar"></v-app-bar>

    <v-navigation-drawer>
      <v-list>
        <v-list-item title="Navigation drawer"></v-list-item>
      </v-list>
    </v-navigation-drawer>

    <v-main class="d-flex align-center justify-center" style="min-height: 300px;">
      Main Content
    </v-main>
  </v-layout>
</template>

<script lang="ts">

</script>

运行效果:
在这里插入图片描述
src/components/HelloWorld.vue

<template>
  <v-layout class="rounded rounded-md">
    <v-navigation-drawer>
      <v-list>
        <v-list-item title="Navigation drawer"></v-list-item>
      </v-list>
    </v-navigation-drawer>
<!--   bar在drawer之后 drawer占满一列-->
    <v-app-bar title="Application bar"></v-app-bar>

    <v-main class="d-flex align-center justify-center" style="min-height: 300px;">
      Main Content
    </v-main>
  </v-layout>
</template>

运行效果:
在这里插入图片描述
正如您所看到的,将 v-app-bar 放在 v-navigation-drawer 之前意味着它将使用屏幕的整个宽度。当它放在 v-navigation-drawer 之后时,它将只使用剩下的空闲空间。

一些布局组件接受位置属性(location prop),通过该属性,您可以在布局中放置组件。在下面的示例中,我们使用两个 v-navigation-drawer 组件,在应用程序的两侧各放置一个。
src/components/HelloWorld.vue

<template>
  <v-layout class="rounded rounded-md">
    <v-app-bar color="surface-variant" title="Application bar"></v-app-bar>
    
<!--  默认为左  -->
    <v-navigation-drawer>
      <v-list>
        <v-list-item title="Drawer left"></v-list-item>
      </v-list>
    </v-navigation-drawer>
<!--  指定位置为右  -->
    <v-navigation-drawer location="right">
      <v-list>
        <v-list-item title="Drawer right"></v-list-item>
      </v-list>
    </v-navigation-drawer>

    <v-main class="d-flex align-center justify-center" style="min-height: 300px;">
      Main Content
    </v-main>
  </v-layout>
</template>

运行效果:
在这里插入图片描述
复杂布局

让我们创建一个更复杂的布局来展示系统的灵活性。在下面的示例中,我们重新创建了 Discord 应用程序的一般布局。这个例子还展示了布局组件接受宽度或高度属性,以及同一类型的多个组件可以堆叠在同一位置的功能。
src/components/HelloWorld.vue

<template>
  <v-layout class="rounded rounded-md">
    <v-system-bar color="grey-darken-3"></v-system-bar>

    <v-navigation-drawer
      color="grey-darken-2"
      permanent
      width="72"
    ></v-navigation-drawer>

    <v-navigation-drawer
      color="grey-darken-1"
      permanent
      width="150"
    ></v-navigation-drawer>

    <v-app-bar
      color="grey"
      flat
      height="48"
    ></v-app-bar>

    <v-navigation-drawer
      color="grey-lighten-1"
      location="right"
      permanent
      width="150"
    ></v-navigation-drawer>

    <v-app-bar
      color="grey-lighten-2"
      flat
      height="48"
      location="bottom"
    ></v-app-bar>

    <v-main class="d-flex align-center justify-center" style="min-height: 300px;">
      Main Content
    </v-main>
  </v-layout>
</template>

运行效果:
在这里插入图片描述

动态布局和顺序

在大多数情况下,简单地按照正确的顺序将布局组件放置在标记中即可实现您想要的布局。然而,在某些情况下这可能不可行。其中一个情况是,如果您希望动态更改布局组件的顺序。

为了解决这个问题,您可以通过使用 order 属性来显式设置布局顺序。请看下面的示例,了解在使用该属性时会发生什么。通过切换开关,您可以将应用栏的顺序更改为 -1,从而将其放置在布局顺序中导航抽屉的上方。(越小表示优先级越高)

所有布局组件的默认顺序都是 0。具有相同顺序的布局组件将按照它们在标记中的出现顺序进行排序。

src/components/HelloWorld.vue

<template>

  <v-layout class="rounded rounded-md">
    <v-navigation-drawer  color="grey-darken-2" permanent></v-navigation-drawer>

    <v-app-bar
      :order="order"
      color="grey-lighten-2"
      flat
      title="Application bar"
    >
      <template v-slot:append>
        <v-switch
          v-model="order"
          false-value="0"
          hide-details
          inset
          label="Toggle order"
          true-value="-1"
        ></v-switch>
      </template>
    </v-app-bar>

    <v-main class="d-flex align-center justify-center" style="min-height: 300px;">
      Main Content
    </v-main>
  </v-layout>
</template>
<script>
export default {
  data: () => ({
    order: 0,
  }),
}
</script>

运行效果:
在这里插入图片描述
在这里插入图片描述
获取布局信息

布局系统提供了一个getLayoutItem 函数,可用于获取标记中特定布局组件的大小和位置信息。你可以在布局组件中添加一个nameprop并给他一个特殊的值来使用该函数。你也可以使用v-app上的 ref 访问该方法,或者使用useLayout 组合式函数访问该方法。

ref 方式:
src/components/HelloWorld.vue

<template>
  <v-layout ref="app" class="rounded rounded-md">
    <v-app-bar color="grey-lighten-2" name="app-bar">
      <v-btn class="mx-auto" @click="print('app-bar')">Get data</v-btn>
    </v-app-bar>

    <v-navigation-drawer
      color="grey-darken-2"
      location="end"
      name="drawer"
      permanent
    >
      <div class="d-flex justify-center align-center h-100">
        <v-btn @click="print('drawer')">Get data</v-btn>
      </div>
    </v-navigation-drawer>

    <v-main class="d-flex align-center justify-center" style="min-height: 300px;">
      Main Content
    </v-main>

    <v-footer
      name="footer"
      app
    >
      <v-btn
        class="mx-auto"
        variant="text"
        @click="print('footer')"
      >
        Get data
      </v-btn>
    </v-footer>
  </v-layout>
</template>
<script>
export default {
  methods: {
    print (key) {
      alert(JSON.stringify(this.$refs.app.getLayoutItem(key), null, 2))
    },
  },
}
</script>

运行效果:
在这里插入图片描述

组合式函数方式:
src/components/HelloWorld.vue

<template>
  <v-layout ref="app" class="rounded rounded-md">
    <v-app-bar color="grey-lighten-2" name="app-bar">
      <child v-slot="{ print }">
        <v-btn class="mx-auto" @click="print('app-bar')">Get data</v-btn>

      </child>
    </v-app-bar>

    <v-navigation-drawer
      color="grey-darken-2"
      name="drawer"
      permanent
    >
      <div class="d-flex justify-center align-center h-100">
        <child v-slot="{ print }">
          <v-btn @click="print('drawer')">Get data</v-btn>
        </child>
      </div>
    </v-navigation-drawer>

    <v-main class="d-flex align-center justify-center" style="min-height: 300px;">
      Main Content
    </v-main>

    <v-footer
      name="footer"
      app
    >
      <v-btn
        class="mx-auto"
        variant="text"
        @click="print('footer')"
      >
        Get data
      </v-btn>
    </v-footer>
  </v-layout>
  <test></test>
</template>
<script>
import { useLayout } from 'vuetify'
// 声明一个子组件,提供了一个打印坐标的方法
// useLayout 必须在子组件中发生,以便布局能够被正确注入。
const Child = {
  setup (props, ctx) {
    const { getLayoutItem } = useLayout()

    function print (key) {
      alert(JSON.stringify(getLayoutItem(key), null, 2))
    }

    return () => ctx.slots.default({ print })
  },
}

export default {
  components: { Child },
}
</script>

在这里插入图片描述
所有布局组件的合并大小也可在 layout.mainRect下使用。 此选项由 v-main 组件内部使用,用于确定主要内容区域的大小。
src/components/HelloWorld.vue

<template>
  <v-main :style="{width: layout.mainRect.width,height: layout.mainRect.height}" class="bg-amber-lighten-1">
    自定义布局大小
  </v-main>
</template>
<script setup>
  import {red} from "vuetify/util/colors";

  let layout = {
    mainRect:{
      width:'1000px',
      height:'800px'
    }
  }


</script>

运行效果:
在这里插入图片描述

四、蓝图

Vuetify 蓝图是一种为整个应用程序预配置不同的设计系统的新方法。

使用
蓝图是 Vuetify 配置选项的集合,可为组件、颜色、语言等指定默认值。

空白标签概念
虽然 Vuetify 是在 Google 的 Material Design
规范的掩盖下构建的,但它仍然足够灵活,可用作任何设计系统的基础。默认情况下,Vuetify 组件没有颜色,其本质是white-label。white-label 产品是指由一家公司生产的产品或服务,由其他公司进行品牌重塑,使其看起来像是自己生产的。
可用蓝图
Material Design 1 2014 ✅ 可用 规格
Material Design 2 2017 ✅ 可用 规格
Material Design 3 2022 ✅ 可用 规格

打开项目的 vuetify.js 文件并导入所需的蓝图。下面的示例演示了如何应用
Material Design 1 预设:
最初的 Material Design 设计规格在 2014 年发布,目的是创造一种将原则、设计和创新结合起来的视觉语言。

plugins/vuetify.js

import { createVuetify } from 'vuetify'
import { md1 } from 'vuetify/blueprints'

export default createVuetify({
  blueprint: md1,
})

src/components/HelloWorld.vue

<template>
  <v-main :style="{width: layout.mainRect.width,height: layout.mainRect.height}" >
    <VBtn>BUTTON</VBtn>
    <v-tab>ONE</v-tab>
    <v-tab>TWO</v-tab>
    <v-tab>THREE</v-tab>
  </v-main>
</template>
<script setup>
  import {red} from "vuetify/util/colors";

  let layout = {
    mainRect:{
      width:'1000px',
      height:'800px'
    }
  }


</script>

运行效果:
在这里插入图片描述

Material Design 2 预设:
于 2017 年发布,第 2 版的设计规范获得了大量的新组件更新。 并且以极为成功的第一版设计规范为基础,修改了指导原则。
修改plugins/vuetify.js

import { createVuetify } from 'vuetify'
import { md2 } from 'vuetify/blueprints'

export default createVuetify({
  blueprint: md2,
})

运行效果:
在这里插入图片描述
Material Design 3 预设:
Material Design 3 目前正在积极开发中,它代表了谷歌的设计系统的新篇章。

修改plugins/vuetify.js

import { createVuetify } from 'vuetify'
import { md3 } from 'vuetify/blueprints'

export default createVuetify({
  blueprint: md3,
})

运行效果
在这里插入图片描述

五、日期(Dates)

轻松使用用于需要日期功能的组件(如日期选取器和日历)的日期库。
此特性在 v3.4.0 (Blackguard)版本引入。

使用
组合式日期提供一个共享架构,用于日期选择器和日历等组件。默认实现是使用原生日期对象构建的,但可以切换到其它日期库。如果没有给出其他日期适配器,则使用默认的 Vuetify 实现。

在您的应用程序中,导入 useDate 函数并通过它来使用日期组合式函数。
src/views/Date.vue

<script setup lang="ts">
import { useDate } from 'vuetify'

const date = useDate()
//JavaScript中的月份是从0开始记数的,即1代表一月,2代表二月,以此类推
console.log("日期 " + date.getMonth(new Date('March  1, 2021'))) // 3
console.log("日期 " + date.getMonth(new Date('2022/4/1'))) // 4
</script>

<template>

</template>

<style scoped>

</style>

控制台输出:
在这里插入图片描述
格式选项
日期组合式函数支持以下日期格式化选项:
如需要更详细的api信息请点击api跳转

格式名称输出格式
fullDate“Jan 1, 2024”
fullDateWithWeekday“Tuesday, January 1, 2024”
normalDate“1 January”
normalDateWithWeekday“Wed, Jan 1”
shortDate“Jan 1”
year“2024”
month“January”
monthShort“Jan”
monthAndYear“January 2024”
monthAndDate“January 1”
weekday“Wednesday”
weekdayShort“Wed”

下面的示例展示了如何使用日期组合式函数格式化日期字符串:

src/views/Date.vue

<script setup lang="ts">
import {useDate} from "vuetify";

let date = useDate();
const formatted = date.format('2010-04-13', 'fullDateWithWeekday')
console.log(formatted) // Tuesday, April 13, 2010
</script>

<template>

</template>

<style scoped>

</style>

运行效果:
在这里插入图片描述

API

特性描述
useDate日期组合式函数用于需要日期功能的组件。

适配器
内置日期适配器实现DateIOFormats接口。因此,可以很容易地在支持的任何日期库中交换日期-io.。统一规范,配置了适配器就不能再使用其他的日期库。
src/plugins/vuetify.js
安装luxon:pnpm install --save luxon
如果是ts还需要安装:pnpm install --save-dev @types/luxon(目的是声明这个库的类型)

import { createVuetify } from 'vuetify'
import LuxonAdapter from "@date-io/luxon"

export default createVuetify({
  date: {
    adapter: LuxonAdapter,
  },
})

对于 TypeScript 用户,当使用 LuxonAdapter 时可能会需要进行模块增强(module augmentation)。通过模块增强,你可以扩展已有的接口或类型,以适配 LuxonAdapter 的需求。这样可以确保 TypeScript 在 LuxonAdapter 的使用中能够提供更好的类型检查和提示。

对于 TypeScript 用户,还公开了模块扩充 模块扩充说明
src/plugins/vuetify.js

 export default createVuetify({
  ...
})

declare module 'vuetify' {
  namespace DateModule {
    interface Adapter extends LuxonAdapter {}
  }
}

本地化 (Localization)
关于本地化(Localization)和日期(Date)的配置在 Vuetify 应用中非常重要,因为它们决定了应用如何根据不同的地区或国家显示内容和格式。
src/plugins/vuetify.js

import {createVuetify} from 'vuetify'
export default createVuetify({
  date: {

    locale: {
      en: 'zh-CN',//zh-CN(简体中文):
    },
  },
  locale: {
    locale: 'zh',//zh(中文的通用代码):
  },

})

src/App.vue

<!-- App.vue -->

<template>

  <v-app>

  </v-app>

</template>

<script lang="ts" setup>
import { useDate } from 'vuetify'
const date = useDate()
const formatted = date.format('2010-04-13', 'fullDateWithWeekday')
console.log(formatted)
</script>

运行效果:
在这里插入图片描述
自定义适配器

要实现您自己的日期适配器,请使用 DateAdapter 接口:
import type { DateAdapter } from 'vuetify/labs'

export interface DateAdapter<TDate> {
  date (value?: any): TDate | null
  format (date: TDate, formatString: string): string
  toJsTDate (value: TDate): TDate
  parseISO (date: string): TDate
  toISO (date: TDate): string

  startOfDay (date: TDate): TDate
  endOfDay (date: TDate): TDate
  startOfMonth (date: TDate): TDate
  endOfMonth (date: TDate): TDate
  startOfYear (date: TDate): TDate
  endOfYear (date: TDate): TDate

  isBefore (date: TDate, comparing: TDate): boolean
  isAfter (date: TDate, comparing: TDate): boolean
  isEqual (date: TDate, comparing: TDate): boolean
  isSameDay (date: TDate, comparing: TDate): boolean
  isSameMonth (date: TDate, comparing: TDate): boolean
  isValid (date: any): boolean
  isWithinRange (date: TDate, range: [TDate, TDate]): boolean

  addDays (date: TDate, amount: number): TDate
  addMonths (date: TDate, amount: number): TDate

  getYear (date: TDate): number
  setYear (date: TDate, year: number): TDate
  getDiff (date: TDate, comparing: TDate | string, unit?: string): number
  getWeekArray (date: TDate): TDate[][]
  getWeekdays (): string[]
  getMonth (date: TDate): number
  setMonth (date: TDate, month: number): TDate
  getNextMonth (date: TDate): TDate
}

六、显示 & 平台

显示组合式函数提供了关于当前设备的大量信息。

使用

useDisplay 组合式函数提供了关于当前设备多个方面的信息。
这样,您就可以根据窗口大小、设备类型和 SSR(服务端渲染) 状态来控制应用程序的各个方面。此可组合类可与网格和其他响应式实用工具类(例如显示)配合使用。

以下展示了如何访问应用的显示信息:
src/App.vue

<template>

  <v-app>

  </v-app>

</template>

<script lang="ts" setup>
import {useDisplay} from 'vuetify'
import {onMounted} from "vue";
let {mobile} = useDisplay();
onMounted(()=>{
  console.log(mobile.value) // 判断当前是否是移动设备 false
})
</script>

如果你仍旧在使用 Vue 的选项式 API,那么你可以使用全局变量 $vuetify 来获得显示的信息。注意在选项式 API 中,refs 引用无需使用 即可访问。.value

<script>
  export default {
    mounted () {
      console.log(this.$vuetify.display.mobile)
    },
  }
</script>

应用程序接口

组件描述
useDisplay组合式函数

关键点大小和阈值

阈值用于生成 vuetify 的 useDisplay 可组合组件中看到的各种断点(特点屏幕宽度)的范围。该系统从 xs 开始(起始像素值为 0px),采用“及更高”的思维模式。下面显示了默认阈值。

在这里插入图片描述

这些范围为可访问的各种附加/属性AndUpAndDownuseDisplay

{
  smAndDown: boolean // < 960px
  smAndUp: boolean // > 600px
  mdAndDown: boolean // < 1280px
  mdAndUp: boolean // > 960px
  lgAndDown: boolean // < 1919px
  lgAndUp: boolean // > 1280px
  xlAndDown: boolean // < 2559px
  xlAndUp: boolean // > 1920px
}

选项

useDisplay 可组合项具有多个配置选项,例如定义断点的自定义值的功能。
例如,"阈值"选项会修改用于视口计算的值。以下代码片段重写了xs至lg的阈值,并将mobileBreakpoint(移动断点)设置为“.sm”
src/plugins/vuetify.js

import { createVuetify} from 'vuetify'
export default createVuetify({
  display: {
    mobileBreakpoint: 'sm',//移动端断点设置为 'sm' 以下时应用移动端的样式布局
    thresholds: {
      xs: 0,
      sm: 340,
      md: 540,
      lg: 800,
      xl: 1280,
    },
  },
})

在下面的示例中,我们使用 switch 语句和当前断点名称来修改V卡元件:根据当前设备大小动态计算卡片的高度。
src/App.vue

<!-- App.vue -->

<template>

  <v-app>
    <v-card :height="height" >

    </v-card>
  </v-app>

</template>

<script lang="ts" setup>
import {useDisplay} from "vuetify";
import {computed} from "vue";

let display = useDisplay();
const height = computed(() => {
  console.log(display.name.value)
  switch (display.name.value){

    case 'xs':return 220
    case 'sm':return 400
    case 'md':return 500
    case 'lg':return 600
    case 'xl':return 800
    case 'xxl':return 1200
  }
})

</script>

接口(屏幕大小判定条件)
接口

{
  // Breakpoints
  xs: boolean // 0 - 595
  sm: boolean // 600 - 959
  md: boolean // 960 - 1279
  lg: boolean // 1280 - 1919
  xl: boolean // > 1920
  xxl: boolean
  smAndDown: boolean // < 960
  smAndUp: boolean // > 600
  mdAndDown: boolean // < 1280
  mdAndUp: boolean // > 960
  lgAndDown: boolean // < 1919
  lgAndUp: boolean // > 1280
  xlAndDown: boolean
  xlAndUp: boolean // < 1920

  // true if screen width < mobileBreakpoint
  mobile: boolean
  mobileBreakpoint: number | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'

  // Current breakpoint name (e.g. 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl')
  name: string

  // The current value of window.innerHeight and window.innerWidth
  height: number
  width: number

  // Device userAgent information
  platform: {
    android: boolean
    ios: boolean
    cordova: boolean
    electron: boolean
    chrome: boolean
    edge: boolean
    firefox: boolean
    opera: boolean
    win: boolean
    mac: boolean
    linux: boolean
    touch: boolean
    ssr: boolean
  }

  // The values used to make Breakpoint calculations
  thresholds: {
    xs: number
    sm: number
    md: number
    lg: number
    xl: number
    xxl: number
  }
}

此示例中,我们将演示如何在移动断点处于活动状态时切换 fullscreen 属性。v-dialog
src/App.vue

<template>
  <v-dialog :fullscreen="mobile">  <!--如果是移动设备显示全屏-->
    ...
  </v-dialog>
</template>

<script setup>
  import { useDisplay } from 'vuetify'

  const { mobile } = useDisplay()
</script>

断点条件语句
断点和条件值是从当前视口大小推导出的布尔值。此外,断点组合遵循 Vuetify 栅格的命名约定,并且可以访问诸如 xlOnly、xsOnly、mdAndDown 等属性。

在以下示例中,我们使用 setup 函数将 xs 和 mdAndUp 的值传递给我们的模板。

<template>
  <!--  当前设备>960 最小高度为300 否则为20vh  -->
  <!--  当前设备为<600 边框变圆框 -->

  <v-sheet :min-height="mdAndUp ? 300 : '20vh'"

           :rounded="xs"

           style="border: solid 1px red"
  >
    ...
  </v-sheet>
</template>

<script setup>
import {useDisplay} from 'vuetify'

// Destructure only the keys you want to use
const {xs, mdAndUp} = useDisplay()
</script>

使用动态显示值,我们可以调整v形薄板的最小高度在中等断点或更大断点上时为300,并且仅在超小屏幕上显示圆角.

组件移动断点
Vuetify 中的某些组件具有 mobile-breakpoint 属性,允许您覆盖默认值。这些组件引用在运行时使用文件中提供的选项生成的全局 mobileBreakpoint 值。vuetify.js

以下组件内置了对 mobile-breakpoint 属性的支持:

元件
V-横幅
V-导航抽屉
V-幻灯片组

默认情况下,mobileBreakpoint 设置为 lg,这意味着如果窗口宽度小于 1280 像素(这是 lg 阈值的默认值),则 useDisplay 可组合项会将其移动值更新为 。true
例如,
V-横幅
组件在移动设备和桌面设备上实现不同的样式。在以下示例中,第一个横幅使用 lg 的全局移动断点值,而第二个横幅使用 580 覆盖此默认值:
src/App.vue

<template>
  <div>
    <v-banner>
      ...
    </v-banner>

    <v-banner mobile-breakpoint="580">
      ...
    </v-banner>
  </div>
</template>

<script setup>
  import { onMounted } from 'vue'
  import { useDisplay } from 'vuetify'

  const { width, mobile } = useDisplay()

  onMounted(() => {
    console.log(width.value) // 960
    console.log(mobile.value) // true
  })
</script>

useDisplay 覆盖
将自定义 mobileBreakpoint 值直接指定到useDisplay可组合并覆盖全局值。在以下示例中,我们使用自定义 mobileBreakpoint 值 580:
src/App.vue

<script setup>
import { onMounted } from 'vue'
import { useDisplay } from 'vuetify'
let mobileBreakpoint = 580
const { mobile } = useDisplay({ mobileBreakpoint })

// Given a viewport width of 960px
onMounted(() => {
  console.log(mobile.value) // false
})
</script>

如果为 name 参数提供值,请利用 displayClasses 属性将相应的类应用于组件。在下一个示例中,以下类将应用于组件的根元素:
src/App.vue

 <template>
  <!-- 根据条件显示特定的类 -->
  <!--   当是移动设备是添加类名 v-component-mobile-->
  <div
    :class="[
      displayClasses,
    ]"
  >

  </div>
</template>

<script setup>
import {useDisplay} from 'vuetify'

// 导入 useDisplay 函数,用于处理显示逻辑
let mobileBreakpoint = 580

const {displayClasses} = useDisplay({mobileBreakpoint}, 'v-component')
// 使用 useDisplay 函数,传递参数 mobileBreakpoint 和组件的名称 'v-component' 来获取 displayClasses 属性
</script>

如果省略 name 参数,displayClasses 将使用 Vue 设置的默认名称。以下示例使用本地组件的默认名称:
src/App.vue

<template>
 <!-- 默认名 v-navigation-drawer--mobile-->
  <v-app>
    <v-navigation-drawer
      :class="[
        displayClasses
      ]"
    >
      ...
    </v-navigation-drawer>
  </v-app>

</template>

<script setup>
import {useDisplay} from 'vuetify'

const {displayClasses} = useDisplay()
</script>

七、全局配置

Vuetify允许您在设置应用程序时全局或针对每个组件设置默认 prop 值。利用这一功能,您可以例如在所有组件上禁用涟漪效果,或为所有对话框或按钮设置默认的高程值(组件的阴影和深度效果)。
起步
在Vuetify配置对象的defaults属性中使用默认属性值。在这里,我们已禁用了所有支持涟漪效果的组件的涟漪效果,并为所有组件设置了默认的高程值。
src/plugins/vuetify.ts

import { createApp } from 'vue'
import { createVuetify } from 'vuetify'
export default createVuetify({
  defaults: {
    global: {
      ripple: false,
    },
    VSheet: {
      elevation: 4,
    },
  },
})

上下文默认值

配置也可以针对嵌套在其他组件中的组件进行设置,例如,如果您想为嵌套在一个按钮组件内的所有组件设置默认变体:。
src/plugins/vuetify.ts

createVuetify({
  defaults: {
    VCard: {
      VBtn: { variant: 'outlined' }, // 变体:轮廓
    },
  },
})

效果:
在这里插入图片描述

一些组件已在内部使用这一功能:
在嵌套在 或 内时,具有 variant=“text”。
在嵌套在 内时,具有 bg-color=“transparent”。
列表、芯片组、展开面板、选项卡和表单等使用这个系统来将特定的属性传播到其子组件中,例如 < v-tabs disabled> 会为其内所有组件设置 disabled=“true”。
< v-defaults-provider > 可用于为特定范围内的组件设置默认值。

全局类和样式

定义全局类和样式适用于所有内置组件,包括虚拟组件。这在构建应用程序设计系统时提供了巨大的便利,并减少了模板中重复代码的数量。

假设您想将所有 v-btn 组件的 text-transform 设置为 none,但不想使用SASS变量。通过简单地将样式属性添加到组件的默认值中,您可以将自定义值应用于该组件的所有实例。

以下代码示例修改了所有 组件的 text-transform CSS 属性:

src/plugins/vuetify.js

import { createVuetify } from 'vuetify'
import { VBtn } from 'vuetify/components/VBtn'

export default createVuetify({
  defaults: {
    VBtn: {
      style: 'text-transform: none;',
    },
  },
})


作为一种替代方案,可以应用实用类(utility classes)来实现相同的效果:
src/plugins/vuetify.js

import { createVuetify } from 'vuetify'
import { VBtn } from 'vuetify/components/VBtn'

export default createVuetify({
  defaults: {
    VBtn: {
      class: 'text-none',
    },
  },
})

此外,它适用于任何有效的 Vue 值类型,例如对象和数组:

import { createVuetify } from 'vuetify'
import { VBtn } from 'vuetify/components/VBtn'

export default createVuetify({
  defaults: {
    VBtn: {
      style: [{ textTransform: 'none' }],
    },
  },
})

注意在全局对象中无法使用 class 和 style,只能在特定的组件中使用。

与虚拟组件一起使用

不论您是在开发一个包装器框架还是为您的应用程序构建设计系统,虚拟组件都是一个强大的辅助工具。在 Vuetify 默认系统中,类和样式被视为普通的属性,但不同于在模板级别被覆盖,它们是被合并的。
src/plugins/vuetify.js

import { createVuetify } from 'vuetify'
import { VBtn } from 'vuetify/components/VBtn'

export default createVuetify({
  aliases: {
    VBtnPrimary: VBtn,
  },

  defaults: {
    VBtnPrimary: {
      class: ['v-btn--primary', 'text-none'],
    },
  },
})

现在,在模板中使用并应用自定义类:< v-btn-primary >
src/App.vue

<template>
  <v-app>
    <v-btn-primary ></v-btn-primary>
  </v-app>

</template>
<script setup lang="ts">
</script>

编译后,生成的HTML将包含全局定义的类和自定义类:
在这里插入图片描述

当您有多个变体(不同样式或状态)需要各自的类来作为目标时,这一点尤其有用:
src/App.vue

<template>
  <v-app>
    <v-main>
      <v-btn-primary>Primary</v-btn-primary>

      <span class="mx-2" />

      <v-btn-secondary>Secondary</v-btn-secondary>
    </v-main>
  </v-app>
</template>

<style>
.v-btn.v-btn--primary {
  background: linear-gradient(to right, #ff8a00, #da1b60);
  color: white;
}
.v-btn.v-btn--secondary {
  background: linear-gradient(to right, #da1b60, #ff8a00);
  color: white;
}
</style>

src/plugins/vuetify.ts

import { createVuetify } from 'vuetify'
import { VBtn } from 'vuetify/components/VBtn'

export default createVuetify({
  aliases: {
    VBtnPrimary: VBtn,
    VBtnSecondary:VBtn
  },

  defaults: {
    VBtnPrimary: {
      class: ['v-btn--primary', 'text-none',],
    },
    VBtnSecondary:{
      class:['v-btn--secondary','text-none']
    }
  },
})

运行效果:
在这里插入图片描述

请记住,虚拟组件不会继承其扩展的全局类或样式。例如,以下的Vuetify配置将使用 v-chip 作为虚拟组件的别名,如 < v-chip-primary >。
src/plugins/vuetify.js

 import { createVuetify } from 'vuetify'
import { VChip } from 'vuetify/components/VChip'

export default createVuetify({
  aliases: {
    VChipPrimary: VChip,
  },

  defaults: {
    VChipPrimary: {
      class: 'v-chip--primary',
    },
    VChip: {
      class: 'v-chip--custom',
    },
  },
})

src/App.vue

<template>
  <v-app>
    <v-main>
      <VChipPrimary></VChipPrimary>
      <VChip></VChip>

    </v-main>
  </v-app>
</template>

<style>

</style>

运行效果:当在模板中使用时,它不会具有类 和 v-chip–custom。
在这里插入图片描述

注意: 有些情况下,默认的类或样式可能会无意中传递给内部组件。这主要涉及表单输入和控件。

在自定义组件中使用
利用Vuetify默认引擎并像我们一样配置您的自定义组件。这个功能使得在应用程序中统一功能变得非常简单,并减少重复代码的量。

让我们通过创建一个接受单个prop的基本组件来示例说明:
src/components/MyComponent.vue

 <template>
  <div>I am {{ foo }}</div>
</template>

<script setup>
  defineProps({ foo: String })
</script>

现在,让我们将新组件添加到Vuetify-defaults配置对象中,并为其prop:foo分配一个默认值

src/plugins/vuetify.js

import { createVuetify } from 'vuetify'

export default createVuetify({
  defaults: {
    MyComponent: {
      foo: 'bar',
    },
  },
})

接下来,可组合函数导入 MyComponent.vue。此函数有两个可选参数:
props - 用于生成组件默认值的props对象
name - 组件的名称。这将用于引用您在Vuetify配置中定义的defaults键
在您的模板中,将 useDefaults 的返回值分配给一个变量,并将其传递给 defineProps:

<template>
  <div>I am {{ props.foo }}</div>
</template>

<script setup>
import { useDefaults } from 'vuetify'

//声明一个组件接收的 propsfoo
const _props = defineProps({ foo: String })
// 设置属性的默认值为全局配置项的值
const props = useDefaults(_props, 'MyComponent')
</script>

src/App.vue

<template>
  <v-app>
    <my-component1 >

    </my-component1>
  </v-app>
</template>

<style>

</style>

运行效果:
在这里插入图片描述
请注意,我们必须显式地使用模板中的对象。这是因为Vue会自动打开.prosdefineProps中的值

-<div>I am {{ foo }}</div>
+<div>I am {{ props.foo }}</div>

如果useDefaults函数未提供 name 参数,该参数是可选的,它将从组件的名称中推断。

嵌套默认值

在组件链中,可以为不同的组件分配嵌套的默认值。这提供了无数的方法来配置你的应用程序和其组件。
让我们基于之前的例子,通过创建一个新组件来进一步说明这一点。假设有一个 < MyComponent2 > 组件嵌套了一个 < MyComponent1 > 组件。
当定义这些组件的默认值时,你可以确保这些嵌套组件也具有自己的默认值设置。
这在编写复杂的组件树时非常有用,允许开发者通过层级结构进行配置和覆盖默认值。
这样,即使是最内层的组件也可以有默认的配置设置而不影响上层或根级组件的配置设置。每个嵌套级别的默认值可以提供该组件在不同情境下工作的各种参数选项。

现在,让我们添加到Vuetify默认配置对象中,并为所有嵌套组件的prop分配一个默认值:

src/components/MyComponent1.vue

<template>
  <v-app>
    <v-main>
      <MyComponent1/>
      <!--      引入组件1   -->
      <MyComponent2>
        <MyComponent1/> <!-- I am baz -->
      </MyComponent2>
      <!--   引入组件2 嵌套组件1   -->
    </v-main>
  </v-app>
</template>

<script setup>

</script>

src/components/MyComponent2.vue

<template>
 <slot></slot>
</template>

<script setup>
import { useDefaults } from 'vuetify'
useDefaults()

</script>

src/plugins/vuetify.ts

import { createVuetify } from 'vuetify'

export default createVuetify({
  defaults: {
    MyComponent1: { foo: 'bar' },

    MyComponent2: {
      MyComponent1: { foo: 'baz' },
    },

  }
})

运行效果:
在这里插入图片描述

八、图标字体

Vuetify 出厂时支持四种流行的图标字体库,分别是 Material Design IconsMaterial IconsFont Awesome 4Font Awesome 5

MDI - 图标搜索

使用此工具可搜索任何 Material Design 图标,并通过单击项目将其复制到剪贴板。

单击跳转MDI-图标搜索工具

Material Design 图标

这是 Vuetify 使用的默认图标集。它支持使用构建过程或 CDN 链接进行本地安装。下面显示了如何将 CDN 链接添加到您的:

MDI - CSS

< link href="https://cdn.jsdelivr.net/npm/@mdi/font@5.x/css/materialdesignicons.min.css" rel="stylesheet " >

或者作为本地依赖:

pnpm add @mdi/font -D

import '@mdi/font/css/materialdesignicons.css' // Ensure you are using css-loader
import { createVuetify } from 'vuetify'

export default createVuetify({
  icons: {
    defaultSet: 'mdi', //这已经是默认值-仅用于显示
  },
})

注意:请勿在未指定包版本的情况下使用 CDN 链接。如果不这样做,可能会导致应用程序在新版本中发生意外更改。

MDI - JS SVG
在为生产环境优化应用程序时,建议安装此选项,因为只有内部用于 Vuetify 组件的图标才会导入到应用程序包中。您需要为应用程序的其余部分提供自己的图标。

src/plugins/vuetify.ts

import { createVuetify } from 'vuetify'
import { aliases, mdi } from 'vuetify/iconsets/mdi-svg'

export default createVuetify({
  icons: {
    defaultSet: 'mdi',
    aliases,
    sets: {
      mdi,
    },
  },
})

以下示例演示如何在 SFC(单文件组件) 模板中使用导入的图标:
注意:必须先在src/plugins/vuetify.ts配置mdi-svg才能使用

安装MDI - JS 

pnpm add @mdi/js -D

src/App.vue

<template>
  <v-app>
    <v-icon :icon="mdiAccount" />
  </v-app>

</template>

<script setup>
import { mdiAccount } from '@mdi/js'
</script>

或者,可以将要使用的图标添加为别名,以简化重用:

src/plugins/vuetify.ts

import { createVuetify } from 'vuetify'
import { aliases, mdi } from 'vuetify/iconsets/mdi-svg'
import { mdiAccount } from '@mdi/js'

export default createVuetify({
  icons: {
    defaultSet: 'mdi',
    aliases: {
      ...aliases,
      account: mdiAccount,
    },
    sets: {
      mdi,
    },
  },
})

src/App.vue

<template>
  <v-app>
    <!--  访问图标别名语法: $别名   -->
    <v-icon icon="$account"/>
  </v-app>

</template>

<script setup>

</script>

Material 图标

对于没有构建过程的项目,推荐直接使用 CDN 导入图标。

Material 图标 - CSS

<link href="https://fonts.googleapis.com/css?family=Material+Icons" rel="stylesheet">

默认情况下,有一些 Material 图标是缺失的。例如,person 和 visibility 是可用的,但 person_outline 不可用,而 visibility_outline 是可用的。要使用这些缺失的图标,请将现有的图标分别替换为以下内容:
person 替换为 person_outline
visibility 替换为 visibility_outline

<link
  rel="stylesheet"
  href="https://fonts.googleapis.com/css?family=Material+Icons|Material+Icons+Outlined|Material+Icons+Two+Tone|Material+Icons+Round|Material+Icons+Sharp"
/>

另外,你可以使用 yarn 或 npm 在本地安装。请记住,这不是官方的 Google 仓库,可能不包含所有图标。

pnpm add material-design-icons-iconfont -D

src/plugins/vuetify.js

import 'material-design-icons-iconfont/dist/material-design-icons.css' // 确保您的项目能够处理css文件files
import { createVuetify } from 'vuetify'
import { aliases, md } from 'vuetify/iconsets/md'

export default createVuetify({
  icons: {
    defaultSet: 'md',
    aliases,
    sets: {
      md,
    },
  },
})

src/App.vue

<template>
  <v-icon icon="home" />
</template>

Font Awesome图标

使用 FontAwesome 最简单的方式是使用 CDN。

<link href="https://use.fontawesome.com/releases/v5.0.13/css/all.css" rel="stylesheet">

要本地安装,你可以使用你最喜爱的包管理安装 FontAwesome 的免费版本:

pnpm add @fortawesome/fontawesome-free -D

src/plugins/vuetify.js

import '@fortawesome/fontawesome-free/css/all.css' // 确保运行效果需要引用css文件
import { createVuetify } from 'vuetify'
import { aliases, fa } from 'vuetify/iconsets/fa'

export default createVuetify({
  icons: {
    defaultSet: 'fa',
    aliases,
    sets: {
      fa,
    },
  },
})

src/App.vue

<template>
  <v-icon icon="fas fa-home" />
</template>

FA 4 - CSS
使用 FontAwesome 最简单的方式是使用 CDN。

<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.x/css/font-awesome.min.css" rel="stylesheet">
pnpm add font-awesome@4.7.0 -D
import 'font-awesome/css/font-awesome.min.css' // Ensure your project is capable of handling css files
import { createVuetify } from 'vuetify'
import { aliases, fa } from 'vuetify/iconsets/fa4'
// 在本地安装FontAwesome 4与其新版本相同,只是来自不同的软件包。您将使用fortawesome该程序包,而不是@font-awesome
export default createVuetify({
  icons: {
    defaultSet: 'fa',
    aliases,
    sets: {
      fa,
    },
  },
})

src/App.vue

<template>
  <v-icon icon="fa-check" />
</template>

FA 5 - SVG

pnpm add @fortawesome/fontawesome-svg-core @fortawesome/vue-fontawesome @fortawesome/free-solid-svg-icons @fortawesome/free-regular-svg-icons -D

然后注册全局组件并使用预定义的图标集。如果您有权访问 Font Awesome Pro 图标,则可以以相同的方式将它们添加到库中。

src/plugins/vuetify.ts


//设置使用fa-svg
import { createVuetify } from 'vuetify'
import { aliases, fa } from 'vuetify/iconsets/fa-svg'

export default createVuetify({
  icons: {
    defaultSet: 'fa',
    aliases,
    sets: {
      fa,
    },
  },
})

src/plugins/index.ts

// Plugins
import vuetify from './vuetify'

// Types
import type { App } from 'vue'

import {library} from "@fortawesome/fontawesome-svg-core";
import {FontAwesomeIcon} from "@fortawesome/vue-fontawesome";
import {fas} from "@fortawesome/free-solid-svg-icons";
import {far} from "@fortawesome/free-regular-svg-icons";
export function registerPlugins (app: App) {
  app.component('font-awesome-icon',FontAwesomeIcon) //注册一个全局组件,在任何 Vue 组件的模板中使用 <font-awesome-icon icon="图标名"></font-awesome-icon> 显示一个咖啡
  // 将所有实心图标添加到图标库中
  library.add(fas)
  // 将 Font Awesome 图标库中的所有轮廓(Regular)样式的图标集合添加到应用程序的图标库中
  library.add(far)

  app.use(vuetify)
}

内置别名
可以在 Vuetify 组件中使用图标别名插入图标。
需要引入是mdi才能使用

import '@mdi/font/css/materialdesignicons.css' // Ensure you are using css-loader
import { createVuetify } from 'vuetify'

export default createVuetify({
  icons: {
    defaultSet: 'mdi', // This is already the default value - only for display purposes
  },
})

在这里插入图片描述

配置多个图标集

开箱即用,Vuetify 支持同时使用多个不同的图标集。以下示例演示了如何将默认图标字体更改为 Font Awesome,同时仍通过使用前缀保持对原始 Material Design Icons

src/plugins/vuetify.ts

//设置使用fa-svg
import { createVuetify } from 'vuetify'
import { aliases, fa } from 'vuetify/iconsets/fa-svg'
import {mdi} from "vuetify/iconsets/mdi";
import '@mdi/font/css/materialdesignicons.css'
export default createVuetify({
  icons: {
    defaultSet: 'mdi',
    aliases,
    sets: {
      fa,
      mdi
    },
  },
})

src/plugins/index.ts

// Plugins
import vuetify from './vuetify'

// Types
import type { App } from 'vue'

import {library} from "@fortawesome/fontawesome-svg-core";
import {FontAwesomeIcon} from "@fortawesome/vue-fontawesome";
import {fas} from "@fortawesome/free-solid-svg-icons";
import {far} from "@fortawesome/free-regular-svg-icons";
export function registerPlugins (app: App) {
  app.component('font-awesome-icon',FontAwesomeIcon) //注册一个全局组件,在任何 Vue 组件的模板中使用 <font-awesome-icon icon="图标名"></font-awesome-icon> 显示一个咖啡
  // 将所有实心图标添加到图标库中
  library.add(fas)
  // 将 Font Awesome 图标库中的所有轮廓(Regular)样式的图标集合添加到应用程序的图标库中
  library.add(far)

  app.use(vuetify)
}

src/App.vue

<template>
  <v-icon icon="fas fa-home" />
  <v-icon icon="mdi:mdi-home" />
</template>


<script setup lang="ts">

</script>

创建一个自定义图标集

svg/myicon.vue(封装的svg图标)

<script setup lang="ts">

</script>

<template>
  <svg t="1718001078824" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="9250" width="200" height="200"><path d="M112.138667 317.888a16 16 0 0 1 17.973333-13.749333l80 10.666666a16 16 0 0 1 9.92 5.333334l149.333333 170.666666a16 16 0 0 1-24.074666 21.066667L199.925333 345.728l-74.037333-9.866667a16 16 0 0 1-13.749333-17.973333z" fill="#B05F31" p-id="9251"></path><path d="M219.786667 218.730667a10.666667 10.666667 0 0 1 9.493333 11.722666l-10.666667 101.333334a10.666667 10.666667 0 1 1-21.226666-2.24l10.666666-101.333334a10.666667 10.666667 0 0 1 11.733334-9.493333z" fill="#B05F31" p-id="9252"></path><path d="M780.341333 760.778667c-4.021333 145.034667-125.44 195.232-273.397333 191.136-147.946667-4.106667-266.410667-60.949333-262.4-205.973334 4.021333-145.034667 127.221333-259.285333 275.178667-255.189333 147.946667 4.106667 264.64 125.002667 260.618666 270.026667z" fill="#D0F0F2" p-id="9253"></path><path d="M708.746667 930.474667c-54.336 33.205333-126.421333 44.864-202.389334 42.762666-75.978667-2.112-147.306667-17.738667-199.722666-53.909333-53.738667-37.088-85.610667-94.485333-83.413334-173.984 4.362667-157.216 137.76-280.330667 297.088-275.914667 159.338667 4.416 285.717333 134.730667 281.354667 291.946667-2.197333 79.498667-37.205333 135.04-92.917333 169.098667z m-201.813334 21.44c147.968 4.096 269.386667-46.101333 273.408-191.136 4.021333-145.024-112.661333-265.92-260.618666-270.026667-147.946667-4.096-271.146667 110.144-275.178667 255.178667-4.010667 145.034667 114.442667 201.877333 262.4 205.973333z" fill="#5290BD" p-id="9254"></path><path d="M349.482667 598.730667a21.333333 21.333333 0 0 1-2.218667 30.08c-12.245333 10.581333-23.808 31.477333-29.824 59.36-5.92 27.392-5.888 59.018667 2.432 88.746666a21.333333 21.333333 0 0 1-41.077333 11.498667c-10.346667-36.938667-10.314667-75.637333-3.061334-109.248 7.146667-33.12 21.92-63.893333 43.669334-82.656a21.333333 21.333333 0 0 1 30.08 2.218667z" fill="#DFFDFF" p-id="9255"></path><path d="M479.637333 950.517333c120.458667-9.717333 211.893333-64.213333 215.370667-189.738666 3.701333-133.365333-94.677333-246.325333-225.578667-266.816a274.752 274.752 0 0 1 50.293334-3.2c147.946667 4.096 264.64 124.992 260.618666 270.016-4.021333 145.034667-125.44 195.232-273.397333 191.136a577.450667 577.450667 0 0 1-27.306667-1.386667z" fill="#A6E1E5" p-id="9256"></path><path d="M705.386667 722.848a11.424 11.424 0 1 1-22.858667 0 11.424 11.424 0 0 1 22.848 0zM751.637333 749.696a15.424 15.424 0 1 1-30.837333 0 15.424 15.424 0 0 1 30.837333 0zM743.925333 699.573333a11.562667 11.562667 0 1 1-23.125333 0 11.562667 11.562667 0 0 1 23.125333 0zM753.333333 815.946667a23.989333 23.989333 0 1 1-47.978666 0 23.989333 23.989333 0 0 1 47.978666 0zM705.386667 772.821333a15.424 15.424 0 1 1-30.848 0 15.424 15.424 0 0 1 30.837333 0zM712.661333 865.92a9.354667 9.354667 0 1 1-18.709333 0 9.354667 9.354667 0 0 1 18.709333 0zM680.224 895.338667a15.424 15.424 0 1 1-30.837333 0 15.424 15.424 0 0 1 30.837333 0zM682.528 842.784a15.424 15.424 0 1 1-30.837333 0 15.424 15.424 0 0 1 30.837333 0zM625.984 916.32a11.562667 11.562667 0 1 1-23.125333 0 11.562667 11.562667 0 0 1 23.125333 0z" fill="#81CFD2" p-id="9257"></path><path d="M714.666667 476.672c0 86.186667-76.565333 145.994667-197.333334 145.994667S320 562.858667 320 476.661333C320 390.485333 396.565333 330.666667 517.333333 330.666667S714.666667 390.474667 714.666667 476.672z" fill="#D0F0F2" p-id="9258"></path><path d="M674.101333 599.04C635.221333 628.266667 581.013333 644.010667 517.333333 644.010667c-63.669333 0-117.898667-15.744-156.768-44.96C321.205333 569.482667 298.666667 526.784 298.666667 476.672c0-50.112 22.538667-92.810667 61.898666-122.389333C399.445333 325.088 453.653333 309.333333 517.333333 309.333333c63.669333 0 117.898667 15.744 156.768 44.96C713.461333 383.850667 736 426.56 736 476.661333c0 50.112-22.538667 92.810667-61.898667 122.389334zM517.333333 622.677333c120.768 0 197.333333-59.808 197.333334-146.005333C714.666667 390.485333 638.101333 330.666667 517.333333 330.666667S320 390.474667 320 476.672c0 86.186667 76.565333 145.994667 197.333333 145.994667z" fill="#5290BD" p-id="9259"></path><path d="M435.178667 377.952a21.333333 21.333333 0 0 1-14.4 26.506667c-23.04 6.816-45.226667 41.418667-32.533334 79.466666a21.333333 21.333333 0 1 1-40.48 13.482667c-19.328-57.952 11.829333-119.349333 60.906667-133.866667a21.333333 21.333333 0 0 1 26.506667 14.4z" fill="#DFFDFF" p-id="9260"></path><path d="M474.666667 619.989333C570.517333 607.488 629.333333 552.213333 629.333333 476.661333c0-75.541333-58.816-130.816-154.666666-143.317333a330.026667 330.026667 0 0 1 42.666666-2.677333C638.101333 330.666667 714.666667 390.474667 714.666667 476.672c0 86.186667-76.565333 145.994667-197.333334 145.994667a330.026667 330.026667 0 0 1-42.666666-2.666667z" fill="#A5E1E4" p-id="9261"></path><path d="M654.005333 227.669333c0 84.810667-53.034667 143.658667-136.672 143.658667s-136.672-58.848-136.672-143.658667c0-84.821333 53.034667-143.669333 136.672-143.669333s136.672 58.848 136.672 143.669333z" fill="#D0F0F2" p-id="9262"></path><path d="M632.597333 345.888c-28.170667 30.08-68.202667 46.784-115.264 46.784-47.061333 0-87.093333-16.704-115.264-46.784-28.042667-29.930667-42.741333-71.381333-42.741333-118.218667 0-46.848 14.698667-88.298667 42.741333-118.229333 28.170667-30.08 68.202667-46.773333 115.264-46.773333 47.061333 0 87.093333 16.693333 115.264 46.773333 28.042667 29.930667 42.741333 71.381333 42.741334 118.229333 0 46.837333-14.698667 88.288-42.741334 118.218667zM517.333333 371.338667c83.637333 0 136.672-58.858667 136.672-143.68 0-84.8-53.034667-143.658667-136.672-143.658667s-136.672 58.848-136.672 143.669333c0 84.810667 53.034667 143.658667 136.672 143.658667z" fill="#5290BD" p-id="9263"></path><path d="M474.666667 359.882667c83.637333 0 136.672-58.848 136.672-143.68 0-61.685333-28.064-109.653333-75.562667-131.2 72.917333 8.053333 118.229333 64.266667 118.229333 142.666666 0 84.810667-53.034667 143.658667-136.672 143.658667-22.794667 0-43.317333-4.373333-61.12-12.448 5.973333 0.661333 12.128 1.002667 18.453334 1.002667z" fill="#A5E1E4" p-id="9264"></path><path d="M570.848 183.125333c4.192 16.618667-5.632 33.44-21.973333 37.568-16.32 4.128-32.96-6.005333-37.162667-22.624-4.202667-16.618667 5.632-33.44 21.962667-37.568 16.32-4.128 32.96 6.005333 37.173333 22.613334z" fill="#074894" p-id="9265"></path><path d="M591.530667 177.898667c6.997333 27.690667-9.322667 56.373333-37.418667 63.466666-28.096 7.114667-56.085333-10.368-63.082667-38.069333-6.997333-27.690667 9.322667-56.373333 37.418667-63.477333 28.096-7.104 56.074667 10.378667 63.082667 38.08z m-42.645334 42.794666c16.32-4.128 26.165333-20.949333 21.962667-37.568-4.202667-16.618667-20.853333-26.752-37.173333-22.613333-16.330667 4.117333-26.165333 20.938667-21.973334 37.557333 4.213333 16.618667 20.853333 26.752 37.184 22.613334z" fill="#F7FFFF" p-id="9266"></path><path d="M482.986667 188.416c-2.272 12.544-13.717333 20.96-25.557334 18.805333-11.84-2.144-19.584-14.048-17.301333-26.592 2.272-12.533333 13.717333-20.949333 25.546667-18.805333 11.84 2.154667 19.594667 14.058667 17.312 26.592z" fill="#074894" p-id="9267"></path><path d="M503.978667 192.234667c-4.170667 22.976-25.813333 40.437333-50.357334 35.978666-24.554667-4.458667-38.656-28.416-34.485333-51.392 4.170667-22.976 25.813333-40.448 50.346667-35.989333 24.554667 4.458667 38.666667 28.426667 34.496 51.402667z m-46.549334 14.986666c11.84 2.154667 23.285333-6.261333 25.557334-18.805333 2.282667-12.533333-5.472-24.437333-17.312-26.592-11.84-2.144-23.274667 6.272-25.546667 18.805333-2.282667 12.544 5.472 24.448 17.301333 26.592z" fill="#F7FFFF" p-id="9268"></path><path d="M851.509333 266.954667a21.333333 21.333333 0 0 1 17.536 24.554666l-16 96a21.333333 21.333333 0 0 1-8.554666 13.781334l-192 138.666666a21.333333 21.333333 0 0 1-24.981334-34.581333L812.394667 371.84l14.56-87.349333a21.333333 21.333333 0 0 1 24.554666-17.536z" fill="#8E4323" p-id="9269"></path><path d="M816 394.666667a16 16 0 0 1 16-16h96a16 16 0 0 1 0 32h-96a16 16 0 0 1-16-16z" fill="#8E4323" p-id="9270"></path><path d="M840.885333 297.418667a5.333333 5.333333 0 0 1 4.277334 6.208l-13.994667 76a5.333333 5.333333 0 0 1-2.069333 3.328l-105.333334 77.994666a5.333333 5.333333 0 0 1-6.357333-8.565333l103.648-76.757333 13.621333-73.92a5.333333 5.333333 0 0 1 6.208-4.288z" fill="#C15B30" p-id="9271"></path><path d="M458.133333 456.266667c-5.194667 17.28-21.706667 27.573333-36.864 23.008-15.157333-4.554667-23.232-22.261333-18.026666-39.541334 5.194667-17.28 21.706667-27.573333 36.864-23.008 15.157333 4.554667 23.232 22.261333 18.026666 39.541334z" fill="#08DDAA" p-id="9272"></path><path d="M478.570667 462.410667c-7.818667 25.973333-34.581333 45.984-63.445334 37.301333-28.874667-8.693333-40.128-40.149333-32.32-66.133333 7.818667-25.962667 34.581333-45.973333 63.445334-37.28 28.874667 8.682667 40.138667 40.149333 32.32 66.112z m-57.301334 16.874666c15.168 4.554667 31.669333-5.749333 36.864-23.018666 5.205333-17.28-2.869333-34.986667-18.026666-39.541334-15.157333-4.565333-31.669333 5.738667-36.864 23.008-5.205333 17.28 2.869333 34.986667 18.026666 39.552z" fill="#EEFEFF" p-id="9273"></path><path d="M408.853333 689.6c-1.013333 18.026667-14.645333 31.904-30.453333 31.018667-15.808-0.885333-27.808-16.202667-26.805333-34.208 1.013333-18.016 14.645333-31.893333 30.453333-31.018667 15.808 0.885333 27.797333 16.202667 26.794667 34.208z" fill="#08DDAA" p-id="9274"></path><path d="M430.144 690.794667c-1.514667 27.072-22.826667 52.8-52.928 51.125333-30.101333-1.674667-48.426667-29.621333-46.912-56.704 1.504-27.072 22.826667-52.8 52.928-51.125333 30.101333 1.674667 48.426667 29.621333 46.912 56.704z m-51.733333 29.824c15.797333 0.885333 29.429333-13.002667 30.432-31.018667 1.002667-18.005333-10.986667-33.322667-26.794667-34.208-15.808-0.885333-29.44 13.002667-30.453333 31.018667-1.002667 18.016 10.997333 33.322667 26.805333 34.208z" fill="#EEFEFF" p-id="9275"></path><path d="M520.832 235.306667c-12.8-21.866667-34.837333-16.288-44.64-10.730667-40.32 26.058667-95.466667 72.661333-106.048 80.853333-14.976 11.626667-4.725333 22.933333 6.112 20.8 10.325333-2.026667 92.373333-22.229333 142.826667-50.346666 9.152-5.109333 13.6-20.309333 1.749333-40.565334z" fill="#E58B04" p-id="9276"></path><path d="M470.666667 215.445333l0.266666-0.149333c6.208-3.52 16.277333-7.125333 27.274667-6.272 11.68 0.896 23.594667 6.826667 31.829333 20.906667 13.162667 22.485333 11.146667 45.834667-5.76 55.264-26.197333 14.602667-60.16 26.933333-88.458666 35.818666-28.362667 8.896-51.84 14.570667-57.493334 15.68-9.077333 1.792-19.658667-1.738667-24.309333-10.858666-5.386667-10.56 0.117333-21.482667 9.6-28.832 1.888-1.461333 5.482667-4.394667 10.346667-8.362667 20.501333-16.704 63.466667-51.712 96.448-73.024l0.256-0.16z m5.525333 9.130667c9.802667-5.546667 31.84-11.146667 44.64 10.741333 11.850667 20.256 7.402667 35.456-1.76 40.565334-50.432 28.117333-132.490667 48.32-142.816 50.346666-10.837333 2.133333-21.088-9.173333-6.112-20.8 2.090667-1.610667 5.930667-4.746667 11.061333-8.917333 20.768-16.928 62.645333-51.04 94.986667-71.936z" fill="#B36013" p-id="9277"></path><path d="M468.053333 230.986667c1.962667-2.336 5.578667-3.136 8.064-1.792 10.016 5.397333 30.282667 22.346667 33.514667 48.405333 0.32 2.613333-1.973333 5.258667-5.130667 5.92-3.157333 0.661333-5.984-0.917333-6.304-3.530667-2.826667-22.762667-20.821333-37.824-29.194666-42.336-2.496-1.344-2.922667-4.330667-0.96-6.666666zM434.88 257.653333c2.005333-2.304 5.632-3.061333 8.085333-1.674666 4.341333 2.442667 10.528 7.146667 15.616 13.546666s9.333333 14.837333 9.098667 24.725334c-0.053333 2.677333-2.677333 5.12-5.856 5.461333-3.168 0.341333-5.696-1.557333-5.632-4.234667 0.170667-7.466667-3.050667-14.208-7.434667-19.733333a48.106667 48.106667 0 0 0-13.056-11.392c-2.464-1.386667-2.826667-4.373333-0.821333-6.698667zM400.234667 281.962667c2.026667-2.304 5.653333-3.04 8.096-1.632 3.253333 1.856 7.786667 5.376 11.488 10.197333 3.701333 4.821333 6.794667 11.221333 6.506666 18.805333-0.096 2.677333-2.752 5.098667-5.92 5.408-3.178667 0.309333-5.664-1.621333-5.568-4.298666 0.192-5.184-1.92-9.898667-4.917333-13.792a32.469333 32.469333 0 0 0-8.917333-7.978667c-2.453333-1.397333-2.794667-4.394667-0.768-6.709333z" fill="#E16002" p-id="9278"></path><path d="M477.450667 230.218667a5.333333 5.333333 0 0 1-1.056 7.466666l-95.018667 71.509334a5.333333 5.333333 0 0 1-6.410667-8.533334l95.018667-71.498666a5.333333 5.333333 0 0 1 7.466667 1.056z" fill="#FFB444" p-id="9279"></path></svg>
</template>

<style scoped>

</style>

src/iconsets/custom.ts(配置图标)

import { h } from 'vue'
import type { IconSet, IconAliases, IconProps } from 'vuetify'
import myicon from "../../svg/myicon.vue";
// 引入图标组件

// 把图标组件封装到对象 ,这样可以存储多个图标
const customIcons =  {myicon}


const custom: IconSet = {
  // 接受属性
  component: (props: IconProps) =>{
    console.log(props.tag) // i 标签
    console.log(props.icon) // 图标名 通过不同的名字拿到不同的图标
    return h(props.tag, [h(customIcons[props.icon as string], { class: 'v-icon__svg' })]) // class: 'v-icon__svg' 生成的类名
  }
}

export { custom }

src/plugins/vuetify.ts(设置自己的图标为默认)

import {createVuetify} from 'vuetify'
import {aliases, fa} from 'vuetify/iconsets/fa-svg'
import {mdi} from "vuetify/iconsets/mdi";
import '@mdi/font/css/materialdesignicons.css'
import {custom} from '../iconsets/custom'

export default createVuetify({
  icons: {
    defaultSet: 'custom',
    aliases,
    sets: {
      fa,
      mdi,
      custom
    },
  },
})

src/App.vue(使用自定义的图标)

<template>
   <v-icon icon="myicon"></v-icon>


</template>


<script setup lang="ts">




import Myicon from "../svg/myicon.vue";
</script>

运行效果:
在这里插入图片描述
增加可用的图标别名
如果你正在开发自定义的 Vuetify 组件,你可以扩展别名对象以利用内部 Vuetify 组件所使用的相同功能。格式 图标别名:别名的名称。

src/plugins/vuetify.ts(我们为 myicon 配置一个别名mic)

import {createVuetify} from 'vuetify'
import {aliases, fa} from 'vuetify/iconsets/fa-svg'
import {mdi} from "vuetify/iconsets/mdi";
import '@mdi/font/css/materialdesignicons.css'
import {custom} from '../iconsets/custom'

export default createVuetify({
  icons: {
    defaultSet: 'custom',
    aliases:{
      ...aliases,
      mic:'myicon'
    },
    sets: {
      fa,
      mdi,
      custom
    },
  },
})

src/App.vue(使用别名加上$)

<template>
  <v-icon icon="$mic"></v-icon>
  <v-icon icon="myicon"></v-icon>

</template>


<script lang="ts" setup>



</script>

运行效果:
在这里插入图片描述

九、国际化 (i18n)

Vuetify 支持其组件的语言国际化(i18n)。

引导应用程序时,可以使用 defaultLocale 选项指定可用的区域设置和默认区域设置。区域设置服务还支持轻松集成VUE-i18N.使用具有 RTL(从右到左)语言的区域设置也会影响 Vuetify 组件的方向性。

RTL(从右到左):所有内容的显示方向会自动从左到右切换为从右到左。这对于支持多语言、特别是 RTL 语言的网站和应用程序非常重要。比如说有些国家是从右到左阅读字。

快速入门

要设置可用的语言环境消息或默认语言环境,请在安装 Vuetify 时提供语言环境选项。

src/plugins/vuetify.ts

// Translations provided by Vuetify
import {pl, sv, zhHans} from 'vuetify/locale'

// Your own translation file

import {createVuetify} from "vuetify";



 const vuetify = createVuetify({
  locale: {
    locale: 'zhHans', // 默认使用中文
    fallback: 'sv', // 找不到中文 使用 sv
    // 提供的翻译信息
    messages: { zhHans, pl, sv },
  },
})
export default vuetify

src/App.vue

<template>
  <v-app>

    <p>{{ t('$vuetify.close') }}</p>
    <p>{{ t('$vuetify.open') }}</p>



    <button @click="changeLocale('zhHans')"> 切换汉语</button>
    <button @click="changeLocale('pl')"> 切换波兰</button>
    <button @click="changeLocale('sv')"> 切换瑞典</button>


  </v-app>

</template>

<script setup>
import {useLocale} from 'vuetify'

// t("$键名")获取对应的消息
const {current, t} = useLocale();

// 切换语言
const changeLocale = (lang) => {

  current.value = lang;

};
</script>

运行效果:

在这里插入图片描述

这个目录下可以看到vuetify默认提供的汉字翻译消息有哪些
node_modules/.pnpm/vuetify@3.6.7_typescript@5.4.5_vite-plugin-vuetify@2.0.3_vue-i18n@9.13.1_vue@3.4.27_typescrip_3qzgojnpglhqdtsa7nei5gdb2a/node_modules/vuetify/lib/locale/index.d.mts
在这里插入图片描述
应用程序接口

api描述
useLocale使用区域设置可组合项
v-locale-provider本地化供应者组件用于将应用的一部分设置为另一种语言

为一定范围设置语言
使用v-locale-provider该组件,可以将应用程序的一部分范围限定为与默认区域设置不同的区域设置。

src/App.vue

<template>
  <v-app>
    <v-select></v-select> <!-- 将会使用默认语言 -->

    <v-locale-provider locale="sv">
      <v-select></v-select> <!-- 将会使用 sv(瑞典)语言 -->
    </v-locale-provider>
  </v-app>
</template>

RTL的
RTL(从右到左)支持内置于 Vuetify 附带的所有本地化版本。如果支持的语言标记为 RTL,则所有内容方向都会自动切换。

<template>
  <v-app>
    <v-card>
      <p>{{ t('$vuetify.close') }}</p>
    </v-card>
    <v-locale-provider rtl>
    <v-card>
      <v-navigation-drawer></v-navigation-drawer>
    </v-card>
    </v-locale-provider>


  </v-app>

</template>

<script setup>
import {useLocale} from 'vuetify'

// t($"键名")获取对应的消息
const { t} = useLocale();


</script>

创建自定义本地化语言

若要创建自己的区域设置消息,请将内容复制并粘贴到新文件中,然后更改本地化的字符串。还可以使用区域设置选项的属性来指定是否应显示 RTL。

src/locales/customLocale.js

export default {
  badge: '...',
  close: '...',
  ...
}

src/main.js

import { createVuetify } from 'vuetify'
import customLocale from './locales/customLocale'

const vuetify = createVuetify({
  locale: {
    locale: 'customLocale',
    messages: { customLocale },
    rtl: {
    // 如果在customLocale语言环境 默认组件开启rtl
      customLocale: true,
    },
  },
})

自定义 Vuetify 组件

<template>
  <div class="my-component">
    {{ text }}
  </div>
</template>

<script setup>
  import { useLocale } from 'vuetify'

  const { t } = useLocale()
  const text = t('$vuetify.my-component.text')
</script>

提示:Vuetify 语言环境服务只提供基本的翻译功能,实际上应该只用于内部或自定义 Vuetify 组件。建议您使用适当的 i18n 库,例如VUE-i18N在您自己的应用程序中。Vuetify 确实提供了与其他库集成的支持。

VUE-i18N

如果您使用的是vue-i18n库,您可以很容易地将其与Vuetify集成。这使您可以将所有翻译保存在一个位置。只需在您的消息中为$vuetify创建一个条目,并添加相应的语言更改。然后使用提供的适配器函数将vue-i18n连接到Vuetify(如下例所示)。

src/plugins/index.ts

// Plugins
import {vuetify,i18n} from './vuetify'
import {App} from "vue";


export function registerPlugins (app: App) {
  app.use(i18n)
  app.use(vuetify)

}

src/plugins/vuetify.ts

import {createVuetify} from "vuetify";

import {createVueI18nAdapter} from "vuetify/locale/adapters/vue-i18n";
import {createI18n, useI18n} from "vue-i18n";
import {sv, en} from "vuetify/locale";

const messages = {
  en: {
    $vuetify: {// 引入Vuetify默认英语翻译
      ...en,
      dataIterator: {     //翻译文本以用于特定组件的显示内容
        //翻译文本以用于特定组件的显示内容
        rowsPerPageText: 'Items per page:',
        pageText: '{0}-{1} of {2}',
      },
    },
  },
  sv: {// 引入Vuetify默认瑞典语翻译
    $vuetify: {
      ...sv,
      dataIterator: { //翻译文本以用于特定组件的显示内容
        //定义分页控件中,每页显示多少项的文本描述。
        rowsPerPageText: 'Element per sida:',
        pageText: '{0}-{1} av {2}',
      },
    },
  },
}
//当语言环境为英文时,如果表格显示的是第 1 项到第 10 项,总共有 100 项,文本会显示为 1-10 of 100。在瑞典语环境下则会显示 1-10 av 100。
const i18n = createI18n({
  legacy: false, // 禁用遗留模式,启用组合式API模式
  locale: 'sv', // 设置默认语言为瑞典语
  fallbackLocale: 'en', // 如果瑞典语翻译缺失,使用英语作为后备语言
  messages, // 提供本地化翻译字符串
})

const vuetify = createVuetify({
  locale: {
    adapter: createVueI18nAdapter({i18n, useI18n}),
  },
})
export {vuetify,i18n}

已支持语言

目前,Vuetify 提供以下语言的翻译:

  • af - Afrikaans (Afrikaans)
  • zhHans - 简体中文
  • zhHant - 繁体中文 (正體中文)
  • ar - 阿拉伯语 (العربية)
  • az - 阿塞拜疆语 (Azərbaycan)
  • bg - 保加利亚语 (български)
  • ca - 加泰罗尼亚语 (català)
  • ckb - 中库尔德语 (کوردی)
  • cs - 捷克语 (čeština)
  • da - 丹麦语 (Dansk)
  • de - 德语 (Deutsch)
  • el - 希腊语 (Ελληνικά)
  • en - 英语 (English)
  • es - 西班牙语 (Español)
  • et - 爱沙尼亚语 (eesti)
  • fa - 波斯语 (فارسی)
  • fi - 芬兰语 (suomi)
  • fr - 法语 (Français)
  • he - 希伯来语 (עברית)
  • hr - 克罗地亚语 (hrvatski jezik)
  • hu - 匈牙利语 (magyar)
  • id - 印度尼西亚语 (Indonesian)
  • it - 意大利语 (Italiano)
  • ja - 日语 (日本語)
  • km - Khmer (ខ្មែរ)
  • ko - 韩语 (한국어)
  • lt - 立陶宛语 (lietuvių kalba)
  • lv - 拉脱维亚语 (latviešu valoda)
  • nl - 荷兰语 (Nederlands)
  • no - 挪威语 (Norsk)
  • pl - 波兰语 (język polski)
  • pt - 葡萄牙语 (Português)
  • ro - 罗马尼亚语 (Română)
  • ru - 俄语 (Русский)
  • sk - 斯洛伐克语 (slovenčina)
  • sl - 斯洛文尼亚语 (slovenski jezik)
  • srCyrl - 塞尔维亚语 (српски језик)
  • srLatn - 塞尔维亚语 (srpski jezik)
  • sv - 瑞典语 (svenska)
  • th - 泰国语 (ไทย)
  • tr - 土耳其语 (Türkçe)
  • uk - 乌克兰语 (Українська)
  • vi - 越南语 (Tiếng Việt)

十、程序滚动

使用 goTo 函数在你的应用中滚动。

使用
goTo 方法采用两个参数、目标和选项。目标可以是与页面顶部的像素偏移量、有效的 CSS 选择器或元素引用。options 是一个包含持续时间、缓动、容器和偏移量的对象。

src/App.vue

<template>
  <v-container>
    <v-btn @click="scrollToElement">Scroll to Element</v-btn>
    <div class="scrollContainer" style="max-height: 500px; overflow-y: auto;">
      <div style="height: 1000px;">
        <div class="targetElement" style="margin-top: 800px;">目标</div>
      </div>
    </div>
  </v-container>
</template>
<script setup>
import {useGoTo} from "vuetify";
import {ref} from "vue";
let goTo = useGoTo();
let scrollContainer = ref()
function scrollToElement() {

  // 要移动的目标可以是数字 或者是css选择器
    goTo(".targetElement",{
      //控制移动持续时间
      duration: 10000,
      // 控制移动速度
      easing:"easeInOutCubic",//二次方缓动函数,开始和结束时较慢,中间较快。
      //指定滚动操作的容器。默认情况下,goTo 滚动的是 window 对象(即整个页面)。
      container: ".scrollContainer",

    })
}
</script>

十一、SASS 变量

Vuetify 使用 SASS/SCSS 来设计框架所有方面的样式和外观。

提示:推荐在熟悉了摇树(Treeshaking)过程之后再继续阅读本章节。

安装
Vuetify 开箱即用,无需安装任何额外的编译器,但确实支持高级用例,例如修改框架的底层变量。Vite 为 sass、less 和 stylus 文件提供了内置支持,而无需为它们安装特定于 Vite 的插件;只需安装对应的预处理器本身。

要开始修改 Vuetify 的内部变量,安装 sass 预处理器:

安装
Vuetify 开箱即用,无需安装任何额外的编译器,但确实支持高级用例,例如修改框架的底层变量。Vite 为 sass、less 和 stylus 文件提供了内置支持,而无需为它们安装特定于 Vite 的插件;只是相应的预处理器本身。

  pnpm install -D sass-loader sass

有关 css-pre-processors 的更多详细信息,请参阅官方 vite 页面:
https://vitejs.dev/guide/features.html#css-pre-processors
或官方 vue-cli-page 在:
https://cli.vuejs.org/guide/css.html#pre-processors

基本用法
在 src/styles 目录中创建一个 settings.scss 文件,并更新settings 文件中的样式导入:

自定义组件中使用的变量有点复杂,需要使用特殊的构建插件。
按照插件设置指南进行操作摇树然后添加到插件选项中:

vuetify({
  styles: {
    configFile: 'src/styles/settings.scss',
  },
})

src/styles/settings.scss

@use 'vuetify/settings' with (
  $button-height: 300px,
);

在您的样式文件中,导入 Vuetify 样式并指定要覆盖的变量,仅此而已。

运行效果:

在这里插入图片描述
变量 API
有许多 SASS/SCSS 变量可以在整个 Vuetify 框架中自定义。您可以使用工具浏览所有变量:
在这里插入图片描述
模板中的用法
您只需导入设置文件,就可以访问Vue模板中的全局变量和每个组件的变量:

Comp1.vue

<style lang="scss">
  @use './settings';

  .my-button {
    height: settings.$button-height;
  }
</style>

请记住,要从Vuetify获取设置,必须从本地样式表中转发其变量。在以下示例中,我们修改为转发而不是使用:

src/styles/settings.scss

- @use 'vuetify/settings' with (
+ @forward 'vuetify/settings' with (

禁用实用程序类

实用程序类是Vuetify的一个强大功能,但对于某些项目来说,它们也可能是不必要的。每个实用程序类都使用一组定义的选项生成,禁用实用程序类是通过配置来控制哪些CSS帮助类会被生成和包括在最终的CSS文件中。禁用某些类后,这些类在项目中将不可用,因为它们不再存在于生成的CSS文件中。这是一个优化项目的重要手段,特别是在你知道一些特定的实用程序类在项目中不会被用到的情况下。
在这里。通过将相应的变量设置为:false来禁用各个类

src/styles/settings.scss

 @forward 'vuetify/settings' with (
  $utilities: (
    "align-content": false,
    "align-items": false,
    "align-self": false,
    "border-bottom": false,
    "border-end": false,
    "border-opacity": false,
    "border-start": false,
    "border-style": false,
    "border-top": false,
    "border": false,
    "display": false,
    "flex-direction": false,
    "flex-grow": false,
    "flex-shrink": false,
    "flex-wrap": false,
    "flex": false,
    "float-ltr": false,
    "float-rtl": false,
    "float": false,
    "font-italic": false,
    "font-weight": false,
    "justify-content": false,
    "margin-bottom": false,
    "margin-end": false,
    "margin-left": false,
    "margin-right": false,
    "margin-start": false,
    "margin-top": false,
    "margin-x": false,
    "margin-y": false,
    "margin": false,
    "negative-margin-bottom": false,
    "negative-margin-end": false,
    "negative-margin-left": false,
    "negative-margin-right": false,
    "negative-margin-start": false,
    "negative-margin-top": false,
    "negative-margin-x": false,
    "negative-margin-y": false,
    "negative-margin": false,
    "order": false,
    "overflow-wrap": false,
    "overflow-x": false,
    "overflow-y": false,
    "overflow": false,
    "padding-bottom": false,
    "padding-end": false,
    "padding-left": false,
    "padding-right": false,
    "padding-start": false,
    "padding-top": false,
    "padding-x": false,
    "padding-y": false,
    "padding": false,
    "rounded-bottom-end": false,
    "rounded-bottom-start": false,
    "rounded-bottom": false,
    "rounded-end": false,
    "rounded-start": false,
    "rounded-top-end": false,
    "rounded-top-start": false,
    "rounded-top": false,
    "rounded": false,
    "text-align": false,
    "text-decoration": false,
    "text-mono": false,
    "text-opacity": false,
    "text-overflow": false,
    "text-transform": false,
    "typography": false,
    "white-space": false,
  ),
);

要禁用所有实用程序类,请将整个变量设置为:$utilities false
src/styles/settings.scss

@forward 'vuetify/settings' with (
  $utilities: false,
);

禁用颜色包

颜色包可以方便地将颜色快速应用于组件,但在生产中大多未使用。要禁用它们,请将变量设置为:$color-pack false

src/styles/settings.scss

@forward 'vuetify/settings' with (
  $color-pack: false,
);

启用CSS级联层

@layer 是一种现代 CSS 功能,使得在编写自定义样式时更容易处理特异性问题。这将被默认包含在 Vuetify 4 中,但现在也可以选择使用。使用 @layer 可以有效地管理样式层级关系。在 Vuetify 中,通过一些设置和加载顺序的调整,你可以控制自定义样式与框架样式之间的优先级关系。
启用图层后,样式表的导入顺序变得更加重要,必须在任何组件之前加载包含的文件,否则 CSS 重置将优先于组件样式并破坏所有内容。
src/styles/settings.scss

@forward 'vuetify/settings' with (
  $layers: true,
);

如果您不使用自己的样式,您自己的样式将始终覆盖 vuetify,或者您可以在 vuetify 之前加载的样式表中指定自定义图层的顺序。

src/styles/layers.css

@layer base, vuetify, overrides;

注意事项
在使用 Sass 变量时,有一些注意事项需要了解。

重复的 CSS
将实际样式或引入普通样式表置于设置文件中会导致它们在每次文件被引入时重复。设置文件中只能放置变量、混合宏以及函数,实际样式应放置在主样式表中或通过其他方式加载。

构建性能
Vuetify 默认加载预编译的 CSS,启用变量自定义将切换到基础的 SASS 文件,这些文件必须与项目一起重新编译。如果你使用了多于几个 Vuetify 组件,这可能会影响性能,并且还强制你使用与 Vuetify 相同版本的 SASS 编译器。

符号链接
PNPM 和 Yarn 2+ 会对库文件创建符号链接,而不是将它们复制到 node_modules 目录中。Sass 似乎对这种方式有时不太适配,并可能不能正确应用配置。

使用 api: ‘modern’ 的 sass-loader
你可能需要编写一个自定义导入插件来加载设置文件。

十二、主题配置

自定义应用程序的默认文本颜色、表面等。以编程方式实时轻松修改您的主题。Vuetify 标准支持浅色和深色变体。

API

产品特点描述
useTheme主题组合允许您获取有关当前主题的信息并修改当前主题
v-theme-provider主题提供器组件可以修改子组件的主题

起步
Vuetify 预装了两个主题 light dark。

src/plugins/vuetify.js

import { createApp } from 'vue'
import { createVuetify } from 'vuetify'

export default createVuetify({
  theme: {
    defaultTheme: 'dark'
  }
})

自定义主题

src/plugins/vuetify.js

import {createVuetify} from "vuetify";

const myCustomLightTheme = {
  dark: false,
  colors: {
    background: '#FFFFFF',
    surface: '#FFFFFF',
    'surface-bright': '#FFFFFF',
    'surface-light': '#EEEEEE',
    'surface-variant': '#424242',
    'on-surface-variant': '#EEEEEE',
    primary: '#1867C0',
    'primary-darken-1': '#1F5592',
    secondary: '#48A9A6',
    'secondary-darken-1': '#018786',
    error: '#B00020',
    info: '#2196F3',
    success: '#4CAF50',
    warning: '#FB8C00',
  },
  variables: {
    'border-color': '#000000',
    'border-opacity': 0.12,
    'high-emphasis-opacity': 0.87,
    'medium-emphasis-opacity': 0.60,
    'disabled-opacity': 0.38,
    'idle-opacity': 0.04,
    'hover-opacity': 0.04,
    'focus-opacity': 0.12,
    'selected-opacity': 0.08,
    'activated-opacity': 0.12,
    'pressed-opacity': 0.12,
    'dragged-opacity': 0.08,
    'theme-kbd': '#212529',
    'theme-on-kbd': '#FFFFFF',
    'theme-code': '#F5F5F5',
    'theme-on-code': '#000000',
  }
}

/*
主要颜色属性
dark: 指定主题是亮色主题还是暗色主题。false 表示这是一个亮色主题。
colors: 定义了一系列颜色,这些颜色用于应用程序的不同部分。
background: 用于整个应用程序的背景色。
surface: 用于卡片、表单等表面组件的背景色。
surface-bright: 用于更明亮的表面颜色。
surface-light: 用于比 surface 更浅的表面颜色。
surface-variant: 用于表面组件的变体颜色。
on-surface-variant: 用于表面变体上文本或图标的颜色。
primary: 用于主要操作和元素的颜色(如按钮、链接等)。
primary-darken-1: 用于主要颜色的暗调变体。
secondary: 用于次要操作和元素的颜色。
secondary-darken-1: 用于次要颜色的暗调变体。
error: 用于错误状态和消息的颜色。
info: 用于信息提示和消息的颜色。
success: 用于成功状态和消息的颜色。
warning: 用于警告状态和消息的颜色。
/*
变量属性
variables: 定义了一些特定的样式变量,这些变量影响应用程序的视觉效果和交互行为。
border-color: 用于边框颜色。
border-opacity: 用于边框透明度。
high-emphasis-opacity: 高强调元素的透明度。
medium-emphasis-opacity: 中等强调元素的透明度。
disabled-opacity: 禁用状态元素的透明度。
idle-opacity: 空闲状态元素的透明度。
hover-opacity: 悬停状态元素的透明度。
focus-opacity: 聚焦状态元素的透明度。
selected-opacity: 选中状态元素的透明度。
activated-opacity: 激活状态元素的透明度。
pressed-opacity: 按下状态元素的透明度。
dragged-opacity: 拖动状态元素的透明度。
theme-kbd: kbd 元素的背景颜色,用于显示键盘输入。
theme-on-kbd: kbd 元素的文本颜色。
theme-code: code 元素的背景颜色,用于显示代码块。
theme-on-code: code 元素的文本颜色。*/
const vuetify = createVuetify({
 
  theme: {
    defaultTheme: 'myCustomLightTheme',
    themes: {myCustomLightTheme}
  }
})
export {vuetify}

使用 Typescript 时,您可以使用 type 来获取主题对象结构的ThemeDefinition类型提示。

src/plugins/vuetify.js

import { createApp } from 'vue'
import { createVuetify, type ThemeDefinition } from 'vuetify'

const myCustomLightTheme: ThemeDefinition = {
  dark: false,
  colors: {
    background: '#FFFFFF',
    surface: '#FFFFFF',
    primary: '#6200EE',
    'primary-darken-1': '#3700B3',
    secondary: '#03DAC6',
    'secondary-darken-1': '#018786',
    error: '#B00020',
    info: '#2196F3',
    success: '#4CAF50',
    warning: '#FB8C00',
  },
}

export default createVuetify({
  theme: {
    defaultTheme: 'myCustomLightTheme',
    themes: {
      myCustomLightTheme,
    },
  },
})

在运行时更改主题

src/App.vue

<template>
  <v-app>
    <v-btn @click="toggleTheme">toggle theme</v-btn>
    ...
  </v-app>
</template>

<script setup>
import { useTheme } from 'vuetify'

const theme = useTheme()

function toggleTheme () {
  console.log(theme.global.current.value.dark) // 判断 当前主题是否暗色模式
 
  theme.global.name.value = theme.global.current.value.dark ? 'light' : 'dark'
  // 不是暗色变为暗色 是暗色变为亮色
}
</script>

请注意,大多数 Vuetify 组件都支持 theme 属性。当使用该属性时,为特定组件及其所有子组件创建一个新的上下文。在下面的示例中,v-btn 使用了暗色主题,因为该主题应用在其父级 v-card 上。

<template>
  <v-app>
    <v-card theme="dark">
      <!-- button uses dark theme -->
      <v-btn>foo</v-btn>
    </v-card>
  </v-app>
</template>

您可以使用组件来动态地为应用程序的较大部分应用不同的主题,而无需在每个单独的组件上设置主题属性。

<template>
  <v-app>
    <!--  使用默认主题  -->
    <v-card>...</v-card>

    <v-theme-provider theme="high-contrast">

    <!--  使用高对比度主题  -->
      <v-card>...</v-card>
      <v-btn>...</v-btn>
    </v-theme-provider>
  </v-app>
</template>

Vuetify 主题系统支持添加自定义颜色。在配置 Vuetify 主题设置时,将您的自定义颜色添加到 colors 对象中,Vuetify 将为您生成多个 CSS 类和变量,以便您在应用程序中使用。

src/plugins/vuetify.js

import { createApp } from 'vue'
import { createVuetify } from 'vuetify'

export default createVuetify({
  theme: {
    defaultTheme: 'myCustomTheme',
    themes: {
      myCustomTheme: {
        dark: false,
        colors: {
        //我们在这里省略了标准颜色属性,以强调我们添加的自定义颜色属性
          something: '#00ff00',
        },
      },
    },
  },
})

src/App.vue

<template>
  <v-app>
<!--      使用自定义颜色-->
      <v-btn color="something">...</v-btn>

  </v-app>
</template>

颜色的自定义属性是一个列表,因此需要使用逗号或者函数: 红色, 绿色, 蓝色(rgb)或 rgba。

<template>
  <div class="bg-something on-something">background color with appropriate text color contrast</div>

  <div class="text-something">text color</div>

  <div class="border-something">border color</div>
</template>

<style>
  .custom-class {
    background: rgb(var(--v-theme-something))
    color: rgba(var(--v-theme-on-something), 0.9)
  }
</style>

颜色衍生

Vuetify 主题系统可以帮助您为主题中的颜色生成任意数量的变体。以下示例展示了如何为 colors.primary 和 colors.secondary 生成1个明亮版本和2个变暗版本:

src/plugins/vuetify.ts

import {createVuetify} from "vuetify";
const myCustomLightTheme = {
  dark: false,
  colors: {
    background: '#FFFFFF',
    surface: '#FFFFFF',
    'surface-bright': '#FFFFFF',
    'surface-light': '#EEEEEE',
    'surface-variant': '#424242',
    'on-surface-variant': '#EEEEEE',
    primary: '#1867C0',
    'primary-darken-1': '#1F5592',
    secondary: '#48A9A6',
    'secondary-darken-1': '#018786',
    error: '#B00020',
    info: '#2196F3',
    success: '#4CAF50',
    warning: '#FB8C00',
  },
  variables: {
    'border-color': '#000000',
    'border-opacity': 0.12,
    'high-emphasis-opacity': 0.87,
    'medium-emphasis-opacity': 0.60,
    'disabled-opacity': 0.38,
    'idle-opacity': 0.04,
    'hover-opacity': 0.04,
    'focus-opacity': 0.12,
    'selected-opacity': 0.08,
    'activated-opacity': 0.12,
    'pressed-opacity': 0.12,
    'dragged-opacity': 0.08,
    'theme-kbd': '#212529',
    'theme-on-kbd': '#FFFFFF',
    'theme-code': '#F5F5F5',
    'theme-on-code': '#000000',
  }
}


const vuetify = createVuetify({

  theme:{
    defaultTheme:'myCustomLightTheme',
    themes:{myCustomLightTheme},
    variations:{
      colors:['primary','secondary'],  需要生成变体的颜色:primary 和 secondary
      lighten: 1,// // 每个颜色生成1个变亮变体
      darken: 2, // // 每个颜色生成2个变暗变体

    }
  }
})
export {vuetify}

src/App.vue

<template>
  <div class="text-primary-lighten-1">text color</div>

  <div class="text-primary-darken-1">text color</div>

  <div class="text-primary-darken-2">text color</div>
</template>

禁用主题

可以通过将主题配置属性设置为 false来禁用主题功能。这会阻止创建 Vuetify 样式表,并且主题类不会应用于组件。

src/plugins/vuetify.js

import { createApp } from 'vue'
import { createVuetify } from 'vuetify'

export default createVuetify({
  theme: false,
})

主题对象结构

interface ThemeInstance {
/**

*原始主题对象

*可以进行变异以添加新主题或更新现有颜色

*/
  themes: Ref<{ [name: string]: ThemeDefinition }>

/**

*当前主题的名称

*从父组件继承

*/
  readonly name: Ref<string>

/**处理过的主题对象,包括自动生成的颜色*/
  readonly current: Ref<ThemeDefinition>
  readonly computedThemes: Ref<{ [name: string]: ThemeDefinition }>

  readonly global: {
   /**当前全局主题的名称*/
    name: Ref<string>

  /**

*已处理当前全局主题的主题对象

*相当于`theme.comptedThemes.value[theme.global.name.value]`

*/
    readonly current: Ref<ThemeDefinition>
  }
}

CSP Nonce
具有启用了 script-src 或 style-src CSP 规则的页面可能需要为嵌入的 style 标签指定一个 nonce。

<!-- 与脚本src-->一起使用
Content-Security-Policy: script-src 'self' 'nonce-dQw4w9WgXcQ'

<!-- 与脚本style-->一起使用
Content-Security-Policy: style-src 'self' 'nonce-dQw4w9WgXcQ'
// src/plugins/vuetify.js

import {createVuetify} from 'vuetify'

export const vuetify = createVuetify({
  theme: {
    cspNonce: 'dQw4w9WgXcQ',
  },
})

十三、摇树(Treeshaking)
作为一个组件框架,Vuetify 总是水平增长。根据您的项目,要求可能是打包体积尽量小。

自动摇树
摇树(Treeshaking)使你可以通过只包含使用的组件,从而显著地降低打包大小。Vuetify 使用插件来实现
Webpack 或者 vite 的自动摇树算法。

安装
webpack-plugin-vuetify 或者 vite-plugin-vuetify,并在打包配置中启用它。注意 Vuetify 插件需要在 Vue 插件后,否则有可能工作不正常。

vue.config.js

const { VuetifyPlugin } = require('webpack-plugin-vuetify')

module.exports = {
  plugins: [
    new VuetifyPlugin(),
  ],
}

就是这样!无论在哪里使用,Vuetify 组件和指令都会被自动地导入到您的应用中。如果您在之前使用了通配符来导入,现在就可以移除掉它们。

src/main.js

  import 'vuetify/styles'
  import { createVuetify } from 'vuetify'
- import * as components from 'vuetify/components'
- import * as directives from 'vuetify/directives'

手动导入
不使用加载器插件时,可手动导入组件。

src/plugins/vuetify.js

import { createApp } from 'vue'
import { createVuetify } from 'vuetify'
import { VCard } from 'vuetify/components/VCard'
import { VRating } from 'vuetify/components/VRating'
import { VToolbar } from 'vuetify/components/VToolbar'
import { Ripple } from 'vuetify/directives'

const vuetify = createVuetify({
  components: {
    VCard,
    VRating,
    VToolbar,
  },
  directives: {
    Ripple,
  },
})

export default vuetify

您还可以在 .vue 文件中就地导入组件,如下所示。

Component.vue

<template>
  <v-card>
    <v-card-title>...</v-card-title>
    <v-card-text>...</v-card-text>
  </v-card>
</template>

<script setup>
  import { VCard, VCardText, VCardTitle } from 'vuetify/components/VCard'
</script>

局限性

使用加载器插件时,有几种情况需要手动导入组件。

动态组件

使用动态组件时,插件无法解析正在呈现的 Vuetify 组件。这通常发生在使用内置 Vue 的时候。关于动态组件的更多信息可以在官方 Vue 文档中找到。

使用的动态组件可以在本地注册:

Component.vue

<template>
  <component :is="button ? 'v-btn' : 'v-chip'" />
</template>

<script setup>
  import { VBtn } from 'vuetify/components/VBtn'
  import { VChip } from 'vuetify/components/VChip'
  import { shallowRef } from 'vue'

  const btn = shallowRef(false)
</script>

分组件导入

所有组件都可以在 vuetify/components 和 vuetify/components/ 中找到。然而,更推荐使用后者,因为它只加载所需的文件。如果你使用 vuetify/components,树摇优化仍然会在生产构建中起作用,但在开发过程中,它会导致性能下降,因为即使你没有使用的组件,也会加载其样式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值