Vue3 零基础每日笔记(021):class 与 style 动态绑定——对象、数组、三元表达式写法汇总

一、前言

数据驱动视图的最后一公里是样式:Tab 激活高亮、状态标签红绿、行选中变色------这些都要样式"跟着数据变"。class 和 style 的动态绑定写法多而杂,这篇一次汇总到位,以后写样式直接来查表。

二、:class 对象语法:{ 类名: 布尔值 }

最常用写法------类名做 key,数据表达式做 value,为 true 就挂上该类:

vue 复制代码
<template>
  <button :class="{ active: isActive }">点我切换高亮</button>

  <!-- 混合:静态 class 和动态 :class 共存,Vue 自动合并 -->
  <button class="btn" :class="{ active: isActive, disabled: isDisabled }">
    多条件高亮
  </button>
</template>

<script setup>
import { ref } from 'vue'
const isActive = ref(true)
const isDisabled = ref(false)
</script>

<style scoped>
.btn { padding: 6px 16px; }
.active { background: #42b983; color: #fff; }
.disabled { opacity: 0.5; }
</style>

两个要点:

  1. 静态 class 和动态 :class 可以同时写,结果是合并,不会覆盖
  2. 对象里可以放任意表达式:{ active: count > 5 }

三、:class 数组语法:多类名批量挂

类名组合比较动态时用数组:

vue 复制代码
<template>
  <!-- 数组:每个元素都是一个类名 -->
  <p :class="[baseClass, activeClass]">数组组合样式</p>

  <!-- 数组 + 对象混搭:数组里某一项用对象控制开关 -->
  <p :class="[baseClass, { highlight: isHighlight }]">数组嵌对象</p>

  <!-- 三元表达式:二选一场景 -->
  <p :class="isError ? 'error' : 'success'">{{ isError ? '失败' : '成功' }}</p>
</template>

<script setup>
import { ref } from 'vue'

const baseClass = ref('text')
const activeClass = ref('active')
const isHighlight = ref(true)
const isError = ref(false)
</script>

选择心法:条件开关多 → 对象;类名本身是变量 → 数组;二选一 → 三元。三者可以无限组合。

四、:style 对象语法:CSS 内联的 JS 形态

:style 接一个对象,属性名两种写法二选一

vue 复制代码
<template>
  <!-- camelCase 写法:fontSize(推荐) -->
  <p :style="{ fontSize: size + 'px', color: textColor }">camelCase</p>

  <!-- kebab-case 写法:'font-size',必须加引号 -->
  <p :style="{ 'font-size': size + 'px', 'font-weight': 'bold' }">kebab-case</p>
</template>

<script setup>
import { ref } from 'vue'
const size = ref(20)
const textColor = ref('#42b983')
</script>

细节:fontSize 不用引号(JS 标识符合法);'font-size' 必须引号(有横线)。值需要单位就手动拼字符串。

五、:style 数组与自动前缀

多段样式来源不同时用数组合并:

vue 复制代码
<template>
  <p :style="[baseStyle, overrideStyle]">数组合并样式</p>
</template>

<script setup>
import { ref } from 'vue'

const baseStyle = ref({ fontSize: '18px', color: '#333' })
const overrideStyle = ref({ color: '#e74c3c' })  // 同名属性后者覆盖
</script>

另外,需要浏览器前缀的属性(transform 等)Vue 会自动补全(如 -webkit-transform),不用手写。

六、综合实战:Tab 高亮 + 状态标签

最常见的两个业务样式场景:

vue 复制代码
<template>
  <!-- Tab 高亮:对象语法 + v-for(016 篇知识联动) -->
  <div class="tabs">
    <button
      v-for="tab in tabs"
      :key="tab.id"
      :class="{ active: currentTab === tab.id }"
      @click="currentTab = tab.id"
    >
      {{ tab.name }}
    </button>
  </div>

  <!-- 状态标签:三元表达式配色 -->
  <ul>
    <li v-for="order in orders" :key="order.id">
      {{ order.name }}
      <span :class="['tag', order.status === 'paid' ? 'green' : 'gray']">
        {{ order.status === 'paid' ? '已支付' : '待支付' }}
      </span>
    </li>
  </ul>
</template>

<script setup>
import { ref } from 'vue'

const currentTab = ref(1)
const tabs = [
  { id: 1, name: '商品' },
  { id: 2, name: '评价' },
  { id: 3, name: '详情' }
]

const orders = ref([
  { id: 1, name: '订单A', status: 'paid' },
  { id: 2, name: '订单B', status: 'unpaid' }
])
</script>

<style scoped>
.tabs button { margin-right: 8px; }
.active { background: #42b983; color: #fff; }
.tag { padding: 2px 8px; border-radius: 4px; font-size: 12px; }
.green { background: #e1f3d8; color: #529b2e; }
.gray { background: #f4f4f5; color: #909399; }
</style>

两个模式直接抄进项目:currentTab === tab.id 配对象语法做 Tab 高亮;['tag', 条件 ? 'a' : 'b'] 数组嵌三元做状态标签。

【截图位置:Tab 切换高亮与订单状态标签的运行效果】

七、踩坑记录

  1. 对象语法类名带特殊字符要引号{ 'mt-10': isShow } 这种带横线的类名必须加引号
  2. :style 忘写单位{ fontSize: 20 } 无效(部分属性可以,但 font-size 不行),写 '20px'size + 'px'
  3. kebab-case 属性没加引号{ font-size: '12px' } 直接语法错误,JS 对象里横线属性必须引号
  4. :class 里用了不存在的类:不报错但也不生效,先确认 scoped 样式里真的定义了这个类
  5. 重要样式用内联 :style:内联优先级高但难维护,频繁复用的样式写进 class,:style 只管"高度动态"的那几个值

八、今日小结

  • :class 三板斧:对象管开关、数组管组合、三元管二选一
  • 静态 class 与动态 :class 自动合并共存
  • :style 对象两种键名:fontSize(免引号)与 'font-size'(必须引号);数组合并时后者覆盖前者
  • 经典模式:Tab 高亮、状态标签配色,直接复用

下篇预告

指令篇最后一课:把前面全部知识(v-model 修饰符、computed 校验、:class 配色、v-if 提示)合体,从零写一个注册页联动校验------纯 Vue3 不用 UI 库,做完这篇你就能独立写表单了。

相关推荐
杨利杰YJlio1 小时前
ITSK PE 26U5 测试版解读:组件完善、VMD 修复与服务器支持边界
前端·javascript·后端
夏幻灵1 小时前
Vue / React 列表渲染中的 key:为什么没有 key,Checkbox 可能“对号跑错”?
前端·javascript·vue.js
YWL1 小时前
vue-time-axis-plus进阶:双进度条+跨空白续播+播放指针,打造专业级监控回放体验
前端·javascript·vue·时间轴
mmsx1 小时前
MapLibre 实战 09|Bug 单写着"地图被风刮走了":一个瓦片源工厂,是三个线上事故换来的
android·前端·开源
不羁的木木1 小时前
给鸿蒙 App 增加打开外部网页能力 —— flutter_web_browser 的鸿蒙使用指南
前端·flutter·harmonyos
广州山泉婚姻1 小时前
微服务时代,前后端分离架构该怎样高效协同?
前端·后端
EatFan1 小时前
多租户系统到底怎么设计?从 tenant_id 到 JWT 租户隔离的真实实践
前端·后端·全栈·多租户
Bs_MoneyMagnet1 小时前
基于springboot+vue的旅游行程分享与推荐小程序的设计与实现 源码+文档
java·vue.js·spring boot·后端·微信小程序·毕业设计·计算机毕业设计