vue2与vue3生命周期详解
vue2
beforeCreate
在Vue.js中,beforeCreate生命周期钩子是在实例初始化后,但在数据观测和事件配置之前被调用的。这里的“数据观测”和“事件配置”具体指的是:
数据观测(Data Observation)
Vue.js的核心特性之一就是数据绑定和响应式系统。当你创建一个Vue实例时,其data对象会被转换成响应式的(“转换成响应式”是指将普通的JavaScript对象或属性转换为具有特殊行为的对象或属性,这种行为主要是为了支持数据绑定和响应式更新。当Vue实例化时,它会遍历data对象中的所有属性,并使用*Object.defineProperty()*方法将每个属性转换为getter和setter。这一过程称为数据的“响应式化”)。这意味着当data对象中的属性发生变化时,所有依赖于这些属性的视图部分将会自动更新。
在beforeCreate阶段,Vue实例的data对象还没有被转换成响应式。因此,在这个阶段,你无法访问到响应式的data属性,因为它们尚未被处理和代理到Vue实例的上下文中。数据观测的过程发生在created钩子之前。
事件配置(Event Configuration)
事件配置指的是Vue实例上的事件监听器和计算属性(computed properties)、侦听器(watchers)的设置。在beforeCreate阶段,这些事件监听器和侦听器还没有被设置。这意味着在这个阶段,你不能触发任何基于事件的行为,也不能访问到计算属性和侦听器的结果,因为它们尚未初始化。
例如,如果你在Vue实例中定义了一个计算属性或一个watcher,那么在beforeCreate钩子中,这些计算属性或watcher不会存在或工作,因为它们的初始化发生在beforeCreate之后。
created
在实例创建完成后被立即调用。此时,实例已完成了数据观测和属性计算,同时也完成了methods和watch/event事件的配置。
beforeMount(挂载前)
在挂载开始之前被调用,此时模板已经编译完成,但尚未渲染成html。
**模板:**模板通常指的是用于描述UI组件结构的标记语言,这些模板可以包含动态数据绑定和条件逻辑
<template>
<div class="greeting">
<!-- 动态数据绑定 -->
<h1>{{ message }}</h1>
<!-- 条件渲染 -->
<p v-if="showDetail">
Welcome to your {{ appName }} application!
</p>
<!-- 列表渲染 -->
<ul>
<li v-for="(item, index) in items" :key="index">
{{ item.name }} - Quantity: {{ item.quantity }}
</li>
</ul>
<!-- 事件处理 -->
<button @click="reverseMessage">Reverse Message</button>
</div>
</template>
<script>
export default {
data() {
return {
message: 'Hello Vue!',
showDetail: true,
appName: 'Vue',
items: [
{ name: 'Apple', quantity: 5 },
{ name: 'Banana', quantity: 3 },
{ name: 'Cherry', quantity: 7 }
]
};
},
methods: {
reverseMessage() {
this.message = this.message.split('').reverse().join('');
}
}
};
</script>
在这个示例中,模板包含了以下特性:
动态数据绑定:{{ message }} 插入了message数据属性的值。
条件渲染:
根据showDetail的布尔值决定是否渲染段落。
列表渲染:
- 遍历items数组并为每个数组项创建一个列表项。
事件处理:@click=“reverseMessage” 绑定了按钮的点击事件,当点击时会调用reverseMessage方法。
这些特性使得Vue.js模板非常强大和灵活,能够根据数据的变化动态地更新UI,同时保持代码的简洁和可读性。 -
DOM文档对象模型结构 JavaScript HTML DOM | 菜鸟教程 (runoob.com)
模板编译是指将HTML模板中的指令、表达式和其他动态内容转换为可以高效渲染DOM的JavaScript代码的过程。这个过程主要包括以下几个步骤:
解析(Parsing):
将模板字符串解析成抽象语法树(Abstract Syntax Tree,简称AST)。在这个过程中,编译器会识别出模板中的文本、表达式、指令(如v-if、v-for)等,并将它们转换为树状结构的节点。
优化(Optimization):
对AST进行静态分析,标记哪些节点是静态的,哪些是动态的。静态节点不需要每次渲染时都重新生成,而动态节点则需要根据数据变化重新计算。优化过程还包括移除不必要的计算和减少重复的DOM操作,以提高性能。
代码生成(Code Generation):
将优化后的AST转换为渲染函数的源代码。渲染函数是一个纯JavaScript函数,它接受状态数据作为参数,返回描述DOM结构的虚拟DOM(Virtual DOM)节点。虚拟DOM是一个轻量级的内存对象,表示真实的DOM结构。
编译后的结果:
最终,编译过程会产生一个渲染函数,这个函数在每次数据变化时都会被调用,以生成新的虚拟DOM树。然后,Vue会将新旧虚拟DOM树进行比较(diff算法),找出最小的变更集,最后将这些变更应用到实际的DOM上,以达到更新视图的效果。
在beforeMount生命周期钩子被调用时,模板编译已经完成,这意味着模板已经被转换成了渲染函数,但是这个函数尚未被执行,因此DOM尚未被更新。一旦mounted钩子被调用,就表示首次渲染已完成,组件已经被附加到DOM中,此时用户可以看到组件的输出。mounted(挂载完成)
在实例挂载到页面之后调用。此时真实DOM已经渲染完成,可以进行DOM操作。
beforeUpdate(更新前)
在数据更新之前被调用,该方法可用于在更新之前访问现有的DOM(beforeUpdate生命周期钩子在数据即将更新但DOM还未更新时被调用。这个钩子可以用于在DOM更新前执行一些操作,比如保存当前的滚动位置,或者在数据更改前获取DOM的某些测量值。)
<template> <div ref="scrollContainer"> <ul> <li v-for="item in items" :key="item.id">{{ item.text }}</li> </ul> </div> </template> <script> export default { data() { return { items: [ { id: 1, text: 'Item 1' }, { id: 2, text: 'Item 2' }, { id: 3, text: 'Item 3' }, ], }; }, beforeUpdate() { // 在数据更新前保存滚动位置 this.scrollTop = this.$refs.scrollContainer.scrollTop; }, updated() { // 在数据更新后恢复滚动位置 this.$refs.scrollContainer.scrollTop = this.scrollTop; }, methods: { addNewItem() { this.items.push({ id: Date.now(), text: 'New Item' }); }, }, }; </script>
在这个例子中,我们有一个可滚动的
-
列表,它由items数组的数据驱动。我们在beforeUpdate钩子中保存了scrollContainer元素的当前滚动位置。当数据更新后,在updated钩子中,我们将滚动位置恢复到更新前的位置。
这样,即使列表数据发生了变化,用户的滚动位置也不会丢失,提供了更好的用户体验。这是利用beforeUpdate钩子的一个典型应用场景
updated(更新完成)
在数据更新之后被调用,该方法还会在组件的子组件更新之后被调用。
beforeDestroy(销毁前)
在实例销毁之前调用。此时实例仍然完全可用。
beforeDestroy生命周期钩子是在实例销毁之前被调用的。这是一个重要的时机,可以用来清理实例在运行期间创建的资源,比如事件监听器、定时器、WebSocket连接等,以防止内存泄漏。如下:
<template> <div> <h1>{{ message }}</h1> <button @click="startUpdating">Start Updating</button> <button @click="stopUpdating">Stop Updating</button> </div> </template> <script> export default { data() { return { message: 'Hello Vue!', updateInterval: null, }; }, methods: { startUpdating() { this.updateInterval = setInterval(() => { this.message = new Date().toLocaleTimeString(); }, 1000); }, stopUpdating() { clearInterval(this.updateInterval); this.updateInterval = null; }, }, beforeDestroy() { // 清理定时器 if (this.updateInterval) { clearInterval(this.updateInterval); } // 清理事件监听器 window.removeEventListener('resize', this.onResize); }, mounted() { // 添加事件监听器 window.addEventListener('resize', this.onResize); }, onResize() { console.log('Window resized'); }, }; </script>
在这个例子中,我们有两个按钮,一个用于启动定时器,另一个用于停止定时器。定时器每秒更新message的值,显示当前的时间。此外,我们还在组件挂载时添加了一个窗口大小调整的事件监听器。
在beforeDestroy钩子中,我们检查updateInterval是否存在,如果存在,则清除定时器。同时,我们也从窗口上移除了resize事件的监听器。
通过这种方式,即使组件被销毁,也不会留下任何未清理的资源,确保了良好的资源管理和避免了潜在的内存泄漏问题。destroyed(销毁完成)
在实例销毁之后调用。此时实例所有的指令和事件都已经卸除,所有的子实例都已经被销毁。
destroyed钩子的主要用处包括:
确认资源释放:
在destroyed钩子中,你可以检查或记录资源是否已经被正确释放,这对于调试和确保没有资源泄漏特别有用。
执行最终的清理任务:
虽然大部分清理工作应该在beforeDestroy中完成,但有时你可能需要在实例完全销毁后执行一些额外的清理操作,例如发送一个日志条目到服务器,记录组件的生命周期结束。
异步操作的确认:
如果在beforeDestroy中执行了异步操作(如取消网络请求、关闭WebSocket连接等),destroyed钩子可以用来确认这些异步操作是否已经完成。
状态报告或日志记录:
destroyed钩子可以用来记录组件的销毁状态,这对于监控应用性能或调试问题非常有帮助。vue3
setup() :
开始创建组件,在 beforeCreate 和 created 之前执行,创建的是 data 和 method
setup()函数是在组件初始化的早期阶段执行的,但它并不直接对应于Vue 2中的beforeCreate或created生命周期钩子。setup()的执行时机是在beforeCreate和created之间,但它做的事情与这两个钩子都不完全相同。
在Vue 3中,setup()函数的执行时机如下:
在beforeCreate之后:这意味着在setup()执行之前,Vue实例已经创建,但是还没有初始化数据和方法。setup()是Vue 3中Composition API的入口点,它在组件实例创建后立即调用,但在此之前,data、computed、methods和watch等选项都还没有被定义或初始化。
在created之前:setup()执行完之后,Vue会使用setup()中返回的值(如果有的话)来初始化组件的属性。这意味着在created钩子执行时,你可以在其中访问到setup()中定义的响应式状态和函数。
在setup()中,你可以使用Composition API提供的各种函数,如ref、reactive、computed、watch等,来创建响应式状态和定义行为。这些状态和函数的定义发生在setup()中,而不是像Vue 2那样在data、methods、computed等选项中定义。
因此,setup()可以看作是Vue 3中一个新的生命周期阶段,它位于beforeCreate和created之间,但又独立于这两个钩子,提供了更灵活的方式来组织和管理组件的逻辑。**问题:**我可以这样理解吗,setup中的各种函数由编程人员定义,只有定义了才会加载,而不像vue2 中创建实例后把里面的data、computed、methods和watch全部加载?
答案:是的,你的理解是正确的。在Vue 3中,setup()函数的使用确实带来了组件初始化和资源加载方式上的重要变化。与Vue 2相比,Vue 3的Composition API(主要通过setup()函数体现)提供了更为细粒度的控制和更高效的资源管理。
在Vue 2中,无论你是否在当前作用域中使用data、computed、methods和watch等选项,只要它们被定义在组件中,就会在组件实例化时全部加载。这意味着即使某些数据或方法在整个组件生命周期中从未被使用,它们也会占用一定的内存和处理时间。
而在Vue 3的setup()中,你使用Composition API定义的响应式状态、计算属性、观察者等,只有在你显式地调用相关API(如ref、reactive、computed、watch等)时才会被创建。这意味着:
**1.按需加载:**你仅创建和加载实际需要的资源,这有助于减少内存消耗和提升性能,尤其是在大型应用中。
**2.更细粒度的控制:**你可以根据组件的实际需求和逻辑结构,更灵活地组织和管理状态和行为。
3.更好的可复用性和组合性:通过将逻辑拆分为多个可组合的函数,你可以更容易地在不同的组件中重用相同的逻辑,提高代码的复用率和可维护性。
总之,Vue 3的setup()和Composition API提供了一种更现代、更灵活的组件开发方式,允许开发者更精细地控制组件的初始化过程和资源的加载,从而构建更加高效和可维护的应用。onBeforeMount()
组件挂在到节点上之前执行的函数;(**组件(Component)**是Vue.js中的一个核心概念,它代表了一个可重用的UI部分,可以有自己的模板、样式和逻辑。组件是构建复杂用户界面的基本单位,它们可以嵌套使用,形成组件树,从而构建出层次化的应用程序。组件可以拥有自己的状态(通过props和data)、方法、计算属性和侦听器,以及与其他组件通信的能力。在Vue.js中,组件可以定义为单文件组件(Single File Component,SFC),其中包含模板、脚本和样式三个部分,也可以通过简单的函数或对象定义。组件可以是局部注册的(在某个父组件内注册),也可以是全局注册的(在整个应用中可用)。
**节点(Node)**通常指的是DOM(Document Object Model)树中的一个元素。DOM树是由浏览器解析HTML文档后构建的一颗树形结构,其中每个HTML标签、文本片段、注释等都表示为一个节点。节点可以是元素节点(Element Node)、文本节点(Text Node)、属性节点(Attribute Node)等。
在Vue.js中,当组件被挂载到页面上时,它的模板会被编译并转换为对应的DOM节点,这些节点构成了组件在页面上的可视化表现。组件的挂载过程就是将组件的虚拟DOM(Vue内部维护的DOM树的内存表示)映射到真实DOM树上的过程。)onBeforeMount钩子提供了一个时机,让开发者可以在组件实际挂载到DOM之前执行一些准备性的操作。这些操作可能包括:
数据预加载:如果组件依赖于外部数据,你可以在onBeforeMount中发起数据请求,确保数据在组件可见之前已经加载完成。
**资源预加载:**预加载组件所需的图片、字体或其他资源,以减少页面加载时的延迟。
**初始化操作:**执行一些初始化的计算或设置,如计算初始的布局尺寸、设置默认的动画状态等。
**环境检测:**检查运行环境,如浏览器特性、屏幕尺寸等,以便在组件挂载时做出相应的适应性调整。
例如,如果你的组件需要在挂载前预加载一些数据,你可以这样使用onBeforeMount:import { onBeforeMount, ref } from 'vue'; export default { setup() { const data = ref(null); onBeforeMount(async () => { data.value = await fetchData(); // 假设fetchData是一个异步数据加载函数 }); return { data, }; }, };
在这个例子中,onBeforeMount钩子用于确保数据在组件挂载前已经加载完成,这样当组件首次渲染时,就可以立即展示数据,而不会出现闪烁或延迟。
总之,onBeforeMount是在组件挂载到DOM之前执行的钩子,可以用于执行各种预加载和初始化操作,以确保组件在首次渲染时处于理想状态。onMounted()
组件挂载完成后执行的函数;
onBeforeUpdate()
组件更新之前执行的函数;
onUpdated()
组件更新完成之后执行的函数;
onBeforeUnmount()
组件卸载之前执行的函数;
onBeforeUnmount() 和beforeDestroy()区别
onBeforeUnmount和beforeDestroy都是Vue生命周期钩子,它们都在组件即将被销毁之前被调用,但它们分别属于Vue 3和Vue 2的生命周期体系,并且在执行的上下文方面有一些关键的区别。
Vue2的beforeDestroy
在Vue2中,beforeDestroy是在组件实例被销毁之前调用的钩子。在这个阶段,组件的DOM节点仍然存在,所有的事件监听器和子组件也仍然可用。这是执行清理操作的最佳时机,例如:
清除计时器、解绑自定义事件监听器、取消HTTP请求、执行任何必要的清理工作
由于组件实例仍然可用,你可以在beforeDestroy中访问组件的所有属性和方法。Vue3的onBeforeUnmount
在Vue 3中,onBeforeUnmount扮演着与Vue 2中beforeDestroy类似的角色,但在执行的上下文和细节上有所不同。onBeforeUnmount也是在组件实例被销毁之前调用,但是它是在组合式API的背景下设计的,通常在setup函数中使用。
在Vue 3中,你可能会使用onBeforeUnmount来执行以下操作:
**清理在setup函数中创建的副作用,如watch效果或事件监听器。**执行任何必要的清理工作,类似于Vue 2中的beforeDestroy。“副作用”特指那些在组件初始化或运行过程中,由setup函数内部的操作引发的对外部状态的改变或依赖。这些副作用可以包括但不限于:
**响应式状态监听:**使用watch或watchEffect来监听响应式状态的变化。当状态变化时,这些监听器会执行一些操作,如重新计算衍生状态、更新DOM或其他组件状态。
**事件监听器:**在setup中添加的DOM事件监听器或其他类型的事件监听器,如来自第三方库的事件监听器。
定时器或间隔器:通过setTimeout或setInterval创建的定时任务,这些任务可能在组件生命周期的某个时刻执行。
异步操作:如API调用或WebSocket连接,这些操作可能在组件挂载后持续运行,直到组件被卸载。
**外部状态更改:**setup函数中可能有代码会改变外部状态,如全局变量、共享状态或父组件的状态。在setup函数中创建的这些副作用需要在组件卸载时进行清理,以防止内存泄漏和其他潜在问题。例如,如果你在setup中添加了一个事件监听器,那么在组件卸载时,你需要移除这个监听器,否则即使组件已经不存在,事件处理器仍会保留,导致不必要的资源消耗。
onBeforeUnmount中调用适当的方法来取消监听器、清除定时器、关闭WebSocket连接等,确保组件在卸载时不会留下任何“副作用”。
例如,如果你在setup中使用了watch来监听某个状态,你可以这样清理副作用:import { watch, onBeforeUnmount } from 'vue'; export default { setup() { const myState = reactive({ value: 0 }); const stopWatch = watch(() => myState.value, newValue => { // 执行一些基于状态变化的操作 }); onBeforeUnmount(() => { // 清理监听器 stopWatch(); }); } };
主要区别
上下文:
Vue 2的beforeDestroy是在选项式API中使用的,而Vue 3的onBeforeUnmount则是在组合式API中使用的。
执行时机:
两者都在组件实例被销毁之前调用,但Vue 3的onBeforeUnmount更强调在使用组合式API时的清理工作。
代码组织:
在Vue 2中,beforeDestroy是在组件选项对象中定义的。
在Vue 3中,onBeforeUnmount是在setup函数中调用的,这使得代码更加模块化和可组合。
综上所述,尽管onBeforeUnmount和beforeDestroy在功能上有相似之处,但它们是针对不同版本的Vue框架和不同的编程范式设计的。在升级项目或开始新项目时,选择合适的生命周期钩子对于确保组件的正确清理和资源管理至关重要。onUnmounted()
组件卸载完成后执行的函数;
onActivated()
被包含在 中的组件,会多出两个生命周期钩子函数,被激活时执行;
在Vue中,< keep-alive>是一个包裹动态组件的容器,它可以缓存不活动的组件实例而不是销毁它们。这对于需要频繁切换的视图非常有用,因为它可以避免重复的渲染和初始化过程,从而提高性能。
当一个被包裹的组件从隐藏状态变为可见状态时,即组件被激活时,onActivated生命周期钩子函数会被调用。这个钩子函数提供了在组件重新激活时执行代码的机会,通常用于:
恢复状态:如果组件在被缓存期间丢失了一些状态(如表单输入或滚动位置),onActivated可以用来恢复这些状态。
更新数据:如果组件依赖的数据源在组件非活动期间发生了变化,onActivated可以用来重新获取或更新数据。
**重新计算或刷新:**如果组件中包含的计算属性或渲染逻辑依赖于外部状态,onActivated可以用来触发重新计算或刷新。
例如,假设你有一个用户列表组件,它被包裹,每次用户切换到另一个视图再回来时,你可能想在onActivated中重新获取最新的用户列表,以反映任何可能发生的变更:<template> <div> <h2>User List</h2> <ul> <li v-for="user in users" :key="user.id">{{ user.name }}</li> </ul> </div> </template> <script> import axios from 'axios'; export default { name: 'UserList', data() { return { users: [] }; }, methods: { fetchUsers() { axios.get('/api/users') .then(response => { this.users = response.data; }) .catch(error => { console.error('Error fetching users:', error); }); } }, activated() { // 当组件被激活时,重新获取用户列表 this.fetchUsers(); } }; </script> ---------------------------------------------- <template> <div id="app"> <!-- 使用 <keep-alive> 包裹 UserList 组件 --> <keep-alive> <UserList v-if="showUserList" /> </keep-alive> <!-- 其他组件或内容 --> //<OtherComponent v-else /> </div> </template> <script> import UserList from './components/UserList.vue'; //import OtherComponent from './components/OtherComponent.vue'; export default { name: 'App', components: { UserList, OtherComponent }, data() { return { showUserList: true // 控制 UserList 是否显示的标志 }; } }; </script>
在这个例子中,每当UserList组件从缓存中被激活时,fetchUsers方法会被调用,确保显示的是最新的用户列表。
值得注意的是,与onActivated相对应,Vue还提供了onDeactivated钩子,它在组件被缓存时调用,可以用来执行清理操作或保存组件状态,以备下次激活时使用。这两个钩子一起,提供了对组件在容器中生命周期的完整控制onDeactivated()
比如从 A 组件,切换到 B 组件,A 组件消失时执行;
组件被缓存时调用。具体来说,当一个组件从视图中移除,但并没有被销毁,而是被缓存起来时,onDeactivated钩子会被触发。这通常发生在路由切换或组件切换的场景下,当一个被包裹的组件不再处于活动状态时。
onDeactivated钩子主要用于执行以下几类操作:
**清理副作用:**如果在组件的activated或mounted钩子中设置了某些监听器、定时器或订阅,那么在组件不再活动时,应当在onDeactivated中清理这些副作用,以避免内存泄漏或不必要的资源消耗。
保存状态:如果组件在被缓存时需要保存其当前状态(如表单输入、滚动位置等),以便在重新激活时恢复,onDeactivated是一个合适的地方来执行这样的保存操作。
**暂停活动:**对于那些在组件活跃时持续运行的活动(如动画、游戏循环等),在组件被缓存时应当暂停这些活动,以节省计算资源。假设我们有一个Chat组件,它在用户离开聊天界面时需要断开WebSocket连接,以避免不必要的消息接收和处理。我们可以使用onDeactivated钩子来实现这一需求:
export default { name: 'Chat', data() { return { websocket: null, }; }, mounted() { // 建立WebSocket连接 this.websocket = new WebSocket('ws://your-websocket-url'); }, methods: { closeWebSocket() { if (this.websocket && this.websocket.readyState === WebSocket.OPEN) { this.websocket.close(); } }, }, beforeDestroy() { // 确保在组件销毁前关闭WebSocket连接 this.closeWebSocket(); }, onDeactivated() { // 当组件被缓存时关闭WebSocket连接 this.closeWebSocket(); }, };
在这个例子中,当Chat组件被缓存时,onDeactivated钩子会调用closeWebSocket方法来断开WebSocket连接。这有助于避免组件在非活动状态下继续接收消息,从而节省资源并防止潜在的性能问题。
onErrorCaptured()
当捕获一个来自子孙组件的异常时激活钩子函数。
onErrorCaptured是Vue.js提供的一个全局错误处理钩子,它允许你在**整个应用范围内捕获并处理从子孙组件抛出的未捕获错误。**这个钩子在Vue 2.6.0版本中引入,作为增强应用健壮性和调试体验的一部分。
当一个错误在组件的渲染函数、异步观察者、生命周期钩子或任何子组件中未被捕获时,onErrorCaptured钩子会被触发。这个钩子接收三个参数:
err: 错误对象,包含了错误的具体信息。
instance: 抛出错误的Vue实例。
info: 字符串,提供关于错误来源的额外信息,如错误发生在哪个生命周期钩子或观察者中。使用场景
onErrorCaptured主要在以下场景中使用:
**全局错误处理:**你可以在根Vue实例中设置onErrorCaptured钩子,以便在整个应用范围内捕获并处理错误。这对于生产环境下的错误监控尤其重要,可以帮助你收集错误日志并及时修复问题。
**错误恢复:**在捕获到错误后,你可以决定是否让错误继续向上冒泡,还是在当前层级终止错误传播。这可以通过onErrorCaptured返回true或false来控制。返回true表示错误已被处理,不会继续向上抛出;返回false或未返回任何值,则错误将继续向上抛出,直到被更高层级的错误处理机制捕获。
**调试辅助:**在开发环境中,onErrorCaptured可以提供详细的错误信息,帮助开发者快速定位问题源头。import { defineComponent } from 'vue'; export default defineComponent({ name: 'MyComponent', // ... onErrorCaptured(err, instance, info) { console.error(`An error was captured in ${this.$options.name}: `, err, info); // 返回true表示错误已经被处理,不会继续向上抛出 return true; }, });
通过使用onErrorCaptured,你可以增强应用的健壮性,确保即使在出现未预期的错误时,应用也能优雅地降级或恢复,同时提供有用的错误信息给开发者。
在Vue 3中,setup函数是组合式API的核心,它允许你以函数的形式组织组件的逻辑。使用setup语法糖可以让代码更加简洁,尤其是当你使用
不使用setup语法糖
// MyComponent.vue <template> <div>{{ count }}</div> </template> <script> import { ref } from 'vue'; export default { setup() { const count = ref(0); const increment = () => { count.value++; }; return { count, increment, }; }, }; </script> //在这个例子中,我们定义了一个count响应式状态和一个increment方法,并在setup函数中返回了它们,以便在模板中使用。
使用setup语法糖
<!-- MyComponent.vue --> <template> <div>{{ count }}</div> <button @click="increment">Increment</button> </template> <script setup> import { ref } from 'vue'; const count = ref(0); const increment = () => { count.value++; }; </script>
-
列表,它由items数组的数据驱动。我们在beforeUpdate钩子中保存了scrollContainer元素的当前滚动位置。当数据更新后,在updated钩子中,我们将滚动位置恢复到更新前的位置。