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()
函数来监听数据变化等等。
javascript
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属性的示例:
js
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方法中修改其他响应式数据。
html
<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的代码示例如下:
js
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的代码示例如下:
javascript
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
监听数据的变化即可。例如:
js
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
函数的简单示例:
javascript
<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
指令来循环渲染这些元素。例如:
html
<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
指令应用在任何元素上,例如:
html
<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零技术