68.vue如何优化首屏加载速度?
问题描述:
在Vue项目中,引入到工程中的所有js、css文件,编译时都会被打包进vendor.js,浏览器在加载该文件之后才能开始显示首屏。若是引入的库众多,那么vendor.js文件体积将会相当的大,影响首屏的体验。
几种常用的优化方法:
1. 路由的按需加载
2. 将打包生成后 index.html页面 里面的JS文件引入方式放在 body 的最后
3. 用cdn缓存代替npm安装包,将引用的外部js、css文件剥离开来,不编译到vendor.js中
4. UI组件库的按需加载
5. 项目部署上线之后,开启服务器的Gzip压缩,使服务器尽可能返回更小的资源
6. 使用更高级的SSR服务端渲染框架,比如nuxt来做首屏加载优化
69.什么是mvvm
MVVM最早由微软提出来,它借鉴了桌面应用程序的MVC思想,在前端页面中,把Model用纯JavaScript对象表示,View负责显示,两者做到了最大限度的分离,把Model和View关联起来的就是ViewModel。
ViewModel负责把Model的数据同步到View显示出来,还负责把View的修改同步回Model
View 和 Model 之间的同步工作完全是自动的,无需人为干涉(由viewModel完成)
因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理
70.MVVM模式的优点以及与MVC模式的区别
MVVM模式的优点:
1、低耦合:MVVM模式中,数据是独立于UI的,ViewModel只负责处理和提供数据,UI想怎么处理数据都由UI自己决定,ViewModel不涉及任何和UI相关的事,即使控件改变(input换成p),ViewModel几乎不需要更改任何代码,专注自己的数据处理就可以了
2.自动同步数据:ViewModel通过双向数据绑定把View层和Model层连接了起来,View和Model这两者可以自动同步。程序员不需要手动操作DOM, 不需要关注数据状态的同步问题,MVVM 统一管理了复杂的数据状态维护
3、可重用性:你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
4、独立开发:开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计。
5、可测试:ViewModel里面是数据和业务逻辑,View中关注的是UI,这样的做测试是很方便的,完全没有彼此的依赖,不管是UI的单元测试还是业务逻辑的单元测试,都是低耦合的
MVVM 和 MVC 的区别:
mvc 和 mvvm 其实区别并不大。都是一种设计思想,主要区别如下:
1.mvc 中 Controller演变成 mvvm 中的 viewModel
2.mvvm 通过数据来驱动视图层的显示而不是节点操作。
3.mvc中Mmodel和View是可以直接打交道的,造成Model层和View层之间的耦合度高。而mvvm中Model和View不直接交互,而是通过中间桥梁ViewModel来同步
4.mvvm主要解决了:mvc中大量的DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。
71.常见的实现数据劫持的做法有哪些
实现数据劫持的做法有大致如下几种:
1.代理对象(proxy)
2.Object.defineProperty()
1、代理对象
通过代理对象来访问目标对象,可以实现数据的劫持。
在代理的设计模式中,有目标对象、代理对象和事件处理程序,通过代理对象来访问目标对象,可以实现对目标对象的访问权限控制以及数据的劫持工作
//创建一个事件处理器
const handler = {
get: function(obj, prop){
console.log('A value has been accessed');
return obj[prop];
},
set: function(obj, prop, value){
obj[prop] = value;
console.log(`${prop}is being set to${value}`);
}
}
//目标对象
const initialObj = {
id: 1,
name: 'Foo Bar'
}
//代理对象
const proxiedObj = new Proxy(initialObj, handler);
//给代理对象赋值,会调用handler这个事件处理程序,然后调用事件处理程序中的set方法间接访问目标对象,给目标对象赋值
proxiedObj.age = 24
2、Object.defineProperty()
:
vue.js 则是采用Object.defineProperty()
来实现数据的劫持的,通过Object.defineProperty()
来劫持各个属性的setter
,getter
,在数据变动时立马能侦听到从而调用setter和getter做对应的处理。
72.Object.defineProperty()方法的作用是什么?
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
//语法:
Object.defineProperty(obj, prop, descriptor)
//参数说明:
obj:必需。目标对象
prop:必需。需定义或修改的属性的名字
descriptor:必需。目标属性所拥有的特性
//返回值:
传入函数的对象。即第一个参数obj
73.Vue项目中常用到的加载器:
- vue-loader -- 用于加载与编译 *.vue 文件,提取出其中的逻辑代码 script、样式代码 style、
以及 HTML 模版 template,再分别把它们交给对应的 Loader 去处理。
- vue-style-loader -- 用于加载 *.vue 文件中的样式
- style-loader -- 用于将样式直接插入到页面的<style>内
- css-loader -- 用于加载 *.css 样式表文件;
- less-loader -- 用于编译与加载 *.less 文件(需要依赖less库)
- babel-loader -- 用于将 ES6 编译成为浏览器兼容的ES5
- file-loader -- 用于直接加载文件
- url-loader -- 用于加载 URL 指定的文件,多用于字体与图片的加载
- json-loader -- 用于加载 *.json 文件作为 JS 实例。
74.跨域问题的解决方案
在前端开发中,当我们使用ajax向服务器发送请求的时候,当协议、域名、和端口号有任何一个
不一致的时候就会产生跨域问题。
1. jsonp ,允许 script 加载第三方资源
2. 在服务器使用cors实现跨域资源共享
跨域问题有很多中解决方案:我所用过的有:
1.jsonp 他的本质是使用script标签去发送请求,然后服务器返回一段js脚本以供客户端执行
2.cors 他需要在服务器端配置跨域访问的响应头
3.在前端的工程化项目(webpack)中,我们可以通过配置devserver的proxy来解决跨域访问的问题。他的原理是在本地开启一个服务器向数据服务器发送请求,因为服务器和服务器之间是没有跨域
4.但是因为webpack的devserver只在开发环境下有效,当项目发布上线之后仍然会有跨域问题,为了解决项目上线的跨域问题,我们配置服务器的反向代理(ngix)
5.除此之外,我还知道当项目打包成apk之后就不存在跨域问题了,所以如果项目要打包成apk,我们需要在项目中的所有请求中写全路径(此时我们可以配置axios.default.baseURL来解决)
75.Vue的双向数据绑定的原理
//1.由页面->数据的变化:通过给页面元素添加对应的事件监听来实现的
//2.由数据->页面的变化:通过数据劫持(Object.defineProperty) + 发布订阅模式来实现的
具体流程:
A.Compile解析器会将页面上的插值表达式/指定翻译成对应Watcher以添加到订阅器维护的列表中
B.通过Object.defineProperty劫持数据的变化,一旦数据源发生变化会触发对应的set方法
C.在set方法中,通知订阅器(Dep)对象中维护的所有订阅者(Watcher)列表更新
D.每一个Watch会去更新对应的页面
//3.关于发布订阅模式
发布订阅模式又叫观察者模式,他定义了一种一对多的关系,让多个观察者对象同时监听某一个主体对象的变化,当这个主题对象的状态发生变化的时候就会通知所有的观察者对象,是的他们能够自动更新自己。
76.函数的节流阀和去抖
//1.函数去抖(debounce):函数调用n秒后才会执行,如果函数在n秒内被调用的话则函数不执行,重新计算执行时间
function debounce(method,delay){
var timer=null;
return function(){
var context=this
var args=arguments;
clearTimeout(timer);
timer=setTimeout(function(){
method.apply(context,args);
},delay);
}
}
函数去抖的应用场景:
1.监控键盘keypress事件,每当内容变化的时候就向服务器发送请求
2.在页面滚动的时候监控页面的滚动事件,会频繁执行scroll事件
3.监控页面的resize事件,拉动窗口改变大小的时候,resize事件被频繁的执行
上面三种场景中都会频繁触发指定事件,比如第一种情况,每当输入框内容变化之后就向服务器发送请求,
可能会导致一秒钟向服务器请求很多次,这显然是不合理的,我们可以使用函数去抖来优化。
//2.函数节流(throttle):函数预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期
function throttle(method,duration){
var begin = new Date();
return function(){
var context = this
var args=arguments
var current=new Date();
if(current-begin>=duration){
method.apply(context,args);
begin = current;
}
}
}
function resizehandler(){
console.log(++n);
}
window.onresize=throttle(resizehandler,500);
函数节流的应用场景:
1.上拉下拉刷新,每拉动一次彻底完毕之后才可以下一次拉动
2.图片轮播动画,每一张图片动画完成之后才开始下一个图片的动画
77.vue中引入组件、注册组件、使用组件的步骤
1.引入组件
import App from '@/components/App.vue'
2.注册组件
注册全局组件 : Vue.component("组价名字",{template:"<div>页面模板</div>"})
注册私有组件 : 在当前组件/vue对象 使用components属性来声明私有组件
3.使用组件
当我们通过 import App from '@/components/App.vue' 这种方式引入组件之后,我们就可以在页面中使用组建了。
<App></App>
使用组件的时候,我们还可以通过属性给子组件传递数据,比如<App msg="123"></App>
在子组件中可以通过props来接收数据。
同样子组件也可以给父组件传递数据,....
78.单页和多页应用的优缺点
1.什么是单页面?
单页面应用(SPA),通俗一点说就是指只有一个主页面的应用,浏览器一开始要加载所有必须的html,js,css.
优点:用户体验好
前后端分离
页面效果会比较炫酷(比如切换页面内容时的专场动画)
缺点:不利于seo
导航不可用,如果一定要导航需要自行实现前进,后退。
初次加载时耗时多
页面负责度提高很多
2.什么是多页面?
多页面(MPA),就是只一个应用中有多个页面,页面跳转时是整页刷新
优点:有利于seo
开发成本较低
缺点:网站的后期维护难度较大
页面之间的跳转用时较长,用户体验较差。
代码重复度大