mustache-Vue编译
Vue 的模板基于 HTML,开发者可以直接在模板中编写 HTML 代码,HTML 解析器能够解析这些代码。
Vue 自己的模板编译系统
在开发过程中,我编写的 template
会被解析成 HTML 字符串,并转换成抽象语法树(AST)。表达式、自定义属性和指令会被转换成虚拟 DOM,通过对比差异生成补丁,最终渲染成真实的 DOM。
虚拟 DOM 的价值
虚拟 DOM 的主要价值在于高效地更新页面。当发现虚拟 DOM 与真实 DOM 之间存在差异时,才会生成补丁并应用到真实 DOM 上,从而优化性能。
<span>Vue</span>;
span.innerHTML = 'Vue';
指令
指令定义了模板渲染的逻辑行为,以下是常用的 Vue 指令及其使用方法。
v-once
指令用于一次性渲染插值内容,绑定的 DOM 元素不会再更新。
v-html
指令用于插入原始 HTML 内容,插值表达式是 JavaScript 表达式,不会对 DOM 进行操作。建议不要使用 v-html
来渲染子模板,而应将子模板放入子组件中。
动态属性名允许属性名根据数据动态改变。
<template>
<div>
<div>
<h1 v-bind:[attr]="tag">{{ title }}</h1>
<h1 v-bind:[null]="title">{{ title }}</h1>
<h1 v-bind:[myAttr]="title">{{ title }}</h1>
<a :[aAttr]="urls[0]" target="_blank">淘宝商城</a>
</div>
<div>
<button @[eventName]="">淘宝</button>
</div>
</div>
</template>
<script>
export default {
data() {
return {
linkIndex: 0,
aAttr: 'href',
eventName: 'click',
attr: 'data-tag',
myAttr: 'data-attr',
tag: 'h1',
title: 'This is my TITLE',
urls: ['https://www.taobao.com', 'https://www.tmall.com', 'https://www.jd.com'],
};
},
};
</script>
在上述示例中:
v-bind:[attr]="tag"
动态绑定属性名,属性名由attr
变量决定,属性值为tag
。v-bind:[null]="title"
使用null
作为属性名,实际不会绑定任何属性。v-bind:[myAttr]="title"
动态绑定自定义属性,属性名由myAttr
变量决定。:[aAttr]="urls[0]"
动态绑定href
属性,属性值为urls
数组的第一个元素。@[eventName]=""
动态绑定事件名,事件名由eventName
变量决定。
通过动态绑定属性名和事件名,可以根据不同的数据动态调整组件的行为和样式,提高代码的灵活性和可维护性。
组件通信
在 Vue 中,组件之间的通信是通过 props 和事件实现的。父组件通过 props 向子组件传递数据,子组件通过事件向父组件发送消息。这种单向数据流的方式使得组件之间的关系更加清晰和易于维护。
父组件传递数据给子组件
父组件可以通过在子组件标签上添加属性来传递数据。
<template>
<div>
<ChildComponent :message="parentMessage" />
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent,
},
data() {
return {
parentMessage: 'Hello from Parent',
};
},
};
</script>
在子组件中,通过 props
接收父组件传递的数据。
<template>
<div>
{{ message }}
</div>
</template>
<script>
export default {
props: {
message: {
type: String,
required: true,
},
},
};
</script>
子组件向父组件发送事件
子组件可以通过 $emit
方法触发自定义事件,通知父组件执行相应的操作。
<template>
<div>
<button @click="sendMessage">Send Message to Parent</button>
</div>
</template>
<script>
export default {
methods: {
sendMessage() {
this.$emit('message-sent', 'Hello from Child');
},
},
};
</script>
父组件监听子组件的自定义事件,并处理传递的数据。
<template>
<div>
<ChildComponent @message-sent="handleMessage" />
</div>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: {
ChildComponent,
},
methods: {
handleMessage(message) {
console.log(message);
},
},
};
</script>
通过 props 和事件,Vue 实现了父子组件之间的高效通信,确保数据流动的可预测性和组件的独立性。
计算属性和侦听器
计算属性和侦听器是 Vue 中处理数据变化的两种重要方式。计算属性用于基于已有数据计算出新的数据,而侦听器用于在数据变化时执行异步或开销较大的操作。
计算属性
计算属性基于它们的依赖进行缓存,只有相关依赖发生变化时,才会重新计算。这使得计算属性在性能上优于方法调用。
<template>
<div>
<p>Original Message: {{ message }}</p>
<p>Reversed Message: {{ reversedMessage }}</p>
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello Vue!',
};
},
computed: {
reversedMessage() {
return this.message.split('').reverse().join('');
},
},
};
</script>
在上述示例中,reversedMessage
是一个计算属性,它依赖于 message
。当 message
发生变化时,reversedMessage
会自动更新。
侦听器
侦听器用于观察 Vue 实例上的数据变动,当数据变化时执行相应的回调函数。适用于需要在数据变化时执行异步操作或开销较大的操作。
<template>
<div>
<input v-model="searchQuery" placeholder="Search..." />
<ul>
<li v-for="item in filteredItems" :key="item.id">{{ item.name }}</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
searchQuery: '',
items: [
{ id: 1, name: 'Apple' },
{ id: 2, name: 'Banana' },
{ id: 3, name: 'Cherry' },
],
filteredItems: [],
};
},
watch: {
searchQuery(newQuery) {
this.filteredItems = this.items.filter((item) => item.name.toLowerCase().includes(newQuery.toLowerCase()));
},
},
created() {
this.filteredItems = this.items;
},
};
</script>
在上述示例中,当 searchQuery
变化时,侦听器会过滤 items
并更新 filteredItems
,从而动态显示匹配的结果。
通过合理使用计算属性和侦听器,可以提高应用的响应速度和用户体验。
生命周期钩子
Vue 实例在创建过程中会经历多个生命周期阶段,每个阶段都有对应的生命周期钩子,允许开发者在特定时机执行代码。
常用的生命周期钩子
created
: 实例创建完成后被调用,此时数据已设置,事件已配置,但 DOM 尚未挂载。mounted
: 实例挂载到 DOM 后被调用,此时可以访问到 DOM 元素。updated
: 数据更新导致虚拟 DOM 重新渲染和打补丁后调用。destroyed
: 实例销毁后调用,适合进行清理工作。
<template>
<div>
<p>Current Time: {{ currentTime }}</p>
</div>
</template>
<script>
export default {
data() {
return {
currentTime: '',
};
},
created() {
console.log('Component is created');
this.currentTime = new Date().toLocaleTimeString();
},
mounted() {
console.log('Component is mounted');
this.timer = setInterval(() => {
this.currentTime = new Date().toLocaleTimeString();
}, 1000);
},
updated() {
console.log('Component is updated');
},
destroyed() {
console.log('Component is destroyed');
clearInterval(this.timer);
},
};
</script>
在上述示例中:
created
钩子用于初始化数据。mounted
钩子开始一个定时器,每秒更新一次currentTime
。updated
钩子在数据更新后记录日志。destroyed
钩子在组件销毁时清理定时器。
了解和合理利用生命周期钩子,可以帮助开发者更好地控制组件的行为和资源管理。
结语
通过本文的介绍,您已经了解了 Vue 的模板语法、指令、组件通信、计算属性与侦听器以及生命周期钩子等核心概念。这些知识点是构建高效、可维护 Vue 应用的基础。建议在实际项目中多加练习和应用,以深入掌握 Vue 的强大功能。