1.v-show和v-if指令的共同点和不同点
当条件改变的时候v-if是通过DOM节点的添加和删除来控制节点的显示隐藏的,
v-show是通过css样式控制节点的显示隐藏的。
v-if的切换成本比较高,v-show渲染成本比较高,
所以当切换频繁的时候使用v-show,如果初次渲染数据较多的时候,使用v-if
2.vue组件中data为什么必须是一个函数
vue组件可能存在多个实例,如果使用对象形式定义data,可能会导致它们共用一个data对象,那么状态变更会影响所有组件实例,这是不合理的采用函数的形式定义,在initData时会将作为工厂函数返回全新的data对象,有效避免了多个实例之间状态污染的问题。而在vue根实例创建过程中不存在这个限制,也是因为根实例只能有一个,不需要担心这种情况。
如果data是一个函数的话,这样每复用一次组件,就会返回一份新的data(类似于给每个组件实例创建一个私有的数据空间,让各个组件实例维护各自的数据)
Object是引用数据类型,里面保存的是内存地址,单纯的写成对象形式,就使得所有组件实例共用了一份data,就会造成一个变了全都会变的结果
3.$nextTick的使用
vue的$nextTick其本质是对js执行原理EventLoop的一种应用。
$nextTick的核心是利用promise,mutationObserver、setImmediate、setTimeout的原生
javascript方法来模拟对应的微/宏任务的实现,本质是为了利用JavaScript的这些异步回调任务队列来实现vue框架中自己的异步回调队列。
nextTick是典型的将底层的javascript执行原理应用到具体案例中的示例,引入异步更新队列机制的原因:
- 如果是同步更新,则多次对一个或者多个属性赋值,会频繁触发dom的渲染,可以减少一些无用的渲染。
- 同时由于virtualDom的引入,每一次状态发生变化之后,状态变化的信号会发送给组件,组件内部使用virtualDom进行计算得出需要更新的具体的dom节点,然后对dom进行更新操作,每次更新状态后的渲染过程需要更多的计算,而这种无用功也将浪费更多的性能,所以异步渲染变得更加至关重要。
- vue采用了数据驱动的思想,但是在一些情况下,仍然需要操作dom。有时候,可能遇到这样的情况,dom1的数据发生了变化,而dom2需要从dom1中获取数据,那这时候就会发现dom2的试图并没有更新,这时就需要用到nextTick了。
4.Vue中双向数据绑定是如何实现的
vue2.0
vue2.0的双向数据绑定是通过数据劫持,结合发布订阅的方式来实现的,也就是说数据和视图同步,数据发生变化,视图也会发生变化,视图变化,数据也会随之发生改变。vue2的双向数据绑定核心是object.definedproperty()方法。给vue中的数据绑定get和set方法,当获取数据的时候,调用get方法,当修改数据的时候调用set方法。通过watcher监听器去更新视图,完成数据的双向绑定。
vue3.0
Object.defineProperty 的问题:在Vue中,Object.defineProperty无法监控到数组下标的变化,导致直接通过数组的下标给数组设置值,不能实时响应。目前只针对以上方法做了hack处理,所以数组属性是检测不到的,有局限性Object.defineProperty只能劫持对象的属性,因此我们需要对每个对象的每个属性进行遍历。Vue里,是通过递归以及遍历data对象来实现对数据的监控的,如果属性值也是对象那么需要深度遍历,显然如果能劫持一个完整的对象,不管是对操作性还是性能都会有一个很大的提升。
Proxy的两个优点:可以劫持整个对象,并返回一个新对象,有13种劫持。
5.v-if和v-for的优先级
v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 true值的时候被渲染。
v-for 指令基于一个数组来渲染一个列表。v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组或者对象,而 item 则是被迭代的数组元素的别名。
在 v-for 的时候,建议设置key值,并且保证每个key值是独一无二的,这便于diff算法进行优化。
在vue中,永远不要把v-if和v-for同时用在同一个元素上,会带来性能方面的浪费。
vue 2.x:当 v-if 与 v-for 一起使用时,v-for 具有比 v-if 更高的优先级
vue 3.x:当 v-if 与 v-for 一起使用时,v-if 具有比 v-for 更高的优先级。
6.vue常用的修饰符
事件修饰符:
stop(阻止事件冒泡)
prevent(阻止默认行为)
self(只触发本身)
once(只触发一次)
captrue(事件捕获,与事件冒泡的方向相反,事件捕获由外向内。)
表单修饰符:
lazy(当光标离开标签之后,才会赋值给value)
trim(过滤掉两边的空格)
number(自动将用户输入的值转化为数值类型。)
键盘修饰符:
普通键(enter、tab、delete、space、esc、up…)
系统修饰键(ctrl、alt、meta、shift…)
鼠标修饰符:lefft,right,middle
7.自定义指令详解
除了我们常用的核心的默认内置的指令像是v-model,v-show,v-if等,vue也允许我们自定义指令,有的情况下,对普通dom元素进行底层操作,这个时候就需要自定义指令。
自定义指令时用来操作dom的,尽管vue推崇的是数据驱动视图的理念,但并不是所有的情况都适合数据驱动。自定义指令就是一种有效的补充和扩展,不仅可用于任何dom操作,而且是可复用的。
自定义指令分为两种:一种是自定义的局部指令,一种是全局指令
8.vue slot
slot又名插槽,是vue的内容分发机制,组件内部的模板引擎使用slot元素作为承载分发内容的出口。插槽slot是子组件的一个模板标签元素,而在一个标签元素是否显示,以及怎么显示是父组件决定的。
slot又分为三类,默认插槽,具名插槽,作用域插槽。
- 默认插槽:又称匿名插槽,当slot没有指定name属性值的时候,一个组件内只能有一个匿名插槽。
- 具名插槽:带有具体名字的插槽,也就是带有name属性的slot,一个组件可以出现多个具名插槽。
- 作用域插槽:默认插槽,剧名插槽的一个变体,可以是匿名插槽,也可以是具名插槽,该插槽的不同点在子组件渲染作用域插槽时,可以将子组件内部的数据传递给父组件,让父组件根据子组件传递过来的数据决定如何渲染该插槽。
9.vue初始化页面闪动问题
当网速较慢,vue.js文件还没有加载完时,在页面上会显示{{message}}的字样,知道vue创建实例,编译模板时,dom才会被替换,所以这个过程屏幕是闪动的。
所以解决这个问题,需要在style样式中设置【v-cloak】{display:none}。在一般情况下,v-clock是一个解决初始化慢导致页面闪动的最佳实践,对于简单的项目很实用。
但是在具有工程化的项目里,比如使用了webpack和vue-router的项目中,html结构只是一个空的div元素,剩余的内容都是由路由去挂载不同的组件完成的,所以不需要v-cloak。
10.vue更新数组时触发视图更新的方法
- vue.set相应式新增与修改数据可以设置对象或数组的值,通过key或数组索引,可以触发视图更新。
- vue.delete,删除对象或数组中元素,通过key或者数组索引,可以触发视图更新。
- 数组对象直接修改属性,可以触发视图更新
- 数组整体修改,可以触发视图更新
Vue包含一组观察数组变异的方法,使用它们改变数组也会触发视图更新不变异的方法:
- push() 向数组的末尾添加一个或多个元素,并返回新的长度。
- pop() 删除最后一个元素,把数组长度减 1,并且返回它删除的元素的值。
- shift() 把数组的第一个元素从其中删除,并返回第一个元素的值。
- unshift() 向数组的开头添加一个或更多元素,并返回新的长度。
- splice() 向/从数组中添加/删除项目,然后返回被删除的项目。 该方法会改变原始数组。
- sort() 对数组的元素进行排序。
- reverse() 颠倒数组中元素的顺序。
不变异的方法:
- filter()
- concat()
- slice()
他们返回的是一个新数组,使用这些方法时,可以用新数组来替换原始数组
11.Vue2.0 和 Vue3.0 有什么区别
- 性能:Vue 3 比 Vue 2 更快,因为它采用了新的渲染引擎,这使得它在大型应用程序中更快。
- 语法:Vue 3 使用了更简单的语法,并移除了一些 Vue 2 中的不常用功能,这使得代码更容易维护和阅读。
- 设计:Vue 3 采用了更加模块化的设计,把各个组件的功能分离开,使得应用程序更加灵活和可扩展。
- TypeScript 支持:Vue 3 原生支持 TypeScript,可以更轻松地与其他 TypeScript 项目集成。
- Composition API:Vue 3 引入了 Composition API
- Vue2 在模板中如果使用多个根节点时会报错,
- Vue3 支持多个根节点,也就是 fragment
12.Vue3带来了什么改变
vue3.0对vue的主要3个特点:响应式、模板、对象式的组件声明方式,进行了全面的更改,底层的实现和上层的api都有了明显的变化,基于Proxy重新实现了响应式,基于treeshaking内置了更多功能,提供了类式的组件声明方式。而且源码全部用typescript重写
13.reactive与ref的区别
- 从定义数据角度对比:
ref用来定义:基本类型数据
reactive用来定义对象(或数组)类型数据
备注:ref也可以用来定义对象(或数组)类型数据, 它内部会自动通过reactive转为代理对象。
- 从原理角度对比:
ref通过Object.defineProperty()的get与set来实现响应式(数据劫持)。
reactive通过使用Proxy来实现响应式(数据劫持), 并通过Reflect操作源对象内部的数据。
- 从使用角度对比:
ref定义的数据:操作数据需要.value,读取数据时模板中直接读取不需要.value。
reactive定义的数据:操作数据与读取数据:均不需要.value。
14.计算属性和watch以及methods的区别
- 作用机制上:
watch 和 computed 都是以 Vue 的依赖追踪机制为基础的,当某一个数据发生变化的时候,
所有依赖这个数据的相关数据,自动发生变化,也就是自动调用相关的函数去实现数据的变动
methods 里面是用来定义函数的,它需要手动调用才能执行。而不像 watch 和 computed 那样,
“自动执行”预先定义的函数,相比于 watch / compute;methods 不处理数据逻辑关系,只提供可调用的函数,类似储存函数的一个库。
- 从性质上
methods里面定义的是函数,你显然需要像"fuc()"这样去调用它(假设函数为fuc)。
computed是计算属性,事实上和和data对象里的数据属性是同一类的(使用上)。
watch:类似于监听机制+事件机制,回调函数自动调用。
15.和route和route 和 router 的区别
router是VueRouter的一个对象,通过Vue.use(VueRouter)和VueRouter构造函数得到一个router的实例对象,这个对象中是一个全局的对象,包含了所有的路由包含了许多关键的对象和属性。例如history对象
route是一个跳转的路由对象,每一个路由都会有一个route对象,是一个局部的对象,可以获取对应的name,path,params,query等
【前端面试题——vue3篇】(二)https://developer.aliyun.com/article/1399412?spm=a2c6h.13148508.setting.33.7c824f0eej0yJq