Vue3 Class 与 Style 绑定

Vue3 Class 与 Style 绑定

  • [1. 绑定 HTML class](#1. 绑定 HTML class)
    • [1.1 绑定对象(3种方式)](#1.1 绑定对象(3种方式))
      • [1.1.1 直接用法(一个class变量或者多个class和html元素自由组合时推荐)](#1.1.1 直接用法(一个class变量或者多个class和html元素自由组合时推荐))
      • [1.1.2 将多个 class 绑定在一个对象变量中(多个class时推荐)](#1.1.2 将多个 class 绑定在一个对象变量中(多个class时推荐))
      • [1.1.3 使用对象的计算属性(多个复杂的class判断时推荐)](#1.1.3 使用对象的计算属性(多个复杂的class判断时推荐))
    • [1.2 绑定数组](#1.2 绑定数组)
      • [1.2.1 直接用法(直接修改类值)](#1.2.1 直接用法(直接修改类值))
      • [1.2.2 结合三目运算符(多个判断时不推荐,过于冗余)](#1.2.2 结合三目运算符(多个判断时不推荐,过于冗余))
      • [1.2.3 数组中嵌套对象(和使用对象没有太大区别)](#1.2.3 数组中嵌套对象(和使用对象没有太大区别))
    • [1.3 组件上使用](#1.3 组件上使用)
      • [1.3.1 单个根元素子组件添加 class 时,会直接合并](#1.3.1 单个根元素子组件添加 class 时,会直接合并)
      • [1.3.2 多个根元素子组件添加 class 时,指定根元素合并](#1.3.2 多个根元素子组件添加 class 时,指定根元素合并)
        • [1.3.2.1 指定单个根元素接收 class(可以)](#1.3.2.1 指定单个根元素接收 class(可以))
        • [1.3.2.1 指定多个根元素接收 class(可以)](#1.3.2.1 指定多个根元素接收 class(可以))
  • [2. 绑定内联样式](#2. 绑定内联样式)
    • [2.1 绑定对象](#2.1 绑定对象)
      • [2.1.1 绑定单个属性值(不推荐变量多时使用,模板代码不够整洁)](#2.1.1 绑定单个属性值(不推荐变量多时使用,模板代码不够整洁))
      • [2.1.2 绑定整个对象(模板更加整洁)](#2.1.2 绑定整个对象(模板更加整洁))
    • [2.2 绑定数组(更好操控每组样式)](#2.2 绑定数组(更好操控每组样式))
  • [3. 最佳实践建议](#3. 最佳实践建议)
    • [3.1 先掌握其中一种,不合适再看其他方式](#3.1 先掌握其中一种,不合适再看其他方式)
    • [3.2 属性名称 推荐驼峰式命名](#3.2 属性名称 推荐驼峰式命名)

1. 绑定 HTML class

1.1 绑定对象(3种方式)

1.1.1 直接用法(一个class变量或者多个class和html元素自由组合时推荐)

我们可以给 :class (v-bind:class 的缩写) 传递一个对象来动态切换 class

javascript 复制代码
<div :class="{ active: isActive }"></div>

active 类是否存在,取决于isActive 的值。

javascript 复制代码
<template>
  <div
    class="demo"
    :class="{
      active: isActive,
      'text-danger': hasError
    }"
  >
    绑定样式类
  </div>
</template>

<script setup>
import { ref } from 'vue'
const isActive = ref(true)
const hasError = ref(false)
setTimeout(() => {
  hasError.value = true
}, 3000)
</script>

<style scoped>
.text-danger {
  color: red;
}
</style>

3s 后

1.1.2 将多个 class 绑定在一个对象变量中(多个class时推荐)

将多个class绑定在一个对象变量中,这样代码相对清爽些,效果相比于1.1.1是相同的。

javascript 复制代码
<template>
  <div class="demo" :class="classObject">
    绑定样式类
  </div>
</template>

<script setup>
import { reactive } from 'vue'
const classObject = reactive({
  active: true,
  'text-danger': false
})
setTimeout(() => {
  classObject['text-danger'] = true
}, 3000)
</script>

<style scoped>
.text-danger {
  color: red;
}
</style>

1.1.3 使用对象的计算属性(多个复杂的class判断时推荐)

如果类的存在,取决于多个值的判断,则可以将对象包装成一个计算属性:

javascript 复制代码
<template>
  <div class="demo" :class="classObject">
    绑定样式类
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'
const isActive = ref(true)
const error = ref(null)

const classObject = computed(() => ({
  active: isActive.value && !error.value,
  'text-danger': error.value && error.value.type === 'fatal'
}))
setTimeout(() => {
  error.value = { type: 'fatal' }
}, 3000)
</script>

<style scoped>
.text-danger {
  color: red;
}
</style>

3s 后

1.2 绑定数组

1.2.1 直接用法(直接修改类值)

直接将多个类名变量放在数组中,可以直接通过修改变量的值,改变类名或者移除:

javascript 复制代码
<template>
  <div class="demo" :class="[isActive, error]">绑定样式类</div>
</template>

<script setup>
import { ref } from 'vue'
const isActive = ref('active')
const error = ref('text-danger')
setTimeout(() => {
  isActive.value = 'normal' // 修改样式类
  error.value = ''  // 移除样式类
}, 3000)
</script>

<style scoped>
.text-danger {
  color: red;
}
</style>

1.2.2 结合三目运算符(多个判断时不推荐,过于冗余)

javascript 复制代码
<template>
  <div :class="[isActive ? activeClass : '', errorClass]">绑定样式类</div>
</template>

<script setup>
import { ref } from 'vue'
const isActive = ref(false)
const activeClass = ref('active')
const errorClass = ref('text-danger')
setTimeout(() => {
  isActive.value = true // 3秒后激活activeClass类
}, 3000)
</script>

<style scoped>
.text-danger {
  color: red;
}
</style>

3s 后

1.2.3 数组中嵌套对象(和使用对象没有太大区别)

数组中使用三目运算符虽然可以达到筛选目的,但是需要判断的类一旦变多,代码就会变得格外臃肿。因此 Vue3 也提供了数组中嵌套对象的方式。

javascript 复制代码
<template>
  <div :class="[{ [activeClass]: isActive }, errorClass]">绑定样式类</div>
</template>

<script setup>
import { ref } from 'vue'
const isActive = ref(false)
const activeClass = ref('active')
const errorClass = ref('text-danger')
</script>

<style scoped>
.text-danger {
  color: red;
}
</style>


加入我们删除中括号[]:

javascript 复制代码
<div :class="[{ activeClass: isActive }, errorClass]">绑定样式类</div>

1.3 组件上使用

1.3.1 单个根元素子组件添加 class 时,会直接合并

子组件:

javascript 复制代码
<template>
  <!-- 子组件模板 -->
  <p class="foo bar">Hi!</p>
</template>

<script setup>

</script>

<style lang="scss" scoped></style>

父组件:

javascript 复制代码
<template>
  <!-- 在使用组件时,添加额外的class -->
  <MyComponent class="baz boo" />
</template>

<script setup>
import MyComponent from '@/components/MyComponent.vue'
</script>

<style scoped>
</style>

1.3.2 多个根元素子组件添加 class 时,指定根元素合并

1.3.2.1 指定单个根元素接收 class(可以)

多个根元素的子组件(指定添加class的根元素):

javascript 复制代码
<template>
  <!-- MyComponent 模板使用 $attrs 时 -->
  <p :class="$attrs.class">Hi!</p>
  <span>This is a child component</span>
</template>

<script setup>

</script>

<style lang="scss" scoped></style>

父组件:

javascript 复制代码
<template>
  <!-- 在使用组件时,添加额外的class -->
  <MyComponent class="baz" />
</template>

<script setup>
import MyComponent from '@/components/MyComponent.vue'
</script>

<style scoped>
</style>


1.3.2.1 指定多个根元素接收 class(可以)

官方给出的例子,只告诉我们 如何让多个根元素组件中的一个根元素接收class。

但是通过观察,不难发现,$attr.class 是指定一个属性class暴露给外部。那么,我们不同根组件指定不同的 attr 名称暴露给外部,不就可以实现多个根元素接收class了吗?让我们尝试一下。

子组件多个根元素 class 暴露给不同attr:

javascript 复制代码
<template>
  <!-- MyComponent 模板使用 $attrs 时 -->
  <p :class="$attrs.pClass">Hi!</p>
  <span :class="$attrs.spanClass">This is a child component</span>
</template>

<script setup>

</script>

<style lang="scss" scoped></style>

父组件给子组件暴露出的多个 attr 分别进行赋值

2. 绑定内联样式

2.1 绑定对象

2.1.1 绑定单个属性值(不推荐变量多时使用,模板代码不够整洁)

javascript 复制代码
<template>
  <div :style="{ color: activeColor, fontSize: fontSize + 'px' }">hello world</div>
</template>

<script setup>
import { ref } from 'vue'
const activeColor = ref('red')
const fontSize = ref(30)
</script>

<style scoped></style>


2.1.2 绑定整个对象(模板更加整洁)

javascript 复制代码
<template>
  <div :style="styleObject">hello world</div>
</template>

<script setup>
import { reactive } from 'vue'
const styleObject = reactive({
  color: 'red',
  fontSize: '30px'
})
</script>

<style scoped></style>


2.2 绑定数组(更好操控每组样式)

javascript 复制代码
<template>
  <div :style="styleArr">使用数组绑定内联样式</div>
</template>

<script setup>
import { ref, reactive } from 'vue'
const styleObj = reactive({
  color: 'red',
  fontSize: '30px'
})
const styleObj2 = reactive({
  textDecoration: 'underline'
})
const styleArr = ref([styleObj, styleObj2])
setTimeout(() => {
  styleArr.value.pop()
}, 3000)
</script>

<style lang="scss" scoped></style>

3s 后

通过这种绑定数组的方式,可以很方便地操作一组样式。

3. 最佳实践建议

3.1 先掌握其中一种,不合适再看其他方式

其实对于初学者而言,不必在多种class绑定方式之中过多纠结。我的建议是,优先熟练使用其中一种,比如 1.1.2 将多个 class 绑定在一个对象变量中:

javascript 复制代码
<template>
  <div class="demo" :class="classObject">
    绑定样式类
  </div>
</template>

<script setup>
import { reactive } from 'vue'
const classObject = reactive({
  active: true,
  'text-danger': false
})
setTimeout(() => {
  classObject['text-danger'] = true
}, 3000)
</script>

<style scoped>
.text-danger {
  color: red;
}
</style>

在绝大多数情况下,这种绑定方式尤为清晰整洁。

当然,不能一概而论,当不同class需要在不同的html元素中自由组合时,则 1.1.1 直接用法 则可能更为合适。

javascript 复制代码
<template>
  <div
    class="demo"
    :class="{
      active: isActive,
      'text-danger': hasError
    }"
  >
    绑定样式类
  </div>
</template>

<script setup>
import { ref } from 'vue'
const isActive = ref(true)
const hasError = ref(false)
setTimeout(() => {
  hasError.value = true
}, 3000)
</script>

<style scoped>
.text-danger {
  color: red;
}
</style>

只要熟练掌握其中一种,在遇到不合适的时候,再回头看看其他绑定方式,更加便捷时即可进行替换。

3.2 属性名称 推荐驼峰式命名

Vue3 官方推荐使用 camelCase (驼峰式命名)来书写 CSS 的属性key,比如:

javascript 复制代码
<div :style="{ fontSize: fontSize + 'px' }"></div>

虽然 Vue3 也支持 kebab-cased 形式的 CSS 属性 key (对应其 CSS 中的实际名称),例如:

html 复制代码
<div :style="{ 'font-size': fontSize + 'px' }"></div>

但很明显 fontSizefont-size 书写更加方便直观。


上一章 《Vue3 计算属性

下一章 《Vue3 条件渲染

相关推荐
夏天想4 小时前
复制了一个vue的项目然后再这个基础上修改。可是通过npm run dev运行之前的老项目,发现运行的竟然是拷贝后的项目。为什么会这样?
前端·vue.js·npm
yiludegeX4 小时前
fluth-vue: 体验流式编程范式之美
vue.js·前端框架·rxjs
没有鸡汤吃不下饭4 小时前
H5移动端页面实现快递单号条形码/二维码扫描,亲测可行!!
前端·javascript·vue.js
Java陈序员5 小时前
宝藏工具站!一个轻量实用的在线工具集合!
vue.js·nuxt.js
喝西瓜汁的兔叽Yan5 小时前
书架效果的实现
javascript·vue.js
GBVFtou5 小时前
vue3 options模式
前端·vue.js
我是日安5 小时前
从零到一打造 Vue3 响应式系统 Day 26 - 数组长度变更处理
前端·javascript·vue.js
jason_yang5 小时前
vue3中使用auto-import与cdn插件冲突问题
vue.js·vite·cdn
丘耳5 小时前
@tiptap/vue-2 知识点笔记-02
前端·javascript·vue.js