盒模型
盒模型的组成大家肯定都懂,由里向外content,padding,border,margin.
盒模型是有两种标准的,一个是标准模型,一个是IE模型。
- 在标准模型中,盒模型的宽高 = 内容(content)的宽高
- IE模型中盒模型的宽高 = 内容(content)+填充(padding)+边框(border)的总宽高
- css如何设置两种模型:
/* 标准模型 */ box-sizing:content-box; /*IE模型*/ box-sizing:border-box;
- js获取宽高
dom.offsetWidth/offsetHeight //最常用的,也是兼容最好的
- 边距重叠
scrollHeight、clientHeight、offsetHeight、innerHeight、scrollTop、offsetTop区别
- scrollHeight:有滚动条时讨论它才有意义。没有滚动条时,scrollHeight==clientHeight恒成立。返回当前整个元素的高度(包括带滚动条的隐蔽的地方)
- clientHeight: 返回当前元素在页面上的可视高度(包括padding;不包括border、margin、滚动条高度)
- offsetHeight:返回当前元素在页面上的可视高度(包括padding、border、滚动条高度;不包括margin)
- innerHeight: 获取窗口的高度,不包含工具条、滚动条(浏览器窗口可视区高度(不包括浏览器控制台、菜单栏、工具栏)
- scrollTop:有滚动条时,滚动条向下滚动的距离。即:元素顶部被遮住部分的高度。没有滚动条时,值为0。
- offsetTop :当前元素顶部距离最近父元素顶部的距离。和有没有滚动条没有关系。
div的高度是由什么决定
是由它文档流中元素的高度的总和决定。什么是文档流(Normal Flow):指的是元素排版布局过程中,内联元素会默认自动从左往右,块级元素从上往下的流式排列方式。并最终窗体自上而下分成一行行,并在每行中从左至右的顺序排放元素。
脱离文档流(常见)
float:left;
position: absolute;
position:fixed;
边距重叠解决方案BFC(块级格式化上下文)
//原理
- bfc是一个页面上的独立的容器,外面的元素不会影响bfc里的元素,反过来,里面的也不会影响外面的
- 内部的box会在垂直方向,一个接一个的放置
- 每个元素的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)
- box垂直方向的距离由margin决定,属于同一个bfc的两个相邻box的margin会发生重叠
- bfc的区域不会与浮动区域的box重叠
- 计算bfc高度的时候,浮动元素也会参与计算
- 父元素加
border
属性 - 父元素加
padding
属性
- 创建BFC
- float属性不为none(脱离文档流)
- position为absolute或fixed
- display为inline-block,table-cell,table-caption,flex,inine-flex
- overflow: hidden或auto
- 根元素
- 应用场景
- 自适应两栏布局
- 清除内部浮动
- 防止垂直margin重叠
清除浮动
.clearfloat:after{display:block;clear:both;content:"";visibility:hidden;height:0} .clearfloat{zoom:1}//zoom(IE转有属性)可解决ie6,ie7浮动问题
.clearfloat{clear:both}//添加一个空div,利用css提高的clear:both清除浮动,让父级div能自动获取到高度
父级div手动定义height,就解决了父级div无法自动获取到高度的问题
必须定义width或zoom:1,同时不能定义height,使用overflow:hidden时,浏览器会自动检查浮动区域的高度
必须定义width或zoom:1,同时不能定义height,使用overflow:auto时,浏览器会自动检查浮动区域的高度
所有代码一起浮动,就变成了一个整体,会产生新的浮动问题。
Position
https://segmentfault.com/a/1190000013683068
- relative: 相对定位,相对于自己的初始位置,不脱离文档流。也就是说元素框偏移某个距离,元素仍保持其未定位前的形状,它原本所占的空间仍保留。
- sticky: 结合relative和fixed。常用于吸顶、吸底。当元素距离页面视口(Viewport,也就是fixed定位的参照)顶部距离大于 0px 时,元素以 relative 定位表现,而**当元素距离页面视口小于 0px 时,元素表现为 fixed 定位,也就会固定在顶部。**须指定
top、right、bottom、left
四个阈值其中之一,才可使粘性定位生效。否则其行为与相对定位相同,且top
和bottom
同时设置时,top
生效的优先级高,left
和right
同时设置时,left
的优先级高。 - 设定为
position:sticky
元素的任意父节点的overflow
属性必须是visible
,否则position:sticky
不会生效。 - absolute: 绝对定位的元素的位置相对于最近的已定位祖先元素,如果元素没有已定位的祖先元素,那么它的位置相对于最初的包含块。
inline-block中间会有空隙
内联块元素具有了内联元素以及块级元素的特性:(1)元素之间可以水平排列 (2)可以当做一个块级元素来设置各种的属性,例如:width、height、padding、margin等 (3)不会自动换行
间隙是由换行或者回车导致的。只要把标签写成一行或者标签直接没有空格,就不会出现间隙。但是这种方式是不太可靠。在父容器上使用font-size:0;可以消除间隙(把空格隐藏/去除),对于Chrome, 其默认有最小字体大小限制,考虑到兼容性,需要取消字体大小限制。
.demo {font-size: 0;-webkit-text-size-adjust:none;}
层叠样式优先级
浏览器默认的样式 < 网页制作者样式 < 用户自己设置的样式<!important
按照权重取最大(取权重最大值显示)去确定最后样式:
!importrant >内联>ID派生选择器(#id h1)> id(100)> class(10)>标签(1)>继承(0.5)
怎样覆盖 !important
很简单,只需再添加一条 带 !important
的CSS规则,再给这个给选择器更高的优先级(添加一个标签,ID或类);或是添加一样选择器,把它的位置放在原有声明的后面,总之,最后定义一条规则比胜)。
或者使用相同的选择器,但是置于已有的样式之后;
或干脆改写原来的规则,以避免使用 !important
。
HTTP:地址栏输入url到显示页面的步骤
基本流程:
a. 域名解析
b. 发起TCP的3次握手(TCP连接理论上不会自动断开)
c. 建立TCP连接后发起http请求
d. 服务器端响应http请求,浏览器得到html代码
e. 浏览器解析html代码,并请求html代码中的资源
f. 浏览器对页面进行渲染呈现给用户
- 在浏览器地址栏输入URL
- 浏览器查看缓存,如果请求资源在缓存中并且新鲜,跳转到转码步骤
- 如果资源未缓存,发起新请求
- 如果已缓存,检验是否足够新鲜,足够新鲜直接提供给客户端,否则与服务器进行验证。
- 检验新鲜通常有两个HTTP头进行控制Expires和Cache-Control:
- HTTP1.0提供Expires,值为一个绝对时间表示缓存新鲜日期
- HTTP1.1增加了Cache-Control: max-age=,值为以秒为单位的最大新鲜时间
- 浏览器解析URL获取协议,主机,端口,path
- 浏览器组装一个HTTP(GET)请求报文
- 浏览器获取主机ip地址,过程如下:
- 浏览器缓存
- 本机缓存
- hosts文件
- 路由器缓存
- ISP DNS缓存
- DNS递归查询(可能存在负载均衡导致每次IP不一样)
- 端口建立TCP链接,三次握手
- TCP链接建立后发送HTTP请求
- 服务器接受请求并解析,将请求转发到服务程序,如虚拟主机使用HTTP Host头部判断请求的服务程序
- 服务器检查HTTP请求头是否包含缓存验证信息如果验证缓存新鲜,返回304等对应状态码
- 处理程序读取完整请求并准备HTTP响应,可能需要查询数据库等操作
- 服务器将响应报文通过TCP连接发送回浏览器
- 浏览器接收HTTP响应,然后根据情况选择**关闭TCP连接或者保留重用,关闭TCP连接的四次握手
- 浏览器检查响应状态吗:是否为1XX,3XX, 4XX, 5XX,这些情况处理与2XX不同
- 如果资源可缓存,进行缓存
- 对响应进行解码(例如gzip压缩)
- 根据资源类型决定如何处理(假设资源为HTML文档)
- 解析HTML文档,构件DOM树,下载资源,构造CSSOM树,执行js脚本,这些操作没有严格的先后顺序,以下分别解释
- 构建DOM树:
- 解析过程中遇到图片、样式表、js文件,启动下载
- 构建CSSOM树:
- 根据DOM树和CSSOM树构建渲染树
- js解析
- 显示页面
数据类型
- 基本类型:数字(number)、字符串(string)、布尔值(boolean)、null、undefined、Symbol
- 引用(对象)类型:值保存在内存中的对象,js不允许直接访问内存的位置,实际上是操作对象的引用。function、array、object 对象是可变的,即值是可以修改的;对象的比较并非值得比较
- undefined表示系统级的、出乎意料的或类似错误的值的空缺;表示缺少值,此处应该有值,但没有定义
- null表示程序级的、正常的或在意料之中的值的空缺; 一般多使用null。null表示没有对象,即该处不应该有值1) 作为函数的参数,表示该函数的参数不是对象2) 作为对象原型链的终点undefined表示缺少值,即此处应该有值,但没有定义1)定义了形参,没有传实参,显示undefined2)对象属性名不存在时,显示undefined3)函数没有写返回值,即没有写return,拿到的是undefined4)写了return,但没有赋值,拿到的是undefined
- null和undefined转换成number数据类型
- null 默认转成 0
undefined 默认转成 NaN
typeof null // object (因为一些以前的原因而不是'null') typeof undefined // undefined null === undefined // false null == undefined // true null === null // true null == null // true !null //true isNaN(1 + null) // false isNaN(1 + undefined) // true
- Symbol:它的功能类似于一种标识唯一性的ID。通常情况下,我们可以通过调用
Symbol()
函数来创建一个Symbol实例:
let s1 = Symbol()
- 每个Symbol实例都是唯一的。因此,当你比较两个Symbol实例的时候,将总会返回
false
.应用场景:
- 使用Symbol来作为对象属性名(key)
注意:Symbol类型的key是不能通过Object.keys()
或者for...in
来枚举的,它未被包含在对象自身的属性名集合(property names)之中,所以,利用该特性,我们可以**把一些不需要对外操作和访问的属性使用Symbol来定义。**当使用JSON.stringify()
将对象转换成JSON字符串的时候,Symbol属性也会被排除在输出内容之外 - 使用Symbol来替代常量
const TYPE_AUDIO = Symbol() const TYPE_VIDEO = Symbol() const TYPE_IMAGE = Symbol()
- 使用Symbol定义类的私有属性/方法:私有化内部属性/方法
- 注册和获取全局Symbol
通常情况下,我们在一个浏览器窗口中(window),使用Symbol()
函数来定义和Symbol实例就足够了。但是,如果你的应用涉及到多个window(最典型的就是页面中使用了<iframe>
),并需要这些window中使用的某些Symbol是同一个,那就不能使用Symbol()
函数了,因为用它在不同window中创建的Symbol实例总是唯一的,而我们需要的是在所有这些window环境下保持一个共享的Symbol。这种情况下,我们就需要使用另一个API来创建或获取Symbol,那就是Symbol.for()
,它可以注册或获取一个window间全局的Symbol实例:
let gs1 = Symbol.for('global_symbol_1') //注册一个全局Symbol let gs2 = Symbol.for('global_symbol_1') //获取全局Symbol gs1 === gs2 // true
基本类型和复杂类型(对象)有什么区别
- 声明变量时不同的内存分配:
1)原始值:存储在栈(stack)中的简单数据段,也就是说,它们的值直接存储在变量访问的位置。
2)引用值:存储在堆(heap)中的对象,也就是说,存储在变量处的值是一个指针(point),指向存储对象的内存地址。 - 不同的内存分配机制也带来了不同的访问机制
1)在javascript中是不允许直接访问保存在堆内存中的对象的,**所以在访问一个对象时,首先得到的是这个对象在堆内存中的地址,然后再按照这个地址去获得这个对象中的值,**这就是传说中的按引用访问。
2)而原始类型的值则是可以直接访问到的 - 复制变量时的不同
1)原始值:在将一个保存着原始值的变量复制给另一个变量时,会将原始值的副本赋值给新变量,此后这两个变量是完全独立的,他们只是拥有相同的value而已。
2)引用值:在将一个保存着对象内存地址的变量复制给另一个变量时,会把这个内存地址赋值给新变量,也就是说这两个变量都指向了堆内存中的同一个对象,他们中任何一个作出的改变都会反映在另一个身上。(这里要理解的一点就是,复制对象时并不会在堆内存中新生成一个一模一样的对象,只是多了一个保存指向这个对象指针的变量罢了)。 - 参数传递的不同(把实参复制给形参的过程)
首先我们应该明确一点:ECMAScript中所有函数的参数都是按值来传递的。但是为什么涉及到原始类型与引用类型的值时仍然有区别呢?还不就是因为内存分配时的差别。
1)原始值:只是把变量里的值传递给参数,之后参数和这个变量互不影响。
2)引用值:对象变量它里面的值是这个对象在堆内存中的内存地址,这一点你要时刻铭记在心
Git的版本控制与分支管理**
git branch A 创建A分支
git branch -d A 删除A分支
git checkout master 切换到master分支
git checkout -b dev 创建并马上切换到dev分支
git merge dev 合并dev分支到当前分支
实现深复制的三种方法
//使用递归的方式实现数组、对象的深拷贝 function deepClone1(obj) { //判断拷贝的要进行深拷贝的是数组还是对象,是数组的话进行数组拷贝,对象的话进行对象拷贝 var objClone = Array.isArray(obj) ? [] : {}; //进行深拷贝的不能为空,并且是对象或者是 if (obj && typeof obj === "object") {// for (key in obj) { if (obj.hasOwnProperty(key)) {// if (obj[key] && typeof obj[key] === "object") {// objClone[key] = deepClone1(obj[key]);// } else { objClone[key] = obj[key];// } } } } return objClone; }
//通过js的内置对象JSON来进行数组对象的深拷贝 function deepClone2(obj) { var _obj = JSON.stringify(obj), objClone = JSON.parse(_obj); return objClone; }
var array = [1,2,3,4]; var newArray = $.extend(true,[],array);
lodash.cloneDeep()实现深拷贝
当对象中只有一级属性,没有二级属性的时候,此方法为深拷贝,但是对象中有对象的时候,此方法,在二级属性以后就是浅拷贝。
JQuery 获取ID元素与JS获取的区别
- KaTeX parse error: Expected 'EOF', got '#' at position 3: ("#̲id")获取的对象其实是一个数…(“#id”)[0],这样两个就相等了。
vue中组件通信方式
- 父组件向子组件传值:
父组件通过props向下传递数据给子组件。注:组件中的数据共有三种形式:data、props、computed - 子组件向父组件传值: 通过事件形式$emit: 子组件通过events给父组件发送消息,实际上就是子组件把自己的数据发送到父组件
- 通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级
- Vuex: Vuex实现了一个单向数据流,在全局拥有一个State存放数据,当组件要更改State中的数据时,必须通过Mutation进行,Mutation同时提供了订阅者模式供外部插件调用获取State数据的更新。而当所有异步操作(常见于调用后端接口异步获取更新数据)或批量的同步操作需要走Action,但Action也是无法直接修改State的,还是需要通过Mutation来修改State的数据。最后,根据State的变化,渲染到视图上。
vuex 是 vue 的状态管理器,存储的数据是响应式的。但是并不会保存起来,刷新之后就回到了初始状态,具体做法应该在vuex里数据改变的时候把数据拷贝一份保存到localStorage里面,刷新之后,如果localStorage里有保存的数据,取出来再替换store里的state。
总结
- 父子通信:
父向子传递数据是通过 props,子向父是通过 events**(
$emit
)**;通过父链 / 子链也可以通信($parent
/$children
);ref 也可以访问组件实例;provide / inject API;$attrs/$listeners
- 兄弟通信:Bus;Vuex
- 跨级通信:Bus;Vuex;provide / inject API、
$attrs/$listeners
同源策略
如果两个页面的协议,端口(如果有指定)和主机都相同,则两个页面具有相同的源。我们也可以把它称为**“协议/主机/端口**
跨域的解决方法
https://www.cnblogs.com/laixiangran/p/9064769.html
- CORS(跨域资源共享): 是一个 W3C 标准,定义了在必须访问跨域资源时,浏览器与服务器应该如何沟通。CORS 背后的基本思想,就是使用自定义的 HTTP 头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE 浏览器不能低于 IE10。整个 CORS 通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS 通信与同源的 AJAX 通信没有差别,代码完全一样。**浏览器一旦发现 AJAX 请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现 CORS 通信的关键是服务器。**只要服务器实现了 CORS 接口,就可以跨源通信。浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。
- 简单请求:浏览器直接发出CORS请求,在头信息中添加一个Origin字段,用来说明请求来自哪个源,服务器根据这个值,决定是否同意这次请求。
- 如果服务器不许可,则返回的信息中不会包含Access-Control-Allow-Origin字段,这个错误需要onerror捕获,返回的状态码可能为200;
如果服务器许可,则服务器返回的响应中会多出Access-Control-字段;
CORS默认不发送cookie,需要发送cookies,则需要服务器指定Access-Control-Allow-Credentials字段,需要在ajax请求中打开withCredentials属性;
- 非简单请求/复杂请求:请求方法是PUT或DELETE,Content-Type字段类型是application/json。
- 会在正式通信前,增加一次OPTIONS查询请求,预检请求(目的就是为了判断实际发送的请求是否是安全的)询问服务器,网页所在域名是否在服务器的许可名单中,以及可以使用那些HTTP动词和头信息字段,只有得到肯定答复,浏览器才会发出正式XMLHTTPRequest请求,否则会报错
服务器通过预检请求,以后每次浏览器正常CORS请求,都会和简单请求一样,会有一个Origin字段,服务器的回应也会有Access-Control-Allow-Origin头信息字段 - JSONP 跨域(Json with Padding的缩写,就是“填充式Json”): 借助script标签能跨域的原理。浏览器告诉服务端一个回调函数的名称,服务端在返回的script里面调用这个回调函数,同时传进客户端需要的数据,这个返回的代码就能在浏览器上执行了。
JSONP和CORS比较,缺点是支持是get类型。优点是兼容老版本浏览器。 - 服务器代理
- document.domain =“父域”:子域跨父域
- postMessage 跨域:父窗口向子iframe传消息
- location.hash 跨域
- window.name 跨域
- 图像 Ping 跨域
进程线程
- 进程:是执行中一段程序,即一旦程序被载入到内存中并准备执行,它就是一个进程。进程是表示资源分配的的基本单位,又是调度运行的基本单位,是系统中的并发执行的单位。
- 线程:单个进程中执行中每个任务就是一个线程。
- 一个线程只能属于一个进程,但是一个进程可以拥有多个线程。多线程处理就是允许一个进程中在同一时刻执行多个任务
- 线程没有地址空间,线程包含在进程的地址空间中
- 父和子进程使用进程间通信机制
- 进程内的任何线程都被看做是同位体,且处于相同的级别。不管是哪个线程创建了哪一个线程,进程内的任何线程都可以销毁、挂起、恢复和更改其它线程的优先权。
- 子进程不对任何其他子进程施加控制,进程的线程可以对同一进程的其它线程施加控制。
状态码
HTTP状态码共分为5种类型:
1** | 信息,服务器收到请求,需要请求者继续执行操作 |
2** | 成功,操作被成功接收并处理 |
3** | 重定向,需要进一步的操作以完成请求 |
4** | 客户端错误,请求包含语法错误或无法完成请求 |
5** | 服务器错误,服务器在处理请求的过程中发生了错误 |
常见的HTTP状态码:
- 200 - 请求成功
- 301 - 资源(网页等)被永久转移到其它URL
- 302- 资源只是临时被移动。客户端应继续使用原有URI
- 304- 未修改。所请求的资源未修改,服务器返回此状态码时,不会返回任何资源。
- 404 - 请求的资源(网页等)不存在
- 500 - 内部服务器错误
- 502- 作为网关或者代理工作的服务器尝试执行请求时,从远程服务器接收到了一个无效的响应
前端缓存
https://www.cnblogs.com/cencenyue/p/7604651.html
- cookie是浏览器提供的一种机制,它将document 对象的cookie属性提供给JavaScript。可以由JavaScript对其进行控制,而并不是JavaScript本身的性质。cookie是存于用户硬盘的一个文件,这个文件通常对应于一个域名,当浏览器再次访问这个域名时,便使这个cookie可用。
如果不在浏览器中设置过期时间,cookie被保存在内存中,生命周期随浏览器的关闭而结束,这种cookie简称会话cookie。如果在浏览器中设置了cookie的过期时间,cookie被保存在硬盘中,关闭浏览器后,cookie数据仍然存在,直到过期时间结束才消失。
Cookie是服务器发给客户端的特殊信息,cookie是以文本的方式保存在客户端,每次请求时都带上它
cookie的缺点主要集中于安全性和隐私保护。(Cookie欺骗,Cookie截获)
- localStorage中一般浏览器支持的是5M大小,这个在不同的浏览器中localStorage会有所不同
localStorage会可以将第一次请求的数据直接存储到本地,这个相当于一个5M大小的针对于前端页面的数据库,相比于cookie可以节约带宽
localStorage本质上是对字符串的读取,如果存储内容多的话会消耗内存空间,会导致页面变卡
localStorage与sessionStorage的唯一一点区别就是localStorage属于永久性存储,而sessionStorage属于当会话结束的时候,sessionStorage中的键值对会被清空
- sessionStorage用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储。**sessionStorage是在同源的窗口中始终存在的数据。**只要这个浏览器窗口没有关闭,即使刷新页面或者进入同源另一个页面,数据依然存在。但是sessionStorage在关闭了浏览器窗口后就会被销毁。同时独立的打开同一个窗口同一个页面,sessionStorage也是不一样的
WebStorage**不会随着HTTP header发送到服务器端,所以安全性相对于cookie来说比较高一些,**不会担心截获,但是仍然存在伪造问题;
白屏之前的步骤优化
发生的原因基本可以归结为网速&静态资源
1、css文件加载需要一些时间,在加载的过程中页面是空白的。 解决:可以考虑将css代码前置和内联。
2、首屏无实际的数据内容,等待异步加载数据再渲染页面导致白屏。 解决:在首屏直接同步渲染html,后续的滚屏等再采用异步请求数据和渲染html。
3、首屏内联js的执行会阻塞页面的渲染。 解决:尽量不在首屏html代码中放置内联脚本。
根本原因是客户端渲染的无力,因此最简单的方法是在服务器端,使用模板引擎渲染所有页面。同时:
1减少文件加载体积,如html压缩,js压缩
2加快js执行速度 比如常见的无限滚动的页面,可以使用js先渲染一个屏幕范围内的东西:懒加载
3提供一些友好的交互,比如提供一些假的滚动条
4使用本地存储处理静态文件。