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 库,做完这篇你就能独立写表单了。

相关推荐
用户5508492902562 分钟前
CSS布局实战:从Flex到Grid的完整避坑指南
前端
用户5508492902563 分钟前
前端接口请求层怎么封装?一个可落地的请求方案
前端
MetWeave16 分钟前
跟着一条 SPECI 走流水线:从电报到界面
前端
用户91775337187523 分钟前
从零封装一个地图组件库:OpenLayers + Vue 的工程化实践
vue.js
Helix25034 分钟前
Chrome 开发者工具进阶:长截图、网络调试与性能分析
前端·chrome·chrome devtools·使用技巧·性能分析·开发者工具·长截图
liangshanbo12151 小时前
面试题:Webpack 的 publicPath 有什么作用?
前端·webpack·node.js
mjhcsp1 小时前
DeepSeek V4.1 Flash 批量处理效能实测
java·前端·数据库
听风若依1 小时前
数据在内存中的存储-纸面笔记整理
c语言·笔记
xiaominngtongxue1 小时前
从中职技能节看实训教学的组织逻辑
笔记
雪芽蓝域zzs2 小时前
第7节:多选模式、自定义选项渲染、受控弹窗显隐
vue.js·elementui