1.属性绑定v-bind(:)
v-bind 是 Vue 2 中用于动态绑定属性的核心指令,它支持多种语法和用法,能够灵活地绑定 DOM 属性、组件 prop,甚至动态属性名。通过 v-bind,可以实现数据与视图之间的高效同步,是构建动态界面的重要工具。
<template><div class="demo-container"><!-- 基础属性绑定 --><div :id="dynamicId">动态 ID 的 div</div><!-- 绑定多个属性 --><div :="{ id: dynamicId, title: dynamicTitle, class: 'my-class' }">绑定多个属性</div><!-- 动态属性名 --><div :[attributeName]="attributeValue">动态属性名绑定</div><!-- 布尔属性绑定 --><button :disabled="isDisabled">点击我</button><!-- 绑定组件的 prop --><child-component :message="parentMessage" :title.sync="parentTitle"></child-component></div>
</template><script>
// 定义子组件
const ChildComponent = {props: {message: String,title: String},template: `<div><h3>子组件</h3><p>从父组件接收到的 message: {{ message }}</p><p>从父组件接收到的 title: {{ title }}</p><button @click="updateTitle">更新父组件的 title</button></div>`,methods: {updateTitle() {// 使用 $emit 触发父组件的更新this.$emit('update:title', '新的标题');}}
};export default {name: "demo",components: {ChildComponent},data() {return {dynamicId: 'my-dynamic-id', // 动态 IDdynamicTitle: '这是一个标题', // 动态标题attributeName: 'class', // 动态属性名attributeValue: 'my-class', // 动态属性值isDisabled: false, // 布尔属性parentMessage: 'Hello from parent!', // 父组件的 messageparentTitle: '初始标题' // 父组件的 title};}
};
</script><style scoped>
.demo-container {margin: 20px;padding: 20px;border: 1px solid #ccc;
}
.my-class {color: blue;font-weight: bold;
}
button {margin-top: 10px;
}
</style>
1.1示例代码中的父子组件通信
-
父组件向子组件传递数据
-
父组件在模板中使用
:message="parentMessage"和:title.sync="parentTitle"。 -
Vue 会将
parentMessage和parentTitle的值传递给子组件的message和title。 -
子组件通过
props接收这些值,并可以在模板中使用。
-
-
子组件向父组件传递事件
-
子组件在模板中有一个按钮,点击按钮时调用
updateTitle方法。 -
updateTitle方法通过this.$emit('update:title', '新的标题')触发一个自定义事件update:title,并传递新值'新的标题'。 -
父组件监听到
update:title事件后,会自动更新parentTitle的值为'新的标题'。
-
1.2面试问题:
-
如何实现父子组件之间的数据传递?
-
父组件如何向子组件传递数据?
-
子组件如何向父组件传递事件?
回答要点:
-
父组件向子组件传递数据: 使用
props。-
父组件通过
v-bind将数据绑定到子组件的props。 -
子组件通过
props接收父组件传递的数据。
-
-
子组件向父组件传递事件: 使用
$emit。-
子组件通过
this.$emit触发一个自定义事件,并传递数据。 -
父组件通过监听子组件的事件来接收数据。
<!-- 父组件 --> <template><div><child-component :message="parentMessage" @update:title="handleTitleUpdate"></child-component></div> </template><script> import ChildComponent from './ChildComponent.vue';export default {components: {ChildComponent},data() {return {parentMessage: 'Hello from parent!',parentTitle: 'Initial Title'};},methods: {handleTitleUpdate(newTitle) {this.parentTitle = newTitle;}} }; </script><!-- 子组件 --> <template><div><p>Message from parent: {{ message }}</p><button @click="updateTitle">Update Parent Title</button></div> </template><script> export default {props: {message: String},methods: {updateTitle() {this.$emit('update:title', 'New Title');}} }; </script> -
.sync修饰符的作用-
简化父子组件之间的双向绑定。
-
-
2.事件绑定 v-on(@)
v-on 是 Vue.js 中用于绑定事件监听器的指令,它允许你为 DOM 元素或组件绑定事件处理函数。通过 v-on,你可以监听用户的交互行为(如点击、输入等),并在事件触发时执行特定的逻辑。
<template><div><h1>事件绑定示例</h1><button @click="handleClick">点击我</button><input type="text" @input="handleInput($event)"><a href="https://example.com" @click.prevent="handleLinkClick">链接</a><div @click="handleDivClick"><button @click.stop="handleButtonClick">点击我</button></div><input type="text" @keyup.enter="handleSubmit"></div>
</template><script>
export default {methods: {handleClick() {alert('按钮被点击了!');},handleInput(event) {console.log('输入框的值:', event.target.value);},handleLinkClick() {alert('链接被点击了,但不会跳转!');},handleDivClick() {alert('div 被点击了!');},handleButtonClick() {alert('按钮被点击了,但不会触发 div 的点击事件!');},handleSubmit() {alert('回车键被按下,表单提交!');}}
};
</script>
2.1基本用法
1. 监听原生 DOM 事件
v-on 可以用来监听原生 DOM 事件,例如 click、input、mouseover 等。
<button @click="handleClick">点击我</button>
2. 监听组件事件
v-on 也可以用来监听自定义组件的事件。子组件通过 $emit 触发事件,父组件通过 v-on 监听这些事件。
<child-component @custom-event="handleCustomEvent"></child-component>
-
custom-event是子组件触发的自定义事件。 -
handleCustomEvent是父组件中定义的事件处理函数。
3. 传递事件参数
在事件处理函数中,你可能需要访问事件对象(例如获取输入框的值或鼠标的位置)。可以通过 $event 获取事件对象。
<input type="text" @input="handleInput($event)">
4. 传递额外参数
除了事件对象,你还可以传递其他参数到事件处理函数。
<button @click="handleClick('Hello', $event)">点击我</button>methods: {handleClick(message, event) {console.log(message); // 输出 "Hello"console.log(event.type); // 输出 "click"}
}
5.事件修饰符
Vue 为 v-on 提供了一些事件修饰符,用于更方便地处理常见的事件行为。
.stop:阻止事件冒泡
-
点击按钮时,
handleButtonClick会被触发,但不会触发handleDivClick。
<div @click="handleDivClick"><button @click.stop="handleButtonClick">点击我</button>
</div>
.prevent:阻止默认行为
-
点击链接时,不会跳转到
https://example.com,因为默认行为被阻止了。
<a href="https://example.com" @click.prevent="handleLinkClick">链接</a>
.capture:使用事件捕获模式
-
在事件冒泡阶段,
handleDivClick会在handleButtonClick之前被触发。
<div @click.capture="handleDivClick"><button @click="handleButtonClick">点击我</button>
</div>
.self:只触发绑定元素自身的事件
-
只有直接点击按钮时,
handleButtonClick才会被触发。
<div @click="handleDivClick"><button @click.self="handleButtonClick">点击我</button>
</div>
.once:事件只触发一次
-
handleClick只会在第一次点击时被触发,之后的点击不会触发。
2.2总结
v-on 是 Vue 中非常强大的指令,用于绑定事件监听器。它支持以下功能:
-
监听原生 DOM 事件和自定义组件事件。
-
传递事件对象和额外参数。
-
使用事件修饰符(如
.stop、.prevent、.capture等)简化事件处理逻辑。 -
使用键盘修饰符(如
.enter、.tab等)处理键盘事件。
3.双向绑定v-model
v-model 是 Vue 中实现双向数据绑定的核心指令,它允许你将表单输入和应用状态进行同步。通过 v-model,表单元素的值会自动与 Vue 实例的数据保持一致,同时用户对表单的修改也会实时更新到数据中,反之亦然。这种双向绑定机制是 Vue 的一大特色,极大地简化了表单处理逻辑。
3.1基本用法
<template><div class="v-model-demo"><h2>v-model 双向绑定示例</h2><!-- 输入框 --><div><label for="text-input">输入框:</label><input id="text-input" v-model="message" placeholder="输入内容"><p>输入的内容是:{{ message }}</p></div><!-- 多行文本框 --><div><label for="textarea">多行文本框:</label><textarea id="textarea" v-model="multiLineMessage" placeholder="输入多行内容"></textarea><p>输入的内容是:</p><p style="white-space: pre">{{ multiLineMessage }}</p></div><!-- 单个复选框 --><div><label><input type="checkbox" v-model="singleCheckbox"> 单个复选框</label><p>复选框是否选中:{{ singleCheckbox }}</p></div><!-- 多个复选框 --><div><label><input type="checkbox" v-model="checkedCities" value="北京"> 北京</label><label><input type="checkbox" v-model="checkedCities" value="上海"> 上海</label><label><input type="checkbox" v-model="checkedCities" value="广州"> 广州</label><p>选中的城市:{{ checkedCities }}</p></div><!-- 单选按钮 --><div><label><input type="radio" v-model="picked" value="A"> A</label><label><input type="radio" v-model="picked" value="B"> B</label><p>选中的选项是:{{ picked }}</p></div><!-- 下拉选择框 --><div><label for="select">下拉选择框:</label><select id="select" v-model="selected"><option disabled value="">请选择</option><option value="北京">北京</option><option value="上海">上海</option><option value="广州">广州</option></select><p>选中的城市是:{{ selected }}</p></div></div>
</template><script>
export default {name: "VModelDemo",data() {return {message: "", // 输入框绑定的数据multiLineMessage: "", // 多行文本框绑定的数据singleCheckbox: false, // 单个复选框绑定的数据checkedCities: [], // 多个复选框绑定的数据picked: "", // 单选按钮绑定的数据selected: "" // 下拉选择框绑定的数据};}
};
</script><style scoped>
.v-model-demo {margin: 20px;font-family: Arial, sans-serif;
}
label {margin-right: 10px;
}
p {margin: 10px 0;
}
textarea {width: 100%;height: 100px;
}
select {width: 100%;
}
</style>
v-model 的工作原理
v-model 实际上是一个语法糖,它背后做了以下几件事:
-
绑定
value属性:-
对于
<input>和<textarea>,v-model会绑定value属性。 -
对于
<select>,v-model会绑定value属性到选中的<option>。 -
对于
<input type="checkbox">和<input type="radio">,v-model会绑定value属性到对应的值。
-
-
监听
input或change事件:-
v-model会监听表单元素的input事件(对于<input>和<textarea>)或change事件(对于<select>、<input type="checkbox">和<input type="radio">)。 -
当事件触发时,它会自动更新绑定的数据。
-
3.2v-model 修饰符
<template><div class="v-model-modifiers-demo"><h2>v-model 修饰符示例</h2><!-- .lazy 修饰符 --><div><label for="lazy-input">输入框(.lazy):</label><input id="lazy-input" v-model.lazy="lazyMessage" placeholder="输入内容"><p>输入的内容是:{{ lazyMessage }}</p><!--.lazy 修饰符:- 默认情况下,v-model 在每次 input 事件触发时更新数据。- 使用 .lazy 修饰符后,数据会在 change 事件触发时更新,即用户离开输入框时。--></div><!-- .number 修饰符 --><div><label for="number-input">输入框(.number):</label><input id="number-input" v-model.number="numberValue" type="number" placeholder="输入数字"><p>输入的数字是:{{ numberValue }}</p><!--.number 修饰符:- 默认情况下,v-model 会将输入框的值作为字符串处理。- 使用 .number 修饰符后,输入框的值会自动转换为数字类型。--></div><!-- .trim 修饰符 --><div><label for="trim-input">输入框(.trim):</label><input id="trim-input" v-model.trim="trimMessage" placeholder="输入内容"><p>输入的内容是:{{ trimMessage }}</p><!--.trim 修饰符:- 默认情况下,v-model 会保留输入框的首尾空格。- 使用 .trim 修饰符后,输入框的值会自动去除首尾空格。--></div></div>
</template><script>
export default {name: "VModelModifiersDemo",data() {return {lazyMessage: "", // .lazy 修饰符绑定的数据numberValue: 0, // .number 修饰符绑定的数据trimMessage: "" // .trim 修饰符绑定的数据};}
};
</script><style scoped>
.v-model-modifiers-demo {margin: 20px;font-family: Arial, sans-serif;
}
label {margin-right: 10px;
}
p {margin: 10px 0;
}
input {width: 100%;padding: 8px;margin-bottom: 10px;
}
</style>
-
输入框(.lazy):
-
用户输入内容时,数据不会立即更新,直到用户离开输入框(触发
change事件)。 -
{{ lazyMessage }}会显示最终的输入内容。
-
-
输入框(.number):
-
用户输入数字时,数据会自动转换为数字类型。
-
{{ numberValue }}会显示数字类型的值。
-
-
输入框(.trim):
-
用户输入内容时,首尾空格会被自动去除。
-
{{ trimMessage }}会显示去除首尾空格后的内容。
-
3.3自定义组件中的 v-model
在自定义组件中,v-model 默认绑定的是子组件的 value 属性和 input 事件。如果你需要自定义 v-model 的行为,可以通过 props 和 $emit 来实现。
<template><div><custom-input v-model="message"></custom-input><p>输入的内容是:{{ message }}</p></div>
</template><script>
import CustomInput from './CustomInput.vue';export default {components: {CustomInput},data() {return {message: ''};}
};
</script>
<!-- CustomInput.vue -->
<template><input:value="value"@input="$emit('input', $event.target.value)"placeholder="输入内容">
</template><script>
export default {props: ['value']
};
</script>
-
工作原理
-
父组件传递数据到子组件:
-
父组件通过
v-model="message"将message的值传递给子组件的valueprop。 -
子组件的
valueprop会接收这个值,并将其绑定到输入框的value属性上。
-
-
子组件向父组件发送数据:
-
当用户在输入框中输入内容时,
input事件被触发。 -
子组件通过
$emit('input', $event.target.value)将用户输入的值发送回父组件。 -
父组件监听到
input事件后,会更新message的值。
-
-
双向绑定:
-
父组件的
message和子组件的输入框内容始终保持同步。 -
用户在输入框中输入的内容会实时更新到父组件的
message中。 -
父组件的
message如果发生变化,输入框的内容也会自动更新。
-
4.计算属性 Computed
在 Vue 2 中,计算属性(Computed Properties)是一种非常强大的功能,它允许你基于 Vue 实例的数据动态计算值。计算属性是响应式的,当依赖的响应式数据发生变化时,计算属性会自动重新计算并更新。
计算属性通常用于以下场景:
-
基于现有数据派生新数据:例如,将用户的输入转换为大写或计算总价。
-
简化模板逻辑:避免在模板中编写复杂的逻辑。
-
缓存计算结果:计算属性会缓存结果,只有当依赖的数据发生变化时才会重新计算。
计算属性通过 computed 选项定义。计算属性的值由一个函数返回,这个函数的返回值会自动绑定到模板中。
<template><div><p>原字符串:{{ message }}</p><p>大写字符串:{{ upperCaseMessage }}</p></div>
</template><script>
export default {data() {return {message: 'hello'};},computed: {upperCaseMessage() {return this.message.toUpperCase();}}
};
</script>
-
data:定义了响应式数据message。 -
computed:定义了计算属性upperCaseMessage。-
upperCaseMessage是一个函数,返回message的大写形式。 -
计算属性的值会自动更新,当
message发生变化时,upperCaseMessage也会重新计算。
-
计算属性的缓存机制
计算属性是基于它们的依赖进行缓存的。只有当依赖的响应式数据发生变化时,计算属性才会重新计算。这意味着如果你的依赖数据没有变化,计算属性的值不会重新计算,从而提高性能。
计算属性与方法的区别
计算属性和方法都可以基于数据动态计算值,但它们有一些关键区别:
-
缓存机制:
-
计算属性:会缓存结果,只有当依赖的响应式数据发生变化时才会重新计算。
-
方法:每次调用都会重新计算,不会缓存结果。
-
-
使用场景:
-
计算属性:适用于基于现有数据派生新数据的场景,尤其是需要缓存结果的场景。
-
方法:适用于需要动态执行的逻辑,例如事件处理函数。
-