1. 请说说Vue的生命周期,和vue2的有什么区别?
Vue 的生命周期可以分为8个阶段:创建前后、挂载前后、更新前后、销毁前后,以及一些特殊场景的生命周期。Vue 3 中还新增了是3个用于调试和服务端渲染的场景。
Vue 2中的生命周期钩子 | Vue 3选项式API的生命周期选项 | Vue 3 组合API中生命周期钩子 | 描述 |
---|---|---|---|
beforeCreate |
beforeCreate |
setup() |
创建前,此时data 和 methods 的数据都还没有初始化 |
created |
created |
setup() |
创建后,data 中有值,尚未挂载,可以进行一些Ajax 请求 |
beforeMount |
beforeMount |
onBeforeMount |
挂载前,会找到虚拟DOM ,编译成Render
|
mounted |
mounted |
onMounted |
挂载后,DOM 已创建,可用于获取访问数据和DOM 元素 |
beforeUpdate |
beforeUpdate |
onBeforeUpdate |
更新前,可用于获取更新前各种状态 |
updated |
updated |
onUpdated |
更新后,所有状态已是最新 |
beforeDestroy |
beforeUnmount |
onBeforeUnmount |
销毁前,可用于一些定时器或订阅的取消 |
destroyed |
unmounted |
onUnmounted |
销毁后,可用于一些定时器或订阅的取消 |
activated |
activated |
onActivated |
keep-alive 缓存的组件激活时 |
deactivated |
deactivated |
onDeactivated |
keep-alive 缓存的组件停用时 |
errorCaptured |
errorCaptured |
onErrorCaptured |
捕获一个来自子孙组件的错误时调用 |
— | renderTracked |
onRenderTracked |
调试钩子,响应式依赖被收集时调用 |
— | renderTriggered |
onRenderTriggered |
调试钩子,响应式依赖被触发时调用 |
— | serverPrefetch |
onServerPrefetch |
组件实例在服务器上被渲染前调用 |
父子组件的生命周期执行顺序:
-
加载渲染阶段
:父 beforeCreate -> 父 created -> 父 beforeMount -> 子 beforeCreate -> 子 created -> 子 beforeMount -> 子 mounted -> 父 mounted -
更新阶段
:父 beforeUpdate -> 子 beforeUpdate -> 子 updated -> 父 updated -
销毁阶段
:父 beforeDestroy -> 子 beforeDestroy -> 子 destroyed -> 父 destroyed
在Vue.js中,组件的生命周期可以分为加载渲染阶段、更新阶段和销毁阶段。下面是对每个阶段的优化的详细说明:
加载渲染阶段优化:
- 在父组件的
beforeCreate
和created
阶段,可以进行一些初始化工作,例如设置初始数据、引入必要的插件等。 - 在父组件的
beforeMount
阶段,可以在DOM挂载之前进行一些准备工作,例如获取远程数据、计算属性等。 - 在子组件的
beforeCreate
和created
阶段,可以进行一些子组件的初始化操作,例如设置子组件的初始状态、注册事件等。 - 在子组件的
beforeMount
阶段,可以在DOM挂载之前进行一些子组件的准备工作,例如计算子组件的样式、绑定事件等。 - 在子组件的
mounted
阶段,可以进行一些与DOM相关的操作,例如操作DOM元素、启动定时器等。 - 在父组件的
mounted
阶段,可以进行一些与整个组件相关的操作,例如监听事件、发送请求等。
更新阶段优化:
- 在父组件的
beforeUpdate
阶段,可以在更新之前进行一些准备工作,例如保存一些需要保持的数据、做一些计算等。 - 在子组件的
beforeUpdate
阶段,可以在更新之前进行一些子组件的准备工作,例如更新子组件的状态、计算子组件的样式等。 - 在子组件的
updated
阶段,可以进行一些与DOM相关的操作,例如操作DOM元素、更新样式等。 - 在父组件的
updated
阶段,可以进行一些与整个组件相关的操作,例如重新计算属性、发送请求等。
销毁阶段优化:
- 在父组件的
beforeDestroy
阶段,可以进行一些清理工作,例如取消事件监听、销毁定时器等。 - 在子组件的
beforeDestroy
阶段,可以进行一些子组件的清理工作,例如解绑事件、释放资源等。 - 在子组件的
destroyed
阶段,可以进行一些与DOM相关的操作,例如移除DOM元素、清空缓存等。 - 在父组件的
destroyed
阶段,可以进行一些与整个组件相关的操作,例如释放内存、取消请求等。
2. 在Vue3应该如何使用Composition API?
Vue3.x的Composition API可以让开发者更灵活地组合和封装逻辑代码。使用Composition API需要先在component中调用setup()
函数,这个函数会在component创建前被调用。之后,在setup()
函数中,你可以使用新的reactive()
函数来创建响应式数据对象,使用computed()
函数来创建计算属性,使用watch()
函数来监听数据变化等等。
import { reactive, computed, watch } from 'vue';
export default {
setup() {
const state = reactive({
count: 0,
});
const doubleCount = computed(() => state.count * 2);
watch(
() => state.count,
(newCount, oldCount) => {
console.log(`state.count changed from ${oldCount} to ${newCount}`);
}
);
function increment() {
state.count++;
}
return {
state,
doubleCount,
increment,
};
},
};
3. 在Vue3 中 computed 属性是如何工作的?它和一个函数方法有什么不同?
在Vue3中,computed属性仍然是一个函数,但是它的定义方式有所不同,可以使用 computed()
函数进行定义。
和一个普通的函数方法相比,computed属性的主要不同在于它具有缓存功能。当computed属性依赖的响应式数据发生变化时,computed函数会重新执行,但是在下一次访问computed属性时,会直接返回上一次执行的结果,而不是重新计算一遍。
例如,下面是一个计算税收的computed属性的示例:
import { computed, reactive } from 'vue'
const state = reactive({
price: 100,
taxRate: 0.1
})
const totalPrice = computed(() => {
return state.price * (1 + state.taxRate)
})
console.log(totalPrice.value) // 110
state.price = 200
console.log(totalPrice.value) // 220
此外,computed属性也有一些其他的特点:
- computed属性必须返回一个值,而不能有副作用。computed属性只能用于计算数据(即根据已有的响应式数据计算出一个新的值),而不能在computed属性中直接修改其他响应式数据或引起其他副作用。
- computed属性可以被设置为只读或可写,如果需要在computed属性中修改其他响应式数据,可以使用
get
和set
方法。在定义computed属性时,可以通过设置get和set方法来控制computed属性的只读或可写状态,并且可以在set方法中修改其他响应式数据。
<template>
<div>
<p>Product name: {{productName}}</p>
<button @click="updateProductName">Update</button>
</div>
</template>
<script>
import { computed, reactive } from "vue";
export default {
setup() {
const data = reactive({
count: 0,
name: "Product"
});
const productName = computed({
get() {
return data.name + " " + data.count;
},
set(value) {
[data.name, data.count] = value.split(" ");
}
});
function updateProductName() {
productName.value = "New Product 1";
}
return {
productName,
updateProductName
};
}
};
</script>
4. 解释一下 Vue3中的 watch 和 watchEffect 的区别和用法。
Vue3中的 watch
和 watchEffect
都是用于监听数据变化的方法,但是二者的用法和实现方式略有不同。
watch是Vue2中的一个API,在Vue3中也有保留并进行了一些优化,它可以监听指定的数据变化,并执行对应的回调函数。 watch
接收两个参数,第一个参数是需要监听的数据,可以是一个函数,返回需要监听的数据值;第二个参数是回调函数,当监听的数据发生变化时,回调函数被调用。watch的代码示例如下:
const state = Vue.reactive({ count: 0 })
Vue.watch(() => state.count, (newVal, oldVal) => {
console.log(`count变化了:${oldVal} -> ${newVal}`);
})
state.count++ // 在控制台输出:‘count变化了:0 -> 1’
watchEffect
(API新增)是基于 reactive
实现的自动侦测响应式依赖的函数,其内部会自动收集响应式数据的依赖,当依赖发生变化时,自动重新执行回调函数并更新组件。watchEffect
只接收一个参数,就是需要执行的回调函数。watchEffect的代码示例如下:
const state = Vue.reactive({ count: 0 })
Vue.watchEffect(() => {
console.log(`count变化了:${state.count}`);
})
state.count++ // 在控制台输出:‘count变化了:1’
相比于 watch
,watchEffect
有着更强大的自动侦测能力,并且可以省略对监听数据的声明,使用起来更加方便。但是需要注意的是,watchEffect
中的回调函数应该是纯函数,不能直接修改响应式数据的值,否则会造成无限循环更新的危险。同时,watchEffect
也不支持监听特定的响应式数据,只能监听所有响应式数据的变化。
5. 如何使用 Vue3 中的 watchEffect 来实现响应式数据的监听和更新?有什么注意事项?
watchEffect
是 Vue3 中新增的一个响应式 API,用于监听和响应状态的变化。它的用法类似于 computed
,但是它不会返回计算结果,而是直接执行函数并收集依赖,当依赖发生变化时,会重新执行函数。
使用 watchEffect
监听响应式数据的变化非常简单,只需要在一个函数中使用 reactive
或 ref
定义响应式数据,并在函数中使用 watchEffect
监听数据的变化即可。例如:
import { reactive, watchEffect } from 'vue'
const state = reactive({
count: 0
})
watchEffect(() => {
console.log(state.count)
})
上面的代码中,我们定义了一个响应式数据 state
,然后使用 watchEffect
监听 state.count
的变化并输出变化后的值。当 state.count
的值发生变化时,watchEffect
会自动重新执行函数并输出最新的值。
注意事项:
-
watchEffect
只能用在 setup 函数或单独的函数中,不能用在模板中。 -
watchEffect
只能监听响应式数据的变化,不能监听非响应式数据的变化。 -
watchEffect
返回的是一个停止监听的函数,可以在组件卸载时使用。 -
watchEffect
中的依赖收集是自动的,不需要手动添加依赖,但是也要注意不要使用局部变量或闭包中的变量,因为它们不会被自动收集。
6. Vue3 中引入了 setup 方法,它有什么作用?它的执行时机是什么时候?
Vue3 中的 setup 方法是一个新的组件选项,用于代替 Vue2 中的 beforeCreate
和 created
钩子函数以及 data
、methods
等选项。它可以在组件实例创建之前执行,并且在组件实例创建之后,返回一个对象,将这个对象中的响应式数据以及函数暴露给组件模板使用。
以下是 setup
函数的简单示例:
<template>
<div>
<p>{{ count }}</p>
<button @click="increment">Increment</button>
</div>
</template>
<script>
export default {
setup() {
const count = Vue.ref(0)
const increment = () => {
count.value++
}
return {
count,
increment
}
}
}
</script>
在 setup
函数中,首先定义了一个 count
变量和一个 increment
函数,通过 Vue.ref()
创建了一个响应式的 count
,并将其暴露给组件模板中使用。同时,将 increment
函数也暴露给模板,当按钮被点击时,将会触发 increment
函数,修改 count
的值。
此外,setup
函数还可以接收 props
对象和 context
对象作为参数,这两个参数分别包含了组件的属性以及组件实例的上下文信息。
props 参数包含了通过组件标签传入的属性值,可以通过解构赋值的方式使用。
context 参数包含了一些常用的 Vue 实例方法和属性,比如 emit 用于触发父组件事件、attrs 用于获取非 prop 特性、slots 用于获取插槽等。
setup
函数的执行时机在组件实例创建之前,它会在 Vue 内部先进行一次 beforeCreate
钩子函数的调用,而在组件实例创建之后,它会在 created
钩子函数调用之前被执行。
需要注意的是,只有在
setup
函数中返回的对象中包含的属性和方法才能在组件模板中使用。如果在setup
函数之外定义属性和方法,就算在setup
函数内部使用,也不能在模板中直接使用。总的来说,
setup
函数为 Vue 3 中的组件开发带来了更好的灵活性和可维护性,让我们能够更加方便地编写代码,提高开发效率。
7. Vue3 中的 <template v-for>
和 v-for
指令的区别和用法。
在Vue3中,<template v-for>
和 v-for
指令都可以用来遍历数组或对象并生成多个元素。它们的主要区别在于语法和用法。
<template v-for>
是一种特殊的语法,它允许我们在一个 <template>
标签内编写多个元素,然后使用 v-for
指令来循环渲染这些元素。例如:
<template v-for="(item, index) in items">
<li :key="index">{{ item }}</li>
</template>
在上面的例子中,<template>
标签内包含了一个<li>
元素,当v-for循环执行时,会根据items数组的长度生成多个<li>
元素。使用<template v-for>
的好处是可以避免在循环体内添加额外的标签,使得代码更简洁。
v-for
指令的用法与Vue2相同。我们可以将v-for
指令应用在任何元素上,例如:
<ul>
<li v-for="(item, index) in items" :key="index">{{ item }}</li>
</ul>
在上面的例子中,v-for指令被应用在<li>
元素上,当循环执行时,会根据items数组的长度生成多个<li>
元素。v-for
指令的优点是可以应用在任何元素上,使得我们可以更灵活地控制循环生成的元素。
总的来说,<template v-for>
和v-for
指令都可以用来循环生成多个元素,选择使用哪种方式取决于具体的需求和习惯。
小程序刷题
搜索: zerojs零技术