前言
在前端面试中vue板块是必考也是很重要的考察点,为了在拿下面试offer,让我们一起来好好整理一些高频的vue考题。
首先来看下v-if和v-show的区别
v-if 是真正的条件渲染 只有当条件为true时才会渲染到DOM中,当条件切换时会触发事件监听器,会其本身以及子组件进行卸载。 所以v-if是惰性的当条件为假时,什么也不会做,性能会更好。
v-show 相对来说比较简单,其不管初始条件与否都会渲染,它是基于css的display属性来控制可见性的。
示例:
js
<template>
<button @click="show = !show">切换显示</button>
<p v-if="show">这个段落是通过 v-if 控制的</p>
</template>
<script>
export default {
data() {
return {
show: false
};
}
};
</script>
效果:
可以看到当条件为true时其display属性为block
js
<template>
<button @click="show = !show">切换显示</button>
<p v-show="show">这个段落是通过 v-show 控制的</p>
</template>
<script>
export default {
data() {
return {
show: false
};
}
};
</script>
效果:
当条件为假时该元素不会挂载到DOM中。
这就是二者的主要区别,但是在面试中我们为了多谈一些时间可以再谈谈他们的应用场景。
场景:
1.在登入弹窗时使用v-if:当用户浏览一个网站时,如果只是浏览,则不需要登陆,可能需要下载时才会选择登录,所以将登入弹窗用v-if,当用户未触发登录动作时,登录弹窗不会被渲染到DOM中,从而减少不必要的DOM节点,有助于提升页面加载性能。 2.form表单的校验使用v-show:要随着用户的输入动态更新使用
v-show
可能更加高效,因为它避免了由于元素的添加和删除导致的DOM操作开销。3.用户权限显示(user,admin) v-if:比如在后台之中我们的普通用户和管理员所展示的资源不同。
组件通信
父->子组件通信
使用props 和defineprops
在vue2的选项式API的写法中使用props vue3的组合式API则是使用dedinepropsd其实两种写法都是通过父组件:属性="数据"
传递数据子组件通过props/defineprops来接收数据,不过在实际中更推荐使用Composition API代码更简洁、可维护性更高。
子->父组件通信🎯
1.使用emit/defineEmit 其原理主要是子组件使用emit("事件名","数据")
来向父组件传递数据,父组件来监听这个事件@事件名="处理函数"
并处理传过来的参数。
js
<template>
<div>
<h2>我是父组件</h2>
<p>从子组件接收到的数据:{{ receivedMessage }}</p>
<!-- 监听子组件的 send-message 事件 -->
<ChildComponent @send-message="handleMessage" />
</div>
</template>
<script setup>
import { ref } from "vue";
import ChildComponent from "./ChildComponent.vue";
const receivedMessage = ref("");
const handleMessage = (message) => {
receivedMessage.value = message; // 更新数据
};
</script>
----------------------------------------------------------
<template>
<div>
<h3>我是子组件</h3>
<button @click="sendToParent">发送数据到父组件</button>
</div>
</template>
<script setup>
import { defineEmits } from "vue";
const emit = defineEmits(["send-message"]); // 定义可发送的事件
const sendToParent = () => {
emit("send-message", "Hello 父组件,我是子组件!"); // 发送事件到父组件
};
</script>
使用ref与defineExpose
原理:父组件获取子组件实例,defineExpose()
将子组件的变量和方法暴露给父组件。
js
<template>
<div>
<ExposeChild ref="comp"/>//让 Vue 把该子组件的实例存储到 `compf` 这个 `ref` 变量中。父组件可以通过 `comp.value` 访问子组件的方法或数据.
<button @click="handleClick">按钮</button>
</div>
</template>
<script setup>
import ExposeChild from './ExposeChild.vue';
import { ref } from 'vue';
const comp=ref(null)
const handleClick = () => {
console.log(comp.value.childName);
comp.value.someMethod();
}
</script>
<style scoped>
</style>
----------------------------------------------------
<template>
</template>
<script setup>
const childName = 'Child Component'
// 在子组件中暴露属性和方法
defineExpose({
childName,
someMethod: () => {
console.log('Method called')
}
})
</script>
<style scoped>
</style>
父子组件双向数据绑定
v-model 从原理上来看v-model的实现原理就是props和emit结合起来使用,本质上是 modelValue
+ update:modelValue
的语法糖。
js
<script setup>
import { defineProps, defineEmits } from "vue";
const props = defineProps(["modelValue"]); // 接收 `v-model` 传递的值
const emit = defineEmits(["update:modelValue"]); // 定义 `emit` 事件
const updateValue = () => {
emit("update:modelValue", "子组件修改的新数据"); // 触发更新
};
</script>
<template>
<p>子组件内容: {{ modelValue }}</p>
<button @click="updateValue">更新父组件数据</button>
</template>
----------------------------------------------------------
<script setup>
import { ref } from "vue";
import ChildComponent from "./ChildComponent.vue";
const parentData = ref("初始数据"); // 绑定到子组件的 `modelValue`
</script>
<template>
<ChildComponent v-model="parentData" />
这行代码等价于<ChidlComponent :modelValue="parentData" @update:modelValue="(val) => parentData = val"/>
<p>父组件显示的子组件数据: {{ parentData }}</p>
</template>
跨组件通信
provide / inject 祖先组件->子孙组件传递数据,避免props层层传递。
xml
<script setup>
import { provide, ref } from "vue";
import ChildComponent from "./ChildComponent.vue";
const sharedData = ref("我是祖先组件的数据");
provide("message", sharedData);
</script>
----------------------------------------------------------
<script setup>
import { inject } from "vue";
const receivedMessage = inject("message");
</script>
-
provide
: 提供数据,让子孙组件可以访问sharedData对象。 -
inject
: 获取祖先组件中的message 因为实际上provide/inject提供和获取的是同一个对象,所以provide/inject本质上是共享同一个数据:祖先组件provide
一个ref
,子孙组件inject
这个ref
,拿到的就是同一个数据的引用,所以子组件修改ref.value
,祖先组件也会同步更新!
还有就是vuex和pinia这两种状态管理工具
Pinia是vuex的改进版更轻巧和灵活。所以vuex逐渐淘汰了。 Pinia是使用我会专门学一篇来接介绍,可以插个眼过一天来看