mvc与mvvm的区别:
Model-View- Controlle 模型-视图-控制器(业务逻辑) 单向通信
View 接受用户交互请求==>请求转交给Controller处理==>Controller 操作Model进行数据更新保存==>Model通知View更新==>View 更新变化数据使用户得到反馈
MVC的思想:Controller负责将Model的数据用View显示出来。
MVC的特点:实现关注点分离,即应用程序中的数据模型与业务和展示逻辑解耦。就是将模型和视图之间实现代码分离,松散耦合,使之成为一个更容易开发、维护和测试的客户端应用程序。
MVC的优点:
1、耦合度低,视图层和业务层分离
2、重用度高
3、生命周期成本低
4、可维护性高
5、部署快
MVC的缺点:
1、不适合小型项目的开发
2、视图与控制器间的过于紧密的连接,视图与控制器是相互分离,但却是联系紧密的部件,妨碍了他们的独立重用
3、降低了视图对模型数据的访问,依据模型操作接口的不同,视图可能需要多次调用才能获得足够的显示数据。4、对未变化数据的不必要的频繁访问,也将损害操作性能。
MVC的应用:主要用于中大型项目的分层开发。
mvvm:
Model 层代表数据模型,View 代表UI 组件,ViewModel 是一个同步View 和 Model的对象。
MVVM是Model-View-ViewModel的简写。即模型-视图-视图模型。【模型】指的是后端传递的数据。【视图】指的是所看到的页面。【视图模型】mvvm模式的核心,它是连接view和model的桥梁。它有两个方向:一是将【模型】转化成【视图】,即将后端传递的数据转化成所看到的页面。实现的方式是:数据绑定。二是将【视图】转化成【模型】,即将所看到的页面转化成后端的数据。实现的方式是:DOM 事件监听。这两个方向都实现的,我们称之为数据的双向绑定。总结:在MVVM的框架下视图和模型是不能直接通信的。它们通过ViewModel来通信,ViewModel通常要实现一个observer观察者,当数据发生变化,ViewModel能够监听到数据的这种变化,然后通知到对应的视图做自动更新,而当用户操作视图,ViewModel也能监听到视图的变化,然后通知数据做改动,这实际上就实现了数据的双向绑定。
MVVM的优点:
MVVM模式的主要目的是分离视图(View)和模型(Model),有几大优点:
1、低耦合,视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定到不同的View上,当View变化的时候Model可以不变,当Model变化的时候View也可以不变。
2、可重用性,可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑。
3、独立开发,开发人员可以专注于业务逻辑和数据的开发(ViewModel),设计人员可以专注于页面设计,使用Expression Blend可以很容易设计界面并生成xml代码。
4、可测试,界面向来是比较难于测试的,而现在测试可以针对ViewModel来写
5、双向数据绑定,它实现了View和Model的自动同步,当Model的属性改变时,不需要手动操作Dom元素,来改变View的显示,而是改变属性后该属性对应View层显示会自动改变
MVVM适用场景: 适合数据驱动的场景,数据操作比较多的场景。
JS内置对象:array、boolean、date、math、number、string、regexp、error...
浏览器对象:window、navigator、screen、history、location
dom对象:document、body、event、style、input、table....
手写响应式:
减少页面加载时间:
减少html,js,css的大小。
合并压缩css,js
减少图片大小,雪碧图之类
减少http请求,请求会很耗时。
多使用缓存。
降低页面的回流,能使用重绘使用重绘
多使用懒加载
阻止事件冒泡和默认事件:
阻止冒泡:e.stopPropagation(); e.cancelBubble=true;
阻止默认事件:e.preventDefault(); return false
vue v-for 为什么要用key?
用v-for正在更新已渲染过的元素列表时,它默认用“就地复用”策略。
key的作用是给dom节点添加唯一标识,让vue里的diff算法能快速找到有变化的dom节点,高效的更新虚拟DOM。
为什么不提倡用index下标绑定key呢,因为,用下标绑定key,删除中间的item,那后面的每一项的下标就全部发生变化会更新全部的dom节点,这样会造成性能消耗。此外还会出现一些bug。(选中项被删除 后面的就变为选中等)
BFC 即 Block Formatting Contexts (块级格式化上下文)
形成一个完全独立的空间,让空间中的子元素不会影响到外面的布局。
触发bfc:
html 根元素
float浮动position (absolute、fixed)
overflow 除了 visible 以外的值 (hidden、auto、scroll)
display 为 inline-block、table-cells、flex
解决:
浮动元素的父元素高度塌陷
两栏自适应布局
外边距垂直方向重合
特性:
1、同一个 BFC 下外边距会发生折叠。(避免外边距的重叠,可以将其放在不同的 BFC 容器中)
2、BFC 可以包含浮动的元素(清除浮动,父级overflow:hidden)
3、BFC 可以阻止元素被浮动元素覆盖(盒子里有两个元素 其中一个元素浮动 第二个将不会被覆盖)
CSS 怎么画一个大小为父元素宽度一半的正方形?
不设宽高、水平垂直居中?
1、弹性盒模型 flex或者grid,justify-content:center、align-items:center
2、子绝父相 top:50%、left:50%,transform:translate(-50%,-50%)
3、父级display:flex; 子级 margin:auto;【margin:auto是具有强烈计算意味的关键字,用来计算元素对应方向应该获得的剩余空间大小 (1) 如果一侧定值,一侧auto,则auto为剩余空间大小(2) 如果两侧均是auto,则平分剩余空间】
4、父级 display: table-cell;vertical-align: middle;text-align: center; 子级 display:inline-block
一些定宽高 知晓父子元素的就能用 line-height:xx;text-align:center / 绝对定位,top:calc(50%-子级自身一半),left:calc(50%-子级自身一半)/ margin-left/right等
cookie、local storage和session storage区别?
cookie:
1、有数量和长度的限制。每个domain最多只能有20条cookie,每个cookie长度不能超过4KB,否则会被截掉。
2、安全性问题。如果cookie被人拦截了,那人就可以取得所有的session信息。
3、在设置的过期时间之前一直有效,即使窗口或浏览器关闭。每次发请求,都会携带在http请求头中。所以只适合保存很小的数据保存的是文本。
session storage,local storage存储能达到5M,保存的是字符串
session storage,仅在当前浏览器窗口关闭前有效,不能持久保存
localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据
函数的节流和防抖?
防抖与节流
函数节流: 指定时间间隔内只会执行一次任务;(滚动条例子)
函数防抖: 任务触发的间隔超过指定间隔的时候,任务才会执行。(注册用户例子)
重绘和回流?
当Render Tree中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。
导致回流的操作:
1、页面首次渲染
2、浏览器窗口大小发生改变
3、元素尺寸或位置发生改变
4、元素内容变化(文字数量或图片大小改变而引起的计算值宽度和高度改变)
5、元素字体大小变化
6、添加或者删除可见的DOM元素
7、激活CSS伪类(例如::hover)
8、查询某些属性或调用某些方法
9、offsetWidth,width,clientWidth,scrollTop/scrollHeight的计算, 会使浏览器将渐进回流队列Flush,立即执行回流。
当页面中元素样式的改变并不影响它在文档流中的位置时(例如:color、background-color、visibility等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘。
回流必定会发生重绘,重绘不一定会引发回流。
如何避免重绘和回流?
css:
避免使用table布局,可能很小的一个小改动会造成整个table的重新布局
尽可能在DOM树的最末端改变class。
避免设置多层内联样式。
将动画效果应用到position属性为absolute或fixed的元素上。
动画实现的速度的选择,动画速度越快,回流次数越多,也可以选择使用requestAnimationFrame
避免使用CSS表达式(例如:calc())
使用transform替代top
使用visibility替换display: none,因为前者只会引起重绘,后者会引发回流(改变了布局)
将频繁重绘或者回流的节点设置为图层,图层能够阻止该节点的渲染行为影响别的节点
js:
避免频繁操作样式,最好一次性重写style属性,或者将样式列表定义为class并一次性更改class属性。
避免频繁操作DOM,创建一个documentFragment,在它上面应用所有DOM操作,最后再把它添加到文档中。
也可以先为元素设置display: none,操作结束后再把它显示出来。因为在display属性为none的元素上进行的DOM操作不会引发回流和重绘。
避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。
谈谈H5和CSS3?
H5:
新增和移除了一些元素。移除font、center、strike等标签 ,这些css可以做。新增语义化标签、音视频、canvas、为表单提供了更多的控件类型url,email,date,tel等。新增了Drag&Drop(拖拽)、Geolocation(地理定位)、webstorage、webworkers等。
语义化标签的作用?
1、去掉或者丢失样式的时候能够让页面呈现出清晰的结构
2、用户体验:例如title、alt用于解释名词或解释图片信息、label标签的活用;
3、有利于SEO:和搜索引擎建立良好沟通,有助于爬虫抓取更多的有效信息:爬虫依赖于标签来确定上下文和各个关键字的权重;
4、方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)以意义的方式来渲染网页;
5、便于团队开发和维护,语义化更具可读性,是下一步吧网页的重要动向,遵循W3C标准的团队都遵循这个标准,可以减少差异化。
css3:
选择器上的丰富(属性、兄弟、伪类等选择器)、样式的支持(弹性盒模型)、动画的支持(transform、transition、animation)
em和rem?
em 大小取决于使用元素的font-size,错误的认为是父元素,其实是继承。
上诉例子,浏览器默认16px,.wrap盒子font-size=16px*10=160px,.box盒子font-size=160px*0.5=80px, 则padding就为80px*0.5=40px。(因为该使用元素有自己的font-size)
上诉例子,浏览器默认16px 父元素继承根元素的font-size,.box没有自己的font-size,也继承的是父元素的。所以padding为 16px*0.5=8px。
rem:相对于根元素大小的单位。(html)
px:相对长度单位。像素px是相对于显示器屏幕分辨率而言的。
适配移动端方案?
1、媒介查询
优点:方法简单,只需修改css文件、调整屏幕宽度时不用刷新页面就可以响应页面布局
缺点:代码量大,不方便维护、不能够完全适配所有的屏幕尺寸,需要编写多套css样式
2、百分比布局方案
优点:宽度自适应,在不同的分辨率下都能达到适配
缺点:百分比的值不好计算、需要确定父级的大小,因为要根据父级的大小进行计算、各个属性中如果使用百分比,相对父元素的属性并不是唯一的、高度不好设置,一般需要固定高度
3、rem方案(使用js修改html的font-size或者媒介查询修改)
优点:rem单位是根据根元素font-size决定大小,只要改变font-size的值,以rem为固定单位的元素大小也会发生响应式的改变
缺点:必须通过一段js代码控制font-size的大小、控制font-size的js代码必须放在在页面第一次加载完成之前,并且放在引入的css样式代码之前
4、vw和vh方案
优点:指定vw\vh相对与视口的宽高,由px换算单位成vw单位比较简单、通过postcss-px-to-viewport插件进行单位转换比较方便
缺点:直接进行单位换算时百分比可能出现小数,计算不方便、兼容性- 大多数浏览器都支持、ie11不支持 少数低版本手机系统 ios8、android4.4以下不支持
编码习惯?
可读性强的命名、备注好注释、
git flow?
Git Flow是构建在Git之上的一个组织、管理软件开发活动的模型。Git Flow是一套使用Git进行源代码管理时的一套行为规范和,通过利用Git创建和管理分支的能力,为每个分支设定具有特定的含义名称,并将软件生命周期中的各类活动归并到不同的分支上。实现了软件开发过程不同操作的相互隔离。这种软件开发的活动模型被称为“Git Flow”。
master、develop、feature、release、hotfix
vue $set原理?
vue初始化时已处理成响应式的,即当我们改变对象obj的值或属性的值时,会触发其在页面上的更新,但是当页面加载完成后,新增的属性就不是响应式的,虽然通过打印this.obj可以看出对象obj上确实增加了新的属性,但是由于新增属性不是响应式的,所以新增的属性不会体现在页面上。原理则是将新增属性设置为响应式,并手动触发通知该属性值的更新。
计算属性与watch的区别?
计算属性变量在computed中定义,属性监听在data中定义。
计算属性初始化的时候就可以被监听并且计算,watch是发生改变的时候才会触发。
如果一个数据依赖于其他数据的简易计算处理的,那么使用computed比较合适。如果需要在某个数据变化时做一些事情,使用watch来观察这个数据变化。
eslint?
它可辅助规范代码风格,有效控制代码质量,并且在多人合作的情况下,也可以使代码看起来更加的整洁。所以在开发过程中,还是建议保留eslint的校验的,养成一个好的编码习惯。
关闭:
1、在vue.config.js中配置 lintOnSave: false
2、package.json文件中注释掉eslint的配置
3、修改eslint 文件中的规则配置参数
js设计模式有哪些?
单例模式、发布-订阅模式、中介者模式、代理模式、组合模式、命令模式等。。。
原型 、原型链?
原型链:
当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链。
js的继承?
1.原型链继承
2.借用构造函数(经典继承)
3.组合继承
4.原型继承
5.寄生式继承
6.寄生组合式继承
原型链继承:
将父类的实例作为子类的原型
优点:父类方法可以复用
缺点:父类的所有引用属性会被所有子类共享,更改一个子类的引用属性,其他子类也会受影响、子类型实例不能给父类型构造函数传参
构造函数继承:
在子类构造函数中调用父类构造函数,可以在子类构造函数中使用call()和apply()方法
优点:可以在子类构造函数中向父类传参数、父类的引用属性不会被共享
缺点:子类不能访问父类原型上定义的方法(即不能访问Parent.prototype上定义的方法),因此所有方法属性都写在构造函数中,每次创建实例都会初始化
组合继承:
组合继承综合了原型链继承和构造函数继承,将两者的优点结合了起来,
基本的思路就是使用原型链继承原型上的属性和方法,而通过构造函数继承实例属性,这样既可以把方法定义在原型上以实现重用,又可以让每个实例都有自己的属性
优点:
1、父类的方法可以复用
2、可以在Child构造函数中向Parent构造函数中传参
3、父类构造函数中的引用属性不会被共享
原型继承:
优点:父类方法可用
缺点:父类的引用会被所有子类所共享、子类实例不能向父类传参
ES6class extends 继承:
Vue响应式原理?
Vue为MVVM框架,当数据模型data变化时,页面视图会得到响应更新,其原理对data的getter/setter方法进行拦截(Object.defineProperty或者Proxy),利用发布订阅的设计模式,在getter方法中进行订阅,在setter方法中发布通知,让所有订阅者完成响应。
在响应式系统中,Vue会为数据模型data的每一个属性新建一个订阅中心作为发布者,而监听器watch、计算属性computed、视图渲染template/render三个角色同时作为订阅者,对于监听器watch,会直接订阅观察监听的属性,对于计算属性computed和视图渲染template/render,如果内部执行获取了data的某个属性,就会执行该属性的getter方法,然后自动完成对该属性的订阅,当属性被修改时,就会执行该属性的setter方法,从而完成该属性的发布通知,通知所有订阅者进行更新。
谈谈spa?谈谈它的优缺点?
整个项目中只有一个页面,页面切换而不重新请求数据。实现思路:页面初始化时加载所有的 HTML、JavaScript 和 CSS,页面内容的变化,靠js动态变化html的内容与用户交互。
优点:提高用户体验,拥有和桌面应用一样的响应速度,关注点分离。
缺点:对搜索引擎seo不友好,初次加载耗时多,不能使用浏览器的前进后退按钮,需自己建立堆栈。
vue项目优化?
1、懒加载(路由懒加载、图片懒加载)
2、抽取功能重复组件和函数封装,提高代码复用率
3、采用服务端渲染ssr和预渲染
4、第三方插件按需引入
5、使用webpack对图片进行压缩
跨域?
指的是浏览器不能执行其他网站的脚本,是浏览器的同源策略引起的,是浏览器施加的安全限制。如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。
限制:
(1)Cookie、LocalStorage 和 IndexDB 无法读取。(2) DOM 无法获得。(3) AJAX 请求不能发送
跨域解决方案:
1、通过jsonp跨域
2、跨域资源共享cors
3、搭建代理服务器
4、postMessage