马上要秋招了,搜集整理了一些Vue面试题,包括组件、指令、API等相关内容,巩固基础😎秋招冲冲冲!!!本篇包括:
✅计算属性和侦听器的区别
✅事件修饰符
✅单页应用(SPA) VS 多页应用(MPA)
✅如何解决SPA首屏加载速度慢
✅v-if和v-for的优先级
计算属性(computed
)是自动监听依赖值的变化,从而动态返回内容(动态显示新的计算结果)。
监听(watch
)是一个过程,在监听的值变化时,可以触发一个回调,并做一些事情。回调函数有两个参数,一个 val
(修改后的 data
数据),一个 oldVal
(原来的 data 数据)。Vue 实例将会在实例化时调用$watch()
,遍历 watch
对象的每一个属性。
两者用于不同情况下完成计算,显示数据的操作。它们的区别主要来源于用法,只是需要动态值,那就用计算属性;需要知道值的改变后执行业务逻辑,才用 watch
,用反或混用虽然可行,但都是不正确的用法。
下面给出这两个特性的基本用法:
计算属性
<div id="app"> {{total}} </div>
<script>
var vm = new Vue({
el: "#app",
data: {
num: 10,
price: 8.8,
},
computed: {
total: function () {
return this.num * this.price;
},
},
});
</script>
侦听器
<div id="app"> {{total}} </div>
<script>
var vm = new Vue({
el: "#app",
data: {
num: 10,
price: 8.8,
},
watch: {
num: function (val) {
this.total = val * this.price;
},
price: function (val) {
this.total = this.num * val;
},
},
});
</script>
结合代码进行说明:
如果 this.num 或者 this.price 没有发生变化,直接获取缓存的总结88作为计算属性的结果。 如果 this.num 或者 this.price 任何一项发生了变化,那么就会重新计算并得到一个总结结果,并重新将结果进行缓存。
computed
的结果是通过return返回的,而 watch
不需要return。watch
中的参数可以得到侦听属性改变的最新结果,而computed
函数没有这种参数。补充:
computed
是一个对象时,有 get 和 set 两个选项。computed
与 methods
相比:methods
是一个方法,它可以接受参数,而 computed
不能;computed
是可以缓存的,methods
不会;一般在 v-for
里,需要根据当前项动态绑定值时,只能用 methods
而不能用 computed
,因为 computed
不能传参。computed
可以依赖其它 computed
,甚至是其它组件的数据(data)。watch
是一个对象时,常用的配置有:handler
(执行的函数)、deep
(是否深度)、immediate
(是否立即执行)computed
默认深度依赖,watch
默认浅度观测参考链接:
https://www.php.cn/vuejs/464220.html
https://blog.csdn.net/itcast_cs/article/details/102802310
常见的事件修饰符: .stop
、.prevent
、.capture
、.self
、.once
、.passive
举例提问:如何给下面这个自定义组件绑定一个原生的click
事件
<custom-component>内容</custom-component>
注意: @click
是自定义事件 click,并不是原生事件 click。绑定原生的 click 是 @click.native="xxx"
,同时补充说明 .exact
会有加分。
.exact
修饰符允许你控制由精确的系统修饰符组合触发的事件。
<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button @click.ctrl="onClick">A</button>
<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button @click.ctrl.exact="onCtrlClick">A</button>
<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button @click.exact="onClick">A</button>
参考链接:
https://v3.cn.vuejs.org/guide/events.html#%E4%BA%8B%E4%BB%B6%E4%BF%AE%E9%A5%B0%E7%AC%A6
https://v3.cn.vuejs.org/guide/events.html#exact-%E4%BF%AE%E9%A5%B0%E7%AC%A6
SPA(single-page application),翻译过来就是单页应用SPA
,是一种网络应用程序或网站的模型。
它通过动态重写当前页面来与用户交互,这种方法避免了页面之间切换时,打断用户体验。在单页应用中,所有必要的代码(HTML
、JavaScript
和CSS
)都通过单个页面的加载而检索,或者根据需要(通常是为响应用户操作)动态装载适当的资源,并添加到页面。
页面在任何时间点都不会重新加载,也不会将控制转移到其他页面。举个例子来讲,一个杯子,早上装的牛奶,中午装的是开水,晚上装的是茶,我们发现,变的始终是杯子里的内容,而杯子始终是那个杯子。再通俗一点,就是局部刷新。我们熟知的JS框架如react
,vue
,angular
,ember
都属于SPA
MPA(MultiPage-page application),翻译过来就是多页应用。在MPA
中,每个页面都是一个独立的主页面。当我们在访问另一个页面的时候,都需要重新加载html
、css
、js
文件,公共文件则根据需求按需加载。
单页应用和多页应用的区别
| 单页应用(SPA) | 多页应用(MPA) |
---|---|---|
组成 | 一个主页面和多个页面片段 | 多个主页面 |
刷新方式 | 局部刷新 | 整页刷新 |
url模式 | 哈希模式 | 历史模式 |
SEO搜索引擎优化 | 难实现,可使用SSR方式改善 | 容易实现 |
数据传递 | 容易 | 通过url、cookie、localStorage等传递 |
页面切换 | 速度快,用户体验良好 | 切换加载资源,速度慢,用户体验差 |
维护成本 | 相对容易 | 相对复杂 |
优点 | 具有桌面应用的即时性、网站的可移植性和可访问性;内容的改变不需要重新加载整个页面;良好的前后端分离,分工更明确 | 首屏加载较快,SEO优化较好。 |
缺点 | 不利于搜索引擎的抓取;首次渲染速度相对较慢(加载整个项目使用的css、js) | 页面跳转较慢 |
参考链接:
https://vue3js.cn/interview/vue/spa.html
https://blog.csdn.net/rgpbrave/article/details/108533825
首屏时间(First Contentful Paint),指的是浏览器从响应用户输入网址地址,到首屏内容渲染完成的时间,此时整个网页不一定要全部渲染完成,但需要展示当前视窗需要的内容。首屏加载可以说是用户体验中最重要的环节。
在页面渲染的过程,导致加载速度慢的原因是:网络延时问题、资源文件体积过大、重复发送请求以加载资源、加载脚本的时候,渲染内容堵塞了。
常见的几种SPA首屏优化方式
参考链接:
https://vue3js.cn/interview/vue/first_page_time.html
为什么不建议v-if和v-for一起使用?
vue在官方文档中明确指出,永远不要把 v-if
和 v-for
同时用在同一个元素上
在 Vue 2
中,v-for
优先于 v-if
被解析,即先执行循环,后判断条件。
编写一个p
标签,同时使用v-if
与 v-for
<div id="app">
<p v-if="isShow" v-for="item in items">
{{ item.title }}
</p>
</div>
创建vue
实例,存放isShow
与items
数据
const app = new Vue({
el: "#app",
data() {
return {
items: [
{ title: "foo" },
{ title: "baz" }]
}
},
computed: {
isShow() {
return this.items && this.items.length > 0
}
}
})
模板指令的代码都会生成在render
函数中,通过app.$options.render
就能得到渲染函数
ƒ anonymous() {
with (this) { return
_c('div', { attrs: { "id": "app" } },
_l((items), function (item)
{ return (isShow) ? _c('p', [_v("\n" + _s(item.title) + "\n")]) : _e() }), 0) }
}
_l
是vue
的列表渲染函数,函数内部都会进行一次if
判断
初步得到结论:v-for
优先级是比v-if
高
再将v-for
与v-if
置于不同标签
<div id="app">
<template v-if="isShow">
<p v-for="item in items">{{item.title}}</p>
</template>
</div>
再输出下render
函数
ƒ anonymous() {
with(this){return
_c('div',{attrs:{"id":"app"}},
[(isShow)?[_v("\n"),
_l((items),function(item){return _c('p',[_v(_s(item.title))])})]:_e()],2)}
}
这时候我们可以看到,v-for
与v-if
作用在不同标签时候,是先进行判断,再进行列表的渲染
v-if
和 v-for
同时用在同一个元素上,带来性能方面的浪费(每次渲染都会先循环再进行条件判断)template
(页面渲染不生成dom
节点),在这一层进行v-if判断,然后在内部进行v-for循环<template v-if="isShow">
<p v-for="item in items">
</template>
computed
提前过滤掉那些不需要显示的项computed: {
items: function() {
return this.list.filter(function (item) {
return item.isShow
})
}
}
参考链接:
https://github.com/57code/vue-interview/blob/master/public/01-vif-vfor/README.md
https://vue3js.cn/interview/vue/if_for.html