面试题答案
一键面试重构步骤
- setup函数替代beforeCreate和created
- 将
beforeCreate
和created
钩子中的逻辑移到setup
函数中。setup
函数在组件创建之前就执行,且this
指向不是组件实例,需要注意变量和方法的定义方式。例如,在Vue 2中:
- 将
export default {
data() {
return {
message: 'Hello'
}
},
beforeCreate() {
console.log('beforeCreate');
},
created() {
console.log('created');
console.log(this.message);
}
}
在Vue 3中可重构为:
import { ref } from 'vue';
export default {
setup() {
const message = ref('Hello');
console.log('equivalent to beforeCreate and created');
console.log(message.value);
return {
message
};
}
}
- 替换其他生命周期钩子
- beforeMount:在Vue 3中使用
onBeforeMount
。在Vue 2中:
- beforeMount:在Vue 3中使用
export default {
beforeMount() {
console.log('beforeMount');
}
}
在Vue 3中:
import { onBeforeMount } from 'vue';
export default {
setup() {
onBeforeMount(() => {
console.log('beforeMount');
});
}
}
- **mounted**:在Vue 3中使用`onMounted`。类似上述替换方式。
- **beforeUpdate**:在Vue 3中使用`onBeforeUpdate`。
- **updated**:在Vue 3中使用`onUpdated`。
- **beforeDestroy**:在Vue 3中重命名为`onBeforeUnmount`。
- **destroyed**:在Vue 3中重命名为`onUnmounted`。
3. 处理数据和方法
- 在Vue 2中,数据和方法定义在组件实例上。在Vue 3的setup
函数中,数据需要使用ref
(基本类型)或reactive
(对象类型)来创建响应式数据。例如:
// Vue 2
export default {
data() {
return {
count: 0
};
},
methods: {
increment() {
this.count++;
}
}
}
// Vue 3
import { ref } from 'vue';
export default {
setup() {
const count = ref(0);
const increment = () => {
count.value++;
};
return {
count,
increment
};
}
}
可能遇到的问题
this
指向变化- 在Vue 2生命周期钩子中,
this
指向组件实例,可以直接访问数据和方法。在Vue 3的setup
函数中,this
为undefined
。需要通过ref
、reactive
等方式创建数据,并将其返回以在模板中使用。
- 在Vue 2生命周期钩子中,
- 父子组件通信变化
- 在Vue 2中通过
props
和$emit
进行父子组件通信。在Vue 3中,setup
函数接收props
和context
,context.emit
用于触发事件。例如,在父组件中传递数据:
- 在Vue 2中通过
<!-- Vue 2 -->
<template>
<ChildComponent :data="parentData" @child-event="handleChildEvent"></ChildComponent>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
export default {
components: { ChildComponent },
data() {
return {
parentData: 'Hello from parent'
};
},
methods: {
handleChildEvent() {
console.log('Child event received');
}
}
}
</script>
<!-- ChildComponent in Vue 2 -->
<template>
<button @click="$emit('child-event')">Emit event</button>
</template>
<script>
export default {
props: ['data'],
created() {
console.log(this.data);
}
}
</script>
在Vue 3中:
<!-- Vue 3 -->
<template>
<ChildComponent :data="parentData" @child-event="handleChildEvent"></ChildComponent>
</template>
<script>
import ChildComponent from './ChildComponent.vue';
import { ref } from 'vue';
export default {
components: { ChildComponent },
setup() {
const parentData = ref('Hello from parent');
const handleChildEvent = () => {
console.log('Child event received');
};
return {
parentData,
handleChildEvent
};
}
}
</script>
<!-- ChildComponent in Vue 3 -->
<template>
<button @click="emit('child-event')">Emit event</button>
</template>
<script>
import { defineComponent } from 'vue';
export default defineComponent({
props: ['data'],
setup(props, { emit }) {
console.log(props.data);
return {
emit
};
}
});
</script>
- 插件和混入的兼容性
- 一些基于Vue 2开发的插件和混入可能无法直接在Vue 3中使用,需要根据Vue 3的规范进行调整。例如,Vue 2的混入可能直接修改组件实例的属性和方法,在Vue 3中需要使用
provide
和inject
等新的机制来实现类似功能。
- 一些基于Vue 2开发的插件和混入可能无法直接在Vue 3中使用,需要根据Vue 3的规范进行调整。例如,Vue 2的混入可能直接修改组件实例的属性和方法,在Vue 3中需要使用