VueJS - 绑定
Vue 3 - 属性、Class、样式和表单绑定
Section titled “Vue 3 - 属性、Class、样式和表单绑定”Vue 的数据绑定系统允许你声明式地将应用数据连接到 DOM。本章介绍如何在 Vue 3 中使用 v-bind 和 v-model 等指令来绑定 HTML 属性、Class、内联样式和表单输入。
绑定 HTML 属性 (v-bind 或 :)
Section titled “绑定 HTML 属性 (v-bind 或 :)”你不能在 HTML 属性内部使用标准的 Mustache 语法 ({{ }})。相反,请使用 v-bind 指令或其简写形式 : 将属性绑定到 JavaScript 表达式或数据属性。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Vue 3 Attribute Binding</title> <script src="https://unpkg.com/vue@3"></script></head><body> <div id="app-attr"> <!-- 错误:将直接渲染 href="{{ googleLink }}" --> <!-- <a href="{{ googleLink }}">Google (Incorrect)</a> -->
<!-- 正确:使用 v-bind --> <a v-bind:href="googleLink" target="_blank">Google (v-bind)</a> <br>
<!-- 正确:使用简写形式 : --> <a :href="yahooLink" target="_blank">Yahoo (shorthand)</a> <br>
<!-- 绑定元素的 ID --> <p :id="paragraphId">This paragraph has a dynamic ID.</p>
<!-- 有条件地禁用按钮 --> <button :disabled="isButtonDisabled">{{ isButtonDisabled ? 'Disabled' : 'Enabled' }}</button> <button @click="toggleButton">Toggle Disable</button> </div>
<script> const { createApp, ref } = Vue;
createApp({ setup() { const googleLink = ref('https://www.google.com'); const yahooLink = ref('https://www.yahoo.com'); const paragraphId = ref('my-unique-paragraph'); const isButtonDisabled = ref(false);
function toggleButton() { isButtonDisabled.value = !isButtonDisabled.value; }
return { googleLink, yahooLink, paragraphId, isButtonDisabled, toggleButton }; } }).mount('#app-attr'); </script></body></html>v-bind:href 或 :href 将锚点标签的 href 属性绑定到 googleLink 或 yahooLink 响应式变量的值。类似地,:id 绑定段落的 ID,而 :disabled 动态绑定按钮的禁用状态。
绑定 HTML Class (v-bind:class 或 :class)
Section titled “绑定 HTML Class (v-bind:class 或 :class)”你可以通过将 :class 绑定到一个对象或数组来动态切换 Class。
绑定到一个对象,其中键是 Class 名称,值是布尔表达式,用于确定是否应应用该 Class。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Vue 3 Class Binding (Object)</title> <script src="https://unpkg.com/vue@3"></script> <style> .active { background-color: lightgreen; font-weight: bold; } .text-danger { color: red; } .base-style { padding: 10px; border: 1px solid #ccc; margin-top: 10px; } </style></head><body> <div id="app-class-obj"> <div class="base-style" :class="{ active: isActive, 'text-danger': hasError }"> This div's classes change dynamically. </div> <button @click="isActive = !isActive">Toggle Active</button> <button @click="hasError = !hasError">Toggle Error</button>
<!-- 也可以绑定到一个返回对象的 computed (计算属性) --> <div class="base-style" :class="classObject"> Bound to computed object. </div> </div>
<script> const { createApp, ref, computed } = Vue;
createApp({ setup() { const isActive = ref(true); const hasError = ref(false);
// 返回 Class 对象的 computed (计算属性) const classObject = computed(() => ({ active: isActive.value, 'text-danger': hasError.value // 你可以在这里添加更多静态或动态 Class }));
return { isActive, hasError, classObject }; } }).mount('#app-class-obj'); </script></body></html>active Class 仅在 isActive 为 true 时应用,而 text-danger 仅在 hasError 为 true 时应用。请注意,text-danger 这样的 kebab-case 风格的 Class 名在对象键中需要使用引号。你可以混合使用静态(base-style)和动态 Class。
绑定到一个数组,其中包含 Class 名称(字符串)或对象(使用对象语法)。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Vue 3 Class Binding (Array)</title> <script src="https://unpkg.com/vue@3"></script> <style> .active { background-color: lightblue; } .important { font-weight: bold; border: 2px solid blue; } .base { padding: 15px; margin-top: 10px; } </style></head><body> <div id="app-class-arr"> <div :class="['base', 'important', { active: isActive }]"> Mixing array and object syntax. </div> <button @click="isActive = !isActive">Toggle Active</button>
<!-- 绑定到一个返回数组的 computed (计算属性) --> <div :class="classArray"> Bound to computed array. </div> </div>
<script> const { createApp, ref, computed } = Vue;
createApp({ setup() { const isActive = ref(false); const activeClass = ref('active'); // 变量中的 Class 名称 const importantClass = ref('important');
const classArray = computed(() => [ 'base', importantClass.value, // 动态获取 Class 名称 isActive.value ? activeClass.value : '' // 条件 Class ]);
return { isActive, classArray }; } }).mount('#app-class-arr'); </script></body></html>这将始终应用 base 和 important Class,并根据 isActive 有条件地应用 active Class。你可以使用三元运算符或在数组中包含对象。
当在自定义组件上使用 :class 时,这些 Class 将被添加到组件的根元素上,并与根元素上已有的 Class 合并。
绑定内联样式 (v-bind:style 或 :style)
Section titled “绑定内联样式 (v-bind:style 或 :style)”将 :style 绑定到一个对象或对象数组。
推荐使用对象语法。CSS 属性名可以使用 camelCase (驼峰式) 或 kebab-case (烤串式)(kebab-case 需要加引号)。
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Vue 3 Style Binding (Object)</title> <script src="https://unpkg.com/vue@3"></script></head><body> <div id="app-style-obj"> <!-- 直接对象绑定 --> <div :style="{ color: activeColor, fontSize: fontSize + 'px', 'margin-top': '10px' }"> Style bound directly. </div>
<!-- 绑定到数据对象 --> <div :style="styleObject"> Style bound to data object. </div>
<label>Color:</label> <input v-model="activeColor"> <label>Font Size (px):</label> <input type="range" v-model="fontSize" min="10" max="40"> </div>
<script> const { createApp, ref, computed } = Vue;
createApp({ setup() { const activeColor = ref('blue'); const fontSize = ref(16);
// 返回样式对象的 computed (计算属性) const styleObject = computed(() => ({ color: activeColor.value, fontSize: `${fontSize.value}px` // 使用模板字符串 // backgroundColor: 'lightyellow' // 添加更多样式 }));
return { activeColor, fontSize, styleObject }; } }).mount('#app-style-obj'); </script></body></html>文本颜色和字体大小由 activeColor 和 fontSize 变量动态控制。
你可以将 :style 绑定到多个样式对象的数组。这在应用来自不同来源的样式时非常有用。
<div id="app-style-arr"> <div :style="[baseStyles, overrideStyles]"> Style bound to array of objects. </div></div>
<script> const { createApp, ref } = Vue; createApp({ setup() { const baseStyles = ref({ fontWeight: 'bold', padding: '10px' }); const overrideStyles = ref({ color: 'green', border: '1px solid green' }); return { baseStyles, overrideStyles }; } }).mount('#app-style-arr');</script>overrideStyles 中的样式将与 baseStyles 中的样式合并,如果它们针对同一属性,则会覆盖 baseStyles 中的样式。
对于通过 :style 绑定的 CSS 属性,Vue 会在需要的地方自动添加供应商前缀(如 -webkit-)。
表单输入绑定 (v-model)
Section titled “表单输入绑定 (v-model)”v-model 指令在表单输入元素(<input>、<textarea>、<select>)上创建双向数据绑定。它会根据输入类型自动选择更新元素的正确方式。
示例:文本输入、Textarea、复选框、单选按钮、Select
Section titled “示例:文本输入、Textarea、复选框、单选按钮、Select”<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Vue 3 v-model Example</title> <script src="https://unpkg.com/vue@3"></script> <style> form > div { margin-bottom: 15px; } label { margin-right: 10px; } </style></head><body> <div id="app-v-model"> <form @submit.prevent> <!-- 文本输入 --> <div> <label for="name">Name:</label> <input type="text" id="name" v-model="formData.name" placeholder="Enter name"> <p>Entered Name: {{ formData.name }}</p> </div>
<!-- 文本区域 --> <div> <label for="message">Message:</label> <textarea id="message" v-model="formData.message" placeholder="Enter message"></textarea> <p style="white-space: pre-line;">Entered Message: {{ formData.message }}</p> </div>
<!-- 单个复选框 (布尔值) --> <div> <input type="checkbox" id="agree" v-model="formData.agreed"> <label for="agree">Agree to terms</label> <p>Agreed: {{ formData.agreed }}</p> </div>
<!-- 多个复选框 (数组) --> <div> <span>Interests:</span> <input type="checkbox" id="tech" value="Technology" v-model="formData.interests"> <label for="tech">Technology</label> <input type="checkbox" id="music" value="Music" v-model="formData.interests"> <label for="music">Music</label> <input type="checkbox" id="sports" value="Sports" v-model="formData.interests"> <label for="sports">Sports</label> <p>Selected Interests: {{ formData.interests }}</p> </div>
<!-- 单选按钮 --> <div> <span>Favorite Color:</span> <input type="radio" id="red" value="Red" v-model="formData.favoriteColor"> <label for="red">Red</label> <input type="radio" id="green" value="Green" v-model="formData.favoriteColor"> <label for="green">Green</label> <p>Selected Color: {{ formData.favoriteColor }}</p> </div>
<!-- Select 下拉列表 --> <div> <label for="country">Country:</label> <select id="country" v-model="formData.country"> <option disabled value="">Please select one</option> <option>USA</option> <option>Canada</option> <option>Mexico</option> </select> <p>Selected Country: {{ formData.country }}</p> </div> <!-- Select 多选 (数组) --> <div> <label for="options">Options (Multiple):</label> <select id="options" v-model="formData.selectedOptions" multiple> <option value="A">Option A</option> <option value="B">Option B</option> <option value="C">Option C</option> </select> <p>Selected Options: {{ formData.selectedOptions }}</p> </div>
</form> </div>
<script> const { createApp, reactive } = Vue;
createApp({ setup() { const formData = reactive({ name: '', message: '', agreed: false, interests: [], // 多个复选框对应的数组 favoriteColor: 'Red', // 初始单选选择 country: '', // 初始 Select 值 selectedOptions: [] // 多选 Select 对应的数组 });
return { formData }; } }).mount('#app-v-model'); </script></body></html>v-model将表单元素的值与formData中对应的属性同步。- 对于文本输入和 textarea,它使用
value属性和input事件。 - 对于复选框,它使用
checked属性和change事件。单个复选框绑定到布尔值,而多个v-model相同的复选框绑定到一个包含其value属性值的数组。 - 对于单选按钮,它使用
checked属性和change事件,绑定到被选中的单选按钮的value值。 - 对于 Select 字段,它使用
value和change。单个 Select 绑定到被选中选项的value值。多选 Select 绑定到一个包含被选中选项value值的数组。
v-model 修饰符
Section titled “v-model 修饰符”v-model 内置了一些修饰符:
- .lazy: 在
change事件后而非input事件后同步(例如,当输入框失去焦点时更新,而不是在每次按键时更新)。 - .number: 自动将输入值类型转换为数字。如果值无法解析为数字,则返回原始值。
- .trim: 自动去除用户输入的头尾空格。
<input v-model.lazy="message"> <!-- 输入框失去焦点时更新 --><input v-model.number="age" type="number"> <!-- 确保 age 是一个数字 --><input v-model.trim="username"> <!-- 移除头尾空格 -->数据绑定是 Vue 的基石,它实现了应用状态与用户界面之间的无缝同步。