马上要秋招了,搜集整理了一些Vue面试题,包括组件、指令、API等相关内容,巩固基础😎秋招冲冲冲!!!本篇包括:
✅ webpack和vite的对比
✅ v-if和v-show的区别
✅ 绑定class的数组用法
✅ 组件中data为什么是函数
✅ 生命周期
vite凭什么比webpack快
webpack启动需要打包
webpack dev serve
在启动时,会把所有的包都build
一遍,从入口文件起索引整个项目的文件,编译成一个或多个js文件,不管模块是否被执行,都会被打包到bundler里。随着项目的复杂程度上升,模块增加,打包后的bundler也会越来越大,打包速度会越来越慢。即项目越复杂,启动时间越来越长。
Vite在启动时不需要打包,不需要拆分模块的依赖,不需要编译,启动速度非常快。
由于现代浏览器本身就支持ES Module,会自动向依赖的Module发出请求。vite充分利用这一点,将开发环境下的模块文件,就作为浏览器要执行的文件,而不是像webpack那样进行打包合并。
vite 请求哪个模块再对该模块进行实时编译 webpack全部编译
当浏览器请求某个模块时,再根据需要对模块内容进行编译。这种按需动态编译的方式,极大的缩减了编译时间,项目越复杂、模块越多,vite的优势越明显。 在HMR方面,当改动了一个模块后,仅需让浏览器重新请求该模块即可,不像webpack那样需要把该模块的相关依赖模块全部编译一次,效率更高。 当需要打包到生产环境时,vite使用传统的rollup进行打包,因此,vite的主要优势在开发阶段。另外,由于vite利用的是ES Module,因此在代码中不可以使用CommonJS
在底层实现上,vite是基于esbuild预构建的,esbuild使用go语言编写,比js编写的打包器预构建快10-100倍,js的操作一般是毫秒级,但go达到了纳秒级
参考链接:
https://segmentfault.com/a/1190000016984434
https://juejin.cn/post/6893699833425559559
https://blog.csdn.net/weixin_40906515/article/details/114313102
首先,v-show
只是 CSS 级别的 display: none;
和 display: block;
之间的切换,而 v-if
决定是否会选择代码块的内容(或组件)。
当需要非常频繁地切换时,使用 v-show
;一次性渲染完(运行时条件很少改变),使用 v-if
。
使用 v-if
在性能优化上有什么经验?
因为当 v-if="false"
时,内部组件是不会渲染的,所以在特定条件才渲染部分组件(或内容)时,可以先将条件设置为 false
,需要时(或异步,比如 $nextTick)再设置为 true
,这样可以优先渲染重要的其它内容,合理利用,可以进行性能优化。
v-if
是“真正”的条件渲染,因为它会确保在切换过程中,条件块内的事件监听器和子组件适当地被销毁和重建。v-if
也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。 相比之下,v-show
就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。 一般来说,v-if
有更高的切换开销,而v-show
有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用v-show
较好;如果在运行时条件很少改变,则使用v-if
较好。 当v-if
与v-for
一起使用时,v-if
具有比v-for
更高的优先级。不推荐v-if和v-for一起使用
参考链接:
https://v3.cn.vuejs.org/guide/conditional.html#v-show
首先是基本的对象用法,传给 :class
(v-bind:class
的简写) 一个对象,以动态地切换 class:
<template>
<div :class="{show: isShow}">内容</div>
</template>
<script>
export default {
data () {
return {
isShow: true
}
}
}
</script>
我们也可以在这里绑定一个返回对象的计算属性。这是一个常用且强大的模式:
<template>
<div :class="classObject"></div>
</template>
<script>
data() {
return {
isActive: true,
error: null,
activeClass: 'active',
errorClass: 'text-danger'
}
},
computed: {
classObject() {
return {
active: this.isActive && !this.error,
'text-danger': this.error && this.error.type === 'fatal'
}
}
}
</script>
绑定 class 的对象用法能满足大部分业务需求,不过,在复杂的场景下,会用到数组,数组中可以有对象、三元表达式
<div :class="[activeClass, errorClass]"></div>
// 数组中有对象
<div :class="[{ active: isActive }, errorClass]"></div>
// 数组中可以有三元表达式
<div :class="[isActive ? activeClass : '', errorClass]"></div>
下面给出一个更为复杂的例子,iView的Button组件,数组里,可以是固定的值,还有动态值(对象)的混合。
<template>
<div :class="classes"></div>
</template>
<script>
export default {
computed: {
classes () {
return [
`${prefixCls}`,
`${prefixCls}-${this.type}`,
{
[`${prefixCls}-long`]: this.long,
[`${prefixCls}-${this.shape}`]: !!this.shape,
[`${prefixCls}-${this.size}`]: this.size !== 'default',
[`${prefixCls}-loading`]: this.loading != null && this.loading,
[`${prefixCls}-icon-only`]: !this.showSlot && (!!this.icon || !!this.customIcon || this.loading),
[`${prefixCls}-ghost`]: this.ghost
}
];
}
}
}
</script>
参考链接:
https://v3.cn.vuejs.org/guide/class-and-style.html#%E5%AF%B9%E8%B1%A1%E8%AF%AD%E6%B3%95
组件是用来复用的。 在Vue中,组件就相当于积木,我们需要用这些积木来搭建我们所预期的结构。在搭建过程中,会重复使用某一类别的积木以完成功能。
我们希望在使用组件时,data
数据是相互隔离,互不影响的。 组件每复用一次,data
数据就应该被复制一次,之后,当某一处复用的地方组件内data
数据被改变时,其他复用地方组件的data
数据不受影响,就需要通过data函数返回一个对象作为组件的状态。
如果我们把组件的data写成对象形式,这些实例用的是同一个构造函数,由于JavaScript的特性,js里对象是引用关系,作用域没有隔离 ,所有的组件实例共用了一个data,就会造成一个变了全都会变(牵一发而动全身)的结果。不能因为将一块圆锥体积木放置在屋顶位置,就将其他用到圆锥体的地方都重置在屋顶。
当我们将组件中的data
写成一个函数,数据以函数返回值形式定义 ,这样每复用一次组件,就会返回一份新的data
,拥有自己的作用域,类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据 。
vue每次会通过组件创建出一个构造函数,每个实例都是通过这个构造函数new出来的。
如果data是一个对象,将这个对象放到这个放到原型上去
function VueComponent(){}
VueComponent.prototype.$options = {
data:{name:'three'}
}
let vc1 = new VueComponent();
vc1.$options.data.name = 'six'; // 将vc1实例上的data修改为six
let vc2 = new VueComponent(); // 在new一个新的实例vc2
console.log(vc2.$options.data.name); six
// 输出vc2的data的值是six,这时候发现vc2中的data也被修改了,他们data相互影响
将data改为一个函数
// 这样就可以保证每个组件调用data返回一个全新的对象,和外部没有关系
function VueComponent(){}
VueComponent.prototype.$options = {
data: () => ({name:'three'})
}
let vc1 = new VueComponent();
let objData = vc1.$options.data()
objData.name = 'six'; // 调用data方法会返回一个对象,用这个对象作为它的属性
console.log(objData)
let vc2 = new VueComponent();
console.log(vc2.$options.data());
参考链接:
https://blog.csdn.net/qq_42072086/article/details/108060494
Vue3 生命周期 主要有 8 个阶段:
所有生命周期钩子的
this
上下文将自动绑定至实例中,因此你可以访问 data、computed 和 methods。这意味着你不应该使用箭头函数来定义一个生命周期方法 (例如created: () => this.fetchTodos()
)。因为箭头函数绑定了父级上下文,所以this
不会指向预期的组件实例,并且this.fetchTodos
将会是 undefined。
我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=30t04w2kn86ck