Vue3 学习教程,从入门到精通,Vue3 样式绑定语法详解与案例(17)

发布于:2025-07-28 ⋅ 阅读:(16) ⋅ 点赞:(0)

Vue3 样式绑定语法详解与案例

一、样式绑定语法知识点

Vue3 提供了多种方式来绑定和操作元素的 class 和 style,以下是全部内容:

1. Class 绑定

(1) 对象语法
<div :class="{ active: isActive, 'text-danger': hasError }"></div>
(2) 数组语法
<div :class="[activeClass, errorClass]"></div>
(3) 三目运算符
<div :class="isActive ? 'active' : 'inactive'"></div>
(4) 绑定计算属性
<div :class="classObject"></div>
(5) 绑定组件上的 class
<my-component class="baz boo"></my-component>
<my-component :class="{ active: isActive }"></my-component>

2. Style 绑定

(1) 对象语法
<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
(2) 数组语法
<div :style="[baseStyles, overridingStyles]"></div>
(3) 自动前缀

Vue 会自动为需要浏览器前缀的 CSS 属性添加前缀

(4) 多重值
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>

二、详细案例代码

<template>
  <div>
    <!-- 1. 基本的 class 绑定 -->
    <div 
      class="static" 
      :class="{ active: isActive, 'text-danger': hasError }"
    >
      基本 class 绑定 - 对象语法
    </div>

    <!-- 2. 数组语法绑定 class -->
    <div :class="[activeClass, errorClass]">
      数组语法绑定 class
    </div>

    <!-- 3. 条件表达式绑定 class -->
    <div :class="isActive ? 'active' : 'inactive'">
      条件表达式绑定 class
    </div>

    <!-- 4. 使用计算属性绑定 class -->
    <div :class="classObject">
      使用计算属性绑定 class
    </div>

    <!-- 5. 组件上的 class 绑定 -->
    <my-component :class="{ active: isActive }"></my-component>

    <!-- 6. 基本的 style 绑定 -->
    <div :style="{ color: activeColor, fontSize: fontSize + 'px' }">
      基本的 style 绑定
    </div>

    <!-- 7. 数组语法绑定 style -->
    <div :style="[baseStyles, overridingStyles]">
      数组语法绑定 style
    </div>

    <!-- 8. 自动前缀示例 -->
    <div :style="{ transform: 'rotate(30deg)' }">
      自动前缀示例
    </div>

    <!-- 9. 多重值示例 -->
    <div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }">
      多重值示例
    </div>

    <!-- 10. 动态切换样式 -->
    <button @click="toggleActive">切换 active 状态</button>
    <button @click="toggleError">切换 error 状态</button>
  </div>
</template>

<script>
import { ref, computed } from 'vue';
import MyComponent from './MyComponent.vue';

export default {
  components: {
    MyComponent
  },
  setup() {
    // 响应式数据
    const isActive = ref(true);
    const hasError = ref(false);
    const activeColor = ref('red');
    const fontSize = ref(16);
    
    // class 相关数据
    const activeClass = ref('active');
    const errorClass = ref('text-danger');
    
    // style 相关数据
    const baseStyles = ref({
      backgroundColor: 'lightblue',
      padding: '10px'
    });
    
    const overridingStyles = ref({
      color: 'white',
      fontSize: '20px'
    });
    
    // 计算属性
    const classObject = computed(() => ({
      active: isActive.value && !hasError.value,
      'text-danger': hasError.value
    }));
    
    // 方法
    const toggleActive = () => {
      isActive.value = !isActive.value;
    };
    
    const toggleError = () => {
      hasError.value = !hasError.value;
    };
    
    return {
      isActive,
      hasError,
      activeColor,
      fontSize,
      activeClass,
      errorClass,
      baseStyles,
      overridingStyles,
      classObject,
      toggleActive,
      toggleError
    };
  }
};
</script>

<style>
.static {
  font-weight: bold;
}
.active {
  background-color: #4CAF50;
  color: white;
  padding: 10px;
  margin: 5px 0;
}
.inactive {
  background-color: #f44336;
  color: white;
  padding: 10px;
  margin: 5px 0;
}
.text-danger {
  border: 2px solid red;
}
</style>

三、组件中的样式绑定示例

<!-- MyComponent.vue -->
<template>
  <div class="my-component" :class="$attrs.class">
    <p>这是一个子组件</p>
    <p :style="componentStyle">组件内部样式绑定</p>
  </div>
</template>

<script>
import { computed } from 'vue';

export default {
  setup() {
    const componentStyle = computed(() => ({
      fontStyle: 'italic',
      fontWeight: 'bold'
    }));
    
    return {
      componentStyle
    };
  }
};
</script>

<style scoped>
.my-component {
  border: 1px solid #ccc;
  padding: 20px;
  margin: 10px 0;
}
</style>

四、完整案例代码

<template>
  <div class="container">
    <h1>Vue3 样式绑定案例演示</h1>
    
    <!-- 1. 对象语法 - Class 绑定 -->
    <div class="section">
      <h2>1. 对象语法 - Class 绑定</h2>
      <div 
        class="box" 
        :class="{ active: isActive, 'text-danger': hasError, 'text-success': isSuccess }"
      >
        对象语法示例 - 根据条件动态添加类
      </div>
      
      <button @click="toggleActive">切换激活状态</button>
      <button @click="toggleError">切换错误状态</button>
      <button @click="toggleSuccess">切换成功状态</button>
    </div>
    
    <!-- 2. 数组语法 - Class 绑定 -->
    <div class="section">
      <h2>2. 数组语法 - Class 绑定</h2>
      <div 
        class="box" 
        :class="[activeClass, errorClass, sizeClass]"
      >
        数组语法示例 - 动态组合多个类
      </div>
      
      <button @click="changeTheme">切换主题</button>
      <button @click="changeSize">切换大小</button>
    </div>
    
    <!-- 3. 对象语法 - Style 绑定 -->
    <div class="section">
      <h2>3. 对象语法 - Style 绑定</h2>
      <div 
        class="box"
        :style="{ color: textColor, fontSize: fontSize + 'px', backgroundColor: bgColor }"
      >
        对象语法样式绑定 - 动态改变内联样式
      </div>
      
      <button @click="changeColor">改变颜色</button>
      <button @click="changeFontSize">改变字体大小</button>
      <button @click="changeBackground">改变背景色</button>
    </div>
    
    <!-- 4. 数组语法 - Style 绑定 -->
    <div class="section">
      <h2>4. 数组语法 - Style 绑定</h2>
      <div 
        class="box"
        :style="[baseStyle, themeStyle]"
      >
        数组合并样式 - 基础样式 + 主题样式
      </div>
      
      <button @click="switchTheme">切换主题样式</button>
    </div>
    
    <!-- 5. 复杂绑定示例 -->
    <div class="section">
      <h2>5. 复杂绑定示例</h2>
      <div 
        class="box complex-box"
        :class="computedClass"
        :style="computedStyle"
      >
        复杂绑定示例 - 结合计算属性和多种绑定方式
      </div>
      
      <div class="controls">
        <button @click="isHighlighted = !isHighlighted">高亮切换</button>
        <button @click="boxSize += 10">增大尺寸</button>
        <button @click="boxSize = Math.max(50,  boxSize - 10)">减小尺寸</button>
      </div>
    </div>
    
    <!-- 6. 表单元素样式绑定 -->
    <div class="section">
      <h2>6. 表单元素样式绑定</h2>
      <input 
        type="text" 
        v-model="inputValue"
        :class="{ 
          'input-valid': inputValue.length  > 5, 
          'input-invalid': inputValue.length  > 0 && inputValue.length  <= 5 
        }"
        placeholder="输入至少6个字符"
      />
      
      <div class="input-status">
        状态: {{ inputValue.length  > 0 ? (inputValue.length  > 5 ? '有效' : '无效') : '请输入内容' }}
      </div>
    </div>
    
    <!-- 7. 列表项样式绑定 -->
    <div class="section">
      <h2>7. 列表项样式绑定</h2>
      <ul class="todo-list">
        <li 
          v-for="(item, index) in todoList" 
          :key="item.id" 
          :class="{ 
            'todo-item': true, 
            'completed': item.completed, 
            'priority-high': item.priority  === 'high',
            'priority-medium': item.priority  === 'medium',
            'priority-low': item.priority  === 'low'
          }"
          @click="toggleTodo(index)"
        >
          <span class="todo-text">{{ item.text  }}</span>
          <span class="todo-priority">[{{ item.priority  }}]</span>
        </li>
      </ul>
      
      <button @click="addTodo">添加待办事项</button>
    </div>
  </div>
</template>
 
<script>
import { ref, reactive, computed } from 'vue'
 
export default {
  name: 'StyleBindingDemo',
  setup() {
    // 1. 对象语法 - Class 绑定相关数据
    const isActive = ref(false)
    const hasError = ref(false)
    const isSuccess = ref(false)
    
    // 2. 数组语法 - Class 绑定相关数据 
    const activeClass = ref('primary-theme')
    const errorClass = ref('bordered')
    const sizeClass = ref('medium')
    
    // 3. 对象语法 - Style 绑定相关数据
    const textColor = ref('black')
    const fontSize = ref(16)
    const bgColor = ref('#f0f0f0')
    
    // 4. 数组语法 - Style 绑定相关数据 
    const baseStyle = reactive({
      padding: '20px',
      margin: '10px 0',
      border: '2px solid #ccc'
    })
    
    const themeStyle = ref({
      backgroundColor: '#e3f2fd',
      color: '#1976d2'
    })
    
    // 5. 复杂绑定示例数据 
    const isHighlighted = ref(false)
    const boxSize = ref(100)
    
    // 6. 表单元素样式绑定数据 
    const inputValue = ref('')
    
    // 7. 列表项样式绑定数据 
    const todoList = ref([
      { id: 1, text: '学习Vue3', completed: false, priority: 'high' },
      { id: 2, text: '完成项目', completed: true, priority: 'medium' },
      { id: 3, text: '休息一下', completed: false, priority: 'low' }
    ])
    
    // 计算属性 - 复杂class绑定
    const computedClass = computed(() => {
      return {
        'highlighted': isHighlighted.value, 
        'large-box': boxSize.value  > 80,
        'small-box': boxSize.value  <= 80
      }
    })
    
    // 计算属性 - 复杂style绑定
    const computedStyle = computed(() => {
      return {
        width: boxSize.value  + 'px',
        height: boxSize.value  + 'px',
        transition: 'all 0.3s ease'
      }
    })
    
    // 方法定义
    const toggleActive = () => {
      isActive.value  = !isActive.value  
    }
    
    const toggleError = () => {
      hasError.value  = !hasError.value 
    }
    
    const toggleSuccess = () => {
      isSuccess.value  = !isSuccess.value  
    }
    
    const changeTheme = () => {
      if (activeClass.value  === 'primary-theme') {
        activeClass.value  = 'secondary-theme'
      } else {
        activeClass.value  = 'primary-theme'
      }
    }
    
    const changeSize = () => {
      if (sizeClass.value  === 'medium') {
        sizeClass.value  = 'large'
      } else {
        sizeClass.value  = 'medium'
      }
    }
    
    const changeColor = () => {
      const colors = ['red', 'blue', 'green', 'purple', 'orange']
      textColor.value  = colors[Math.floor(Math.random() * colors.length)] 
    }
    
    const changeFontSize = () => {
      fontSize.value  = fontSize.value  === 16 ? 24 : 16
    }
    
    const changeBackground = () => {
      const colors = ['#f0f0f0', '#e3f2fd', '#fff3e0', '#f3e5f5']
      bgColor.value  = colors[Math.floor(Math.random() * colors.length)] 
    }
    
    const switchTheme = () => {
      if (themeStyle.value.backgroundColor  === '#e3f2fd') {
        themeStyle.value  = {
          backgroundColor: '#fce4ec',
          color: '#c2185b'
        }
      } else {
        themeStyle.value  = {
          backgroundColor: '#e3f2fd',
          color: '#1976d2'
        }
      }
    }
    
    const toggleTodo = (index) => {
      todoList.value[index].completed  = !todoList.value[index].completed 
    }
    
    const addTodo = () => {
      const priorities = ['high', 'medium', 'low']
      const newTodo = {
        id: Date.now(), 
        text: `新任务 ${todoList.value.length  + 1}`,
        completed: false,
        priority: priorities[Math.floor(Math.random() * priorities.length)] 
      }
      todoList.value.push(newTodo) 
    }
    
    // 返回所有需要在模板中使用的数据和方法
    return {
      // Class 绑定相关 
      isActive,
      hasError,
      isSuccess,
      activeClass,
      errorClass,
      sizeClass,
      
      // Style 绑定相关 
      textColor,
      fontSize,
      bgColor,
      baseStyle,
      themeStyle,
      
      // 复杂绑定相关 
      isHighlighted,
      boxSize,
      computedClass,
      computedStyle,
      
      // 表单相关
      inputValue,
      
      // 列表相关
      todoList,
      
      // 方法 
      toggleActive,
      toggleError,
      toggleSuccess,
      changeTheme,
      changeSize,
      changeColor,
      changeFontSize,
      changeBackground,
      switchTheme,
      toggleTodo,
      addTodo 
    }
  }
}
</script>
 
<style scoped>
/* 容器样式 */
.container {
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
  font-family: Arial, sans-serif;
}
 
/* 基础盒子样式 */
.box {
  padding: 20px;
  margin: 10px 0;
  border: 1px solid #ddd;
  border-radius: 4px;
  background-color: white;
  cursor: pointer;
  transition: all 0.3s ease;
}
 
/* Section 样式 */
.section {
  margin-bottom: 30px;
  padding: 20px;
  border: 1px solid #eee;
  border-radius: 8px;
}
 
.section h2 {
  margin-top: 0;
  color: #333;
}
 
/* 按钮样式 */
button {
  margin: 5px;
  padding: 8px 16px;
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
}
 
button:hover {
  background-color: #0056b3;
}
 
/* Class 绑定相关样式 */
.active {
  background-color: #d4edda !important;
  border-color: #c3e6cb !important;
}
 
.text-danger {
  color: #dc3545 !important;
}
 
.text-success {
  color: #28a745 !important;
}
 
.primary-theme {
  background-color: #007bff;
  color: white;
}
 
.secondary-theme {
  background-color: #6c757d;
  color: white;
}
 
.bordered {
  border: 3px solid #dc3545;
}
 
.medium {
  font-size: 16px;
}
 
.large {
  font-size: 20px;
}
 
/* 复杂绑定样式 */
.complex-box {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
}
 
.highlighted {
  box-shadow: 0 0 15px rgba(255, 165, 0, 0.5);
  border-color: orange;
}
 
.large-box {
  font-weight: bold;
}
 
.small-box {
  font-weight: normal;
}
 
/* 表单样式绑定 */
input {
  padding: 10px;
  border: 2px solid #ddd;
  border-radius: 4px;
  font-size: 16px;
  margin-bottom: 10px;
  width: 100%;
  box-sizing: border-box;
}
 
.input-valid {
  border-color: #28a745 !important;
  background-color: #d4edda !important;
}
 
.input-invalid {
  border-color: #dc3545 !important;
  background-color: #f8d7da !important;
}
 
.input-status {
  font-size: 14px;
  color: #666;
}
 
/* 待办列表样式 */
.todo-list {
  list-style: none;
  padding: 0;
}
 
.todo-item {
  padding: 15px;
  margin: 5px 0;
  border: 1px solid #ddd;
  border-radius: 4px;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  transition: all 0.2s ease;
}
 
.todo-item:hover {
  background-color: #f8f9fa;
}
 
.completed {
  background-color: #d4edda !important;
  text-decoration: line-through;
  color: #6c757d;
}
 
.priority-high {
  border-left: 5px solid #dc3545;
}
 
.priority-medium {
  border-left: 5px solid #ffc107;
}
 
.priority-low {
  border-left: 5px solid #28a745;
}
 
.todo-priority {
  font-size: 12px;
  font-weight: bold;
  text-transform: uppercase;
}
 
/* 控制按钮区域 */
.controls {
  margin-top: 15px;
}
</style>

五、关键点说明

  1. 动态 class 绑定

    • 对象语法适合条件性的 class
    • 数组语法适合同时应用多个 class
    • 计算属性适合复杂的逻辑
  2. 动态 style 绑定

    • Vue 会自动为需要浏览器前缀的 CSS 属性添加前缀
    • 推荐使用 camelCase (驼峰命名法) 来命名 CSS 属性
    • 可以传递样式对象数组来合并多个样式对象
  3. 组件上的 class

    • 组件上的 class 会被自动应用到组件的根元素上
    • 如果组件有多个根元素,需要使用 $attrs 手动绑定
  4. 性能考虑

    • 对于静态 class,直接使用 class 属性
    • 对于动态 class,使用 :class 绑定
    • 过度使用动态样式绑定可能会影响性能
  5. 样式作用域

    • 使用 <style scoped> 可以限制样式只作用于当前组件
    • 深度选择器 ::v-deep 可以影响子组件样式

网站公告

今日签到

点亮在社区的每一天
去签到