Vue3 学习教程,从入门到精通,Vue3 样式绑定语法详解与案例(17)
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>
五、关键点说明
-
动态 class 绑定:
- 对象语法适合条件性的 class
- 数组语法适合同时应用多个 class
- 计算属性适合复杂的逻辑
-
动态 style 绑定:
- Vue 会自动为需要浏览器前缀的 CSS 属性添加前缀
- 推荐使用 camelCase (驼峰命名法) 来命名 CSS 属性
- 可以传递样式对象数组来合并多个样式对象
-
组件上的 class:
- 组件上的 class 会被自动应用到组件的根元素上
- 如果组件有多个根元素,需要使用
$attrs
手动绑定
-
性能考虑:
- 对于静态 class,直接使用 class 属性
- 对于动态 class,使用 :class 绑定
- 过度使用动态样式绑定可能会影响性能
-
样式作用域:
- 使用
<style scoped>
可以限制样式只作用于当前组件 - 深度选择器
::v-deep
可以影响子组件样式
- 使用