前端关于Vue的面试题(六)

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()来劫持各个属性的settergetter,在数据变动时立马能侦听到从而调用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
   开发成本较低
缺点:网站的后期维护难度较大
   页面之间的跳转用时较长,用户体验较差。
   代码重复度大

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值