查缺补漏查缺补漏查缺补漏
技术面照着简历问,问得浅没太深挖,不会的就答不会也没有压力面,然后紧跟hr面,一共18min左右。1v3。
本科学过web技术及应用,计算机网络;项目实践时自学微信小程序开发和React;
软件设计模式分类:
①创建型:创建对象时,不再由我们直接实例化对象;而是根据特定场景,由程序来确定创建对象的方式,从而保证更大的性能、更好的架构优势。(简单工厂模式、工厂方法、抽象工厂模式、单例模式、生成器模式和原型模式)
②结构型:用于帮助将多个对象组织成更大的结构。(适配器模式adapter、桥接模式bridge、组合器模式component、装饰器模式decorator、门面模式、亨元模式flyweight和代理模式proxy)
③行为型:用于帮助系统间各对象的通信,以及如何控制复杂系统中流程。(命令模式command、解释器模式、迭代器模式、中介者模式、备忘录模式、观察者模式、状态模式state、策略模式、模板模式和访问者模式)
①从表面上看:
观察者模式里,只有两个角色 —— 观察者 + 被观察者。
发布订阅模式里,却不仅仅只有发布者和订阅者两个角色,还有一个经常被我们忽略的 —— 经纪人Broker。
②往深层次讲:
观察者和被观察者,是松耦合的关系。
发布者和订阅者,则完全不存在耦合。
③从使用层面上说:
观察者模式,多用于单个应用内部。
发布订阅模式,则更多的是一种跨应用的模式(cross-application pattern),比如我们常用的消息中间件。
小程序的生命周期分为:
(1)应用生命周期
(2)页面生命周期
(3)应用生命周期影响页面生命周期
(1)小程序通过App()来注册一个小程序,App() 必须在 app.js 中调用,必须调用且只能调用一次,app.js中定义了一些应用的生命周期函数:
(1)onLaunch: 初始化小程序时触发,全局只触发一次。
(2)onShow: 小程序初始化完成或用户从后台切换到前台显示时触发。
(3)onHide: 用户从前台切换到后台隐藏时触发。
(4)onError: 小程序发生脚本错误,或者 api 调用失败时,会触发 onError 并带上错误信息。
①用户首次打开小程序,会触发onLauch(全局只触发一次);
②小程序初始化完成后,触发onShow方法,监听小程序显示;
③小程序从前台进入后台(点击左上角关闭,或者按了设备 Home 键,并没有直接销毁),触发onHide方法;
④小程序从后台进入前台显示,触发onShow方法;
⑤小程序后台运行一定时间,或系统资源占用过高,会被销毁;
(2)小程序通过Page()来注册一个页面,js文件中定义了一些页面生命周期函数:
(1)onLoad:首次进入页面加载时触发,可以在 onLoad 的参数中获取打开当前页面路径中的参数。
(2)onShow:加载完成后、后台切到前台或重新进入页面时触发
(3)onReady:页面首次渲染完成时触发(页面已准备妥当,可以进行视图层交互)
(4)onHide:从前台切到后台或进入其他页面触发
(5)onUnload:页面卸载时触发
(6)onPullDownRefresh:监听用户下拉动作
(7)onReachBottom:页面上拉触底事件的处理函数
①小程序注册完成后,加载页面,触发onLoad方法,一个页面只会调用一次;
②页面载入后触发onShow方法,显示页面,每次打开页面都会调用一次;
③首次显示页面,会触发onReady方法,渲染页面和样式,一个页面只会调用一次;
④当小程序后台运行或跳转到其他页面时,触发onHide方法;
⑤当小程序从后台进入前台运行或重新载入页面时,触发onShow方法;
⑥当使用wx.readirectTo(OBJECT)或关闭当前页返回上一页wx.navigateBack(),触发onUnload
【补充】
wx.navigateTo跳转,页面的生命周期变化(wx.navigateTo()是隐藏当前页面,跳转到某个页面,跳转后可以通过wx.navigateBack()返回上一页,但wx.navigateBack()会关闭当前页)
①进入A页面:A执行onLoad()–> onShow()–> onReady();
②A页面wx.navigateTo(B页面):A执行onHide(),B执行onLoad()–> onShow()–> onReady();
③B页面wx.navigateBack(A页面):B执行onUnload(),A执行onShow();
④退出A页面:A执行onUnload()
wx.redirectTo跳转,页面的生命周期变化(wx.redirectTo()是关闭当前页面,跳转到某个页面,跳转页面后不能返回上一页)
①进入A页面:A执行onLoad()–> onShow()–> onReady();
②A页面wx.redirectTo(B页面):A执行onUnload(),B执行onLoad()–> onShow()–> onReady();
①小程序初始化完成后,页面首次加载触发onLoad,只会触发一次;
②小程序进入后台,先执行页面的onHide方法然后执行应用的onHide方法;
③当小程序从后台进入到前台,先执行应用的onShow方法然后执行页面的onShow方法;
生命周期总结
进入小程序时:
首先执行应用生命周期函数,再次执行页面生命周期函数
离开小程序时:
首先执行页面生命周期函数,再次执行应用生命周期函数
一文看懂CDN加速原理
CDN网络是在用户和服务器之间增加Cache层,主要是通过接管DNS实现,将用户的请求引导到Cache上获得源服务器的数据,从而降低网络的访问时间。
①用户输入访问的域名,操作系统向 LocalDns 查询域名的ip地址;
②LocalDns向 ROOT DNS 查询域名的授权服务器(这里假设LocalDns缓存过期);
③ROOT DNS将域名授权dns记录回应给 LocalDns;
④LocalDns得到域名的授权dns记录后,继续向域名授权dns查询域名的ip地址;
⑤域名授权dns 查询域名记录后,回应给 LocalDns;
⑥LocalDns 将得到的域名ip地址,回应给用户端;
⑦用户得到域名ip地址后,访问站点服务器;
⑧站点服务器应答请求,将内容返回给客户端.
①用户输入访问的域名,操作系统向 LocalDns 查询域名的ip地址;
②LocalDns向 ROOT DNS 查询域名的授权服务器(这里假设LocalDns缓存过期);
③ROOT DNS将域名授权dns记录回应给 LocalDns;
④LocalDns得到域名的授权dns记录后,继续向域名授权dns查询域名的ip地址;
⑤域名授权dns 查询域名记录后(一般是CNAME),回应给 LocalDns;
⑥LocalDns 得到域名记录后,向智能调度DNS查询域名的ip地址;
⑦智能调度DNS 根据一定的算法和策略(比如静态拓扑,容量等),将最适合的CDN节点ip地址回应给 LocalDns;
⑧LocalDns 将得到的域名ip地址,回应给用户端;
⑨用户得到域名ip地址后,访问站点服务器。
跨域系统使用,属于后端部署范围。
16.12.0
①let、const:规范变量作用域提高程序运行安全性
②箭头函数:操作符=>简化了函数的书写
③字符串模版:允许使用反引号 ` 来创建字符串,此种方法创建的字符串里面可以包含由美元符号加花括号包裹的变量${vraible}
④Proxyy:可以监听对象身上发生了什么事情,并在这些事情发生后执行一些相应的操作,一个对象有了很强的追踪能力,同时在数据绑定方面也很有用处。个人理解类似于触发器。
react与VUE一大差别就在于优化,vue打包完整使用方便,而react更接近js,优点是很灵活,但运行时优化是一大问题。
React16的expirationTimes模型只能区分是否>=expirationTimes决定节点是否更新。React17的lanes模型可以选定一个更新区间,并且动态的向区间中增减优先级,可以处理更细粒度的更新。
①新增用于绘画的canvas元素
②新增表单属性
required 属性:是一个 boolean 属性。要求填写的输入域不能为空
pattern 属性:描述了一个正则表达式用于验证元素的值。
min 和 max 属性:设置元素最小值与最大值。
step 属性:为输入域规定合法的数字间隔。
height 和 width 属性:用于 image 类型的标签的图像高度和宽度。
autofocus 属性:是一个 boolean 属性。规定在页面加载时,域自动地获得焦点。
multiple 属性:是一个 boolean 属性。规定元素中可选择多个值。
③新增video和audio元素
video标签如何控制播放,放标签,autoplay/autobuffer/muted/loop controls或自己加入组件绑定动作实现。
④地理位置
⑤拖放功能
⑥…
急速8min,自我介绍(2min),然后挑一个最近的项目(基于微信小程序的健身动作只能识别与纠正),主要问实现细节,如何解决问题。1v3。
除了最基础的页面布局和响应跳转之外
主要用了TensorFlow.js接口实现视觉模型加载
结合camera接口获取用户动作,canvas接口将识别的肢体骨架重绘在屏幕上实时反馈给用户,完成前端数据获取和视觉反馈的功能
为了达到更好的用户体验有实现一些数据预拉取和缓存策略
在节约内存方面,使用了tf.tidy丢掉中间变量,以及tf.dispose丢掉用过的tensor向量。
考虑到小程序可以被任何机型的手机使用,有考虑过适配的问题
①对于普通组件适配用的是盒式模型,尽量采用百分制描述组件属性而不是写死坐标,布局等也尽量使用居中使不同机型都有相似观感。
②但对于最核心最影响观感的canvas重绘部分没有办法做到不同机型适配
原因在于tf传的数据是实际camera坐标,照理说直接拿这个坐标写会canvas就可以,但实操并不如此,发现骨架点会有漂移
查阅小程序开发文档发现,微信会在后台按一套不可知的方法将展示出来的camera做裁剪,导致坐标数据失效,并且没有提供可以拿到camera实际大小的方法或说明后台的裁剪规则
所以只能通过将坐标比例写死来适配某一特定手机来解决骨架点漂移的问题
缓存:
posenet.load支持网络加载和localStorage两种方式。
一开始我们是通过google在国内的镜像加载模型的
但是每次加载都需要时间,于是我们直接把模型的json文件放到本地localStorage里面,然后每次都从本地加载,这样就加快了模型加载速度
但是缺点就是不能灵活的更换不同backend的模型
这是从用户体验和实际编码两个方面做出的妥协,我们认为作为一个练习性的项目,首先是要保证功能的稳定性和可用性,再去考虑功能的多样性,这就是我们解决这个问题的全过程
后面如果可以的话,我们认为可以使用相关云服务商提供的OSS(对象存储服务)对模型文件做加速,以进一步提高功能的多样性
数据预拉取:
为使小程序的使用更符合一般使用习惯以及后续还要加上后端进行动作纠正的部分,不会一开始就把获取camera和重绘的界面显示出来,而是通过层层点击跳转,依次选定运动的大类和小类,到达某一特定运动介绍页点击开始训练,才会跳转到识别的功能页。
如果每次都打开camera了才开始加载模型,会让拉长空等时间影响用户体验。
因此考虑运利用前面页面跳转的时间,在进入运动介绍页时就开始加载动作模型,可以减少等待时间,如果用户因阅读介绍页花费较长时间,更可不必等待模型加载,达到打开即用的效果。
1h12min,面试官人很温柔。从自我介绍挖项目,从项目挖基础知识,计网osds都有涉及。手撕代码太拉环节是我自己拉跨,总体体验不错。1v1。
http报头让客户端和服务器之间传递了更多的信息
服务器能够从发送过来的报头了解到用户的一些必要信息
服务器传回的报头让客户端更好的理解和解析
分为公共头部、请求头request和返回头response
公共头部:
字段 | 说明 |
---|---|
Remote Address | 请求的远程地址 |
Request URL | 请求的域名 |
Request Method | 页面请求的方式:Post/Get |
Status Code | 请求的返回状态 |
【补充】
Get和Post的区别(浏览器什么情况下发get,什么情况下发post)
1)post更安全(不会作为url的一部分,不会被缓存、保存在服务器日志、以及浏览器浏览记录中)
2)post发送的数据更大(get有url长度限制)
3)post能发送更多的数据类型(get只能发送ASCII字符)
4)post比get慢
5)post用于修改和写入数据,get一般用于搜索排序和筛选之类的操作(淘宝,支付宝的搜索查询都是get提交),目的是资源的获取,读取数据。
请求头request:
字段 | 说明 |
---|---|
Accept | 浏览器支持的MIME类型(MIME的英文全称是 Multipurpose Internet Mail Extensions(多功能 Internet 邮件扩充服务),它是一种多用途网际邮件扩充协议,在1992年最早应用于电子邮件系统,但后来也应用到浏览器。) |
Accept-Encoding | 浏览器支持的压缩类型 |
Accept-Language | 浏览器支持的语言类型,并且优先支持靠前的语言类型t |
Cache-Control | 指定请求和响应遵循的缓存机制 |
Connection | 当浏览器与服务器通行时对于长连接如何进行处理:close/keep-alive |
Cookie | 向服务器返回cookie,这些cookie是之前服务器发给浏览器的 |
Host | 请求的服务器URL |
Referer | 该页面的来源URL |
User-Agent | 用户客户端的一些必要信息(如os、浏览器及版本、浏览器渲染引擎等) |
返回头response:
字段 | 说明 |
---|---|
Cache-Control | 高速浏览器或者其他客户什么环境可以安全地缓存文档 |
Connection | 当client和server通行时对于长连接如何进行处理 |
Content-Encoding | 数据在传输过程中所使用的压缩编码方式 |
Content-Type | 数据的类型 |
Date | 数据从服务器发送的时间 |
Expires | 认为文档已经过期从而不再缓存的时间期限 |
Server | 服务器名字。Servlet一般不设置这个值,而是由Web服务器自己设置 |
Set-Cookie | 设置和页面关联的cookie |
Transfer-Encoding | 数据传输的方式 |
在REST架构风格中,数据和功能被视为资源,并使用统一资源标识符(URI)进行访问。通过使用一组简单,定义明确的操作来执行资源。客户端和服务器通过使用标准化接口和协议(通常是HTTP)来交换资源的表示。
REST的指导原则包括以下六项
客户端-服务器 :将用户接口问题与数据存储问题分开,通过简化服务器组件来提高跨多个平台的用户接口的可移植性并提高可伸缩性。
无状态 :从客户端到服务器的每个请求都必须包含理解请求所需的所有信息,并且不能利用服务器上任何存储的上下文。因此,会话状态完全保留在客户端上。
可缓存 :缓存约束要求将对请求的响应中的数据隐式或显式标记为可缓存或不可缓存。如果响应是可缓存的,则客户端缓存有权重用该响应数据以用于以后的等效请求。
统一接口 :通过将通用性的软件工程原理应用于组件接口,简化了整个系统架构,提高了交互的可见性。为了获得统一的接口,需要多个架构约束来指导组件的行为。REST由四个接口约束定义:资源识别; 通过陈述来处理资源; 自我描述性的信息; 超媒体作为应用程序状态的引擎。
分层系统 :分层系统风格允许通过约束组件行为来使体系结构由分层组成,这样每个组件都不能“看到”超出与它们交互的直接层。
按需编码(可选) :REST允许通过以小程序或脚本的形式下载和执行代码来扩展客户端功能,因减少预先实现所需的功能数量来简化客户端。
1**:信息,服务器收到请求,需要请求者继续执行操作
2**:成功,操作被成功接收并处理
3**:重定向,需要进一步的操作以完成请求
4**:客户端错误,请求包含语法错误或无法完成请求
5**:服务器错误,服务器在处理请求的过程中发生了错误
404 (“Not Found”)
410(“gone”)当客户端请求的URI不对应任何应用资源时
ps:微信小程序本地缓存最大为10M
缓存数据到本地:缓存值可以为一个字符串,也可以为一个对象,当第一个参数值key相同的时候,后面的会覆盖前面的。异步也一样。
wx.setStorageSync(‘key’,‘value’)同步
wx.setStorage({ key:“key”, data:“value”})异步
获取本地缓存数据:同步和异步两种方法中的key是必须要传入的,否者不知道获取的具体缓存值。
wx.getStorageInfoSync(string key) 同步方式从本地缓存同步获取指定key wx.getStorageInfo(Object object) 异步方式从本地缓存同步获取指定key
wx.getStorageSync(string key)同步方法获取当前storage相关信息 wx.getStorage(Object object) 异步方式获取当前storage相关信息
移除和清理本地缓存数据
wx.removeStorageSync() 同步移除指定key
wx.removeStorage() 异步移除指定key
wx.clearStorageSync() 同步清理本地缓存
wx.clearStorage() 清理本地数据缓存
格式原本格式,不会变换成二进制流或者其他类型。
①首次加载图片一定是从网络下载:wx.downloadFile 必填参数url: 图片的地址。
②当图片下载成功以后,会返回给我们一个tempFilePath,是临时的文件路径。本地临时文件只能通过调用特定接口产生,不能直接写入内容。本地临时文件产生后,仅在当前生命周期内有效,重启之后即不可用。因此,不可把本地临时文件路径存储起来下次使用。
③但小程序的api可以获取到全局唯一的文件管理器,其作用之一就是可以根据临时文件路径,通过saveFile把文件保存到本地缓存,返回值为本地存储路径savedFilePath。
④下次打开小程序 首先去缓存中检查是否存在本地文件的缓存路径,如果有,直接image src赋值本地缓存路径;如果没有,则是第一次下载图片,或者用户手动清理缓存造成的。
12min。火急火燎的感觉,没问下个啥最后扯到数据结构收尾。1v2。
Nginx是一个高性能的HTTP和反向代理服务器,特点是占用内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好。nginx专为性能优化而开发,性能是其最重要的要求,十分注重效率,有报告nginx能支持高达50000个并发连接数。
①反向代理:见下补充
②负载均衡:增加服务器的数量,构建集群,将请求分发到各个服务器上,将原来请求集中到单个服务器的情况改为请求分发到多个服务器,也就是我们说的负载均衡。
③动静分离:将动态跟静态文件混合在一起发布,通过nginx分开
④高可用:下面使用两台Nginx做反向代理服务器,当其中一台Nginx宕机之后,仍能用另一台来工作,两台Nginx之间用keeplived来监测心跳。
【补充】
正向代理:局域网中的电脑用户想要直接访问网络是不可行的,只能通过代理服务器来访问,这种代理服务就被称为正向代理。
反向代理:客户端无法感知代理,因为客户端访问网络不需要配置,只要把请求发送到反向代理服务器,由反向代理服务器去选择目标服务器获取数据,然后再返回到客户端,此时反向代理服务器和目标服务器对外就是一个服务器,暴露的是代理服务器地址,隐藏了真实服务器IP地址
Mint UI:是饿了么团队开发基于vue .js的移动端UI框架,它包含丰富的 CSS 和 JS 组件,能够满足日常的移动端开发需要。
流行指数:★★★★
WEUI:是一套同微信原生视觉体验一致的基础样式库,由微信官方设计团队为微信内网页和微信小程序量身设计,令用户的使用感知更加统一。
流行指数:★★★
Cube UI:是滴滴团队开发的基于 Vue.js 实现的精致移动端组件库。支持按需引入和后编译,轻量灵活;扩展性强,可以方便地基于现有组件实现二次开发。
流行指数:★★★★★
iView UI:是一个基于vue的强大ui库,有很多实用的基础组件比elementui的组件更丰富,主要服务于 PC 界面的中后台产品。使用单文件的 Vue 组件化开发模式 基于 npm + webpack + babel 开发,支持 ES2015 高质量、功能丰富 友好的 API ,自由灵活地使用空间。
流行指数:★★★★★★
layui:是一款采用自身模块规范编写的前端 UI 框架,遵循原生 HTML/CSS/JS 的书写与组织形式,门槛极低,拿来即用。其外在极简,却又不失饱满的内在,体积轻盈,组件丰盈,从核心代码到 API 的每一处细节都经过精心雕琢,非常适合界面的快速开发。
流行指数:★★★★★★★
ElementUI:是饿了么前端开源维护的Vue UI组件库,组件齐全,基本涵盖后台所需的所有组件,文档讲解详细,例子也很丰富。 主要用于开发PC端的页面,是一个质量比较高的Vue UI组件库。
流行指数:★★★★★★★★
at-ui:是一款阿里团队创建的基于 Vue 2.x 的前端 UI 组件库,主要用于快速开发 PC 网站产品。 它提供了一套 npm + webpack + babel 前端开发工作流程,CSS 样式独立,即使采用不同的框架实现都能保持统一的 UI 风格。
流行指数:★★★★★★★★★
amaze UI:是一个移动优先的跨屏前端框架。提供基础样式,网格,表格、表单、按钮及常用组件样式。是一个轻量级(所有 CSS 和 JS gzip 后 100 kB 左右)、 Mobile first 的前端框架。
流行指数:★★★★★★★★★★
Vant UI:有赞前端团队基于有赞统一的规范实现的 Vue 组件库,提供了一整套 UI 基础组件和业务组件。通过 Vant,可以快速搭建出风格统一的页面,提升开发效率。
流行指数:★★★★★★★★★★★
Flutter:是谷歌的移动端 UI 框架,可在极短的时间内构建 Android 和 iOS 上高质量的原生级应用。 Flutter 可与现有代码一起工作, 它被世界各地的开发者和组织使用, 并且 Flutter 是免费和开源的。
流行指数:★★★★★★★★★★★★★
ionic:既是一个CSS框架也是一个Javascript UI库,Ionic 是目前最有潜力的一款 HTML5 手机应用开发框架。通过 SASS 构建应用程序,它提供了很多UI组件来帮助开发者开发强大的应用。它使用 JavaScript MVVM 框架和 AngularJS 来增强应用。提供数据的双向绑定,使用它成为 Web 和移动开发者的共同选择。
流行指数:★★★★★★★★★★★
22min。1v1。完全考察基础,反问环节说二面才问项目,会有引导但是不多,有耐心,记录了完全不知道和没太回答得很完美的部分。
1)浏览器会把输入的域名解析成对应的IP:
依次查找浏览器缓存的DNS记录、本机系统缓存的hosts文件、ISP 服务商缓存 DNS的服务器、递归或迭代地从顶级域名服务器开始找。
2)浏览器与目标服务器建立TCP连接(三次握手):
SYN=1:发送/同步标志
ACK=1:确认标志,表示确认收到请求
seq:报文自己的一个序号id,自己发的是连续的序号
ack:希望接到对方的序号,用来确认是否丢包
3)浏览器通过http协议发送请求(地址栏输入只能是Get)
请求中包含访问的URL,KeepAlive长连接,还有User-Agent用户浏览器操作系统信息,编码等。
4)有些服务会做永久重定向响应
对于大型网站存在多个主机站点,为了负载均衡或者导入流量,往往不会直接返回请求页面,而是重定向。返回的状态码就不是200,而是301,302等以3开头的重定向码,浏览器在获取了重定向响应后,在响应报文中Location项找到重定向地址,重新发送一个http请求,发送内容同上。
5)服务器处理请求并返回响应
经过一系列路由转发之后服务器接收到获取请求,然后处理并返回一个响应。返回状态码200 OK,表示服务器可以响应请求,返回报文,由于在报头中Content-type为“text/html”,浏览器以HTML形式呈现,而不是下载文件。
6)释放TCP连接(四次挥手)
FIN=1:结束标志,用于结束一个TCP会话
ACK=1:确认标志,表示确认收到请求
seq:报文自己的一个序号id,自己发的是连续的序号
ack:希望接到对方的序号,用来确认是否丢包
7)浏览器显示页面
在浏览器没有完整接受全部HTML文档时,它就已经开始显示这个页面了,浏览器接收到返回的数据包,根据浏览器的渲染机制对相应的数据进行渲染。渲染后的数据,进行相应的页面呈现和脚本的交互。
8)浏览器发送获取嵌入在HTML中的其他内容
比如一些样式文件,图片url,js文件url等,浏览器会通过这些url重新发送请求,请求过程依然是HTML读取类似的过程,查询域名,发送请求,重定向等。不过这些静态文件是可以缓存到浏览器中的,有时访问这些文件不需要通过服务器,直接从缓存中取。某些网站也会使用第三方CDN进行托管这些静态文件。
1)遍历HTML文档节点,生成DOM树
①DOM树在构建的过程中可能会被CSS和JS的加载而执行阻塞
②display:none的元素也会在DOM树中
③注释也会在DOM树中
④script标签会在DOM树中
⑤当前节点的所有子节点都构建好后才会去构建当前节点的下一个兄弟节点
2)浏览器解析CSS文件并生成CSSOM规则树
①CSS解析可以与DOM解析同时进行。
②CSS解析与script的执行互斥 。
③在Webkit内核中进行了script执行优化,只有在JS访问CSS时才会发生互斥
3)浏览器通过DOM和CSSOM构建渲染树(Render Tree)
①浏览器会先从DOM树的根节点开始遍历每个可见节点,然后对每个可见节点找到适配的CSS样式规则并应用。
② 当解析HTML的时候,会把新来的元素插入DOM树里面,同时去查找CSS(并行),然后把对应的样式规则应用到元素上,查找样式表是按照从右到左的顺序去匹配的,例如:div p {font-size: 16px},会先寻找所有p标签并判断它的父标签是否为div之后才会决定要不要采用这个样式进行渲染)。所以写CSS时尽量用id和class,千万不要过渡层叠。
②Render Tree和DOM Tree不完全对应,display: none和visibility: hidden的元素不在Render Tree中
④渲染树生成后还是不能渲染到屏幕上,因为缺少各个节点的位置信息,因此还需要布局(Layout)的处理。
4)渲染树布局(layout of the render tree)
①布局阶段会从渲染树的根节点开始遍历
②渲染树的每个节点都是Render Object对象,包含宽高,位置,背景色等样式信息
③所以浏览器就可以通过这些样式信息来确定每个节点对象在页面上的确切大小和位置,布局阶段的输出就是我们常说的盒子模型,它会精确地捕获每个元素在屏幕内的确切位置与大小
④float元素,absoulte元素,fixed元素会发生位置偏移,即脱离文档流=脱离渲染树
5)渲染树绘制(Painting the render tree)
①调用渲染器的paint()方法在屏幕上显示其内容
②渲染树的绘制工作是由浏览器的UI后端组件完成的
③渲染引擎主要有两个:webkit(开源)和Gecko
Firefox使用Geoko,Mozilla自主研发的渲染引擎。Safari和Chrome都使用webkit。
【补充】:渲染阻塞
JS阻塞页面: JS阻塞了构建DOM树,也阻塞了其后的构建CSSOM规则树,整个解析进程必须等待JS的执行完成才能够继续。
CSS阻塞渲染: 由于CSSOM负责存储渲染信息,浏览器就必须保证在合成渲染树之前,CSSOM是完备的,这种完备是指所有的CSS(内联、内部和外部)都已经下载完,并解析完,只有CSSOM和DOM的解析完全结束,浏览器才会进入下一步的渲染。CSS阻塞渲染意味着,在CSSOM完备前,页面将一直处理白屏状态,这就是为什么样式放在head中,仅仅是为了更快的解析CSS,保证更快的首次渲染。需要注意的是,即便没有给页面任何的样式声明,CSSOM依然会生成,默认生成的CSSOM自带浏览器默认样式。
reflow(回流): 当浏览器发现布局发生了变化,这个时候就需要倒回去重新渲染,这个回退的过程叫reflow。reflow会从html这个root frame开始递归往下,依次计算所有的结点几何尺寸和位置,以确认是渲染树的一部分发生变化还是整个渲染树。(回流必然引起重绘) 发生回流的情况如下:
①页面第一次渲染(初始化)
②DOM树变化(如:增删节点)
③Render树变化(如:padding改变)
④浏览器窗口resize
⑤获取元素的某些属性
repaint(重绘): repaint则是当我们改变某个元素的背景色、文字颜色、边框颜色等等不影响它周围或内部布局的属性时,屏幕的一部分要重画,但是元素的几何尺寸和位置没有发生改变。背景色、颜色、字体改变等发生重绘。
减少reflow、repaint触发次数
①用transform做形变和位移可以减少reflow
②避免逐个修改节点样式,尽量一次性修改
③使用DocumentFragment将需要多次修改的DOM元素缓存,最后一次性append到真实DOM中渲染
④可以将需要多次修改的DOM元素设置display:none,操作完再显示。(因为隐藏元素不在render树内,因此修改隐藏元素不会触发回流重绘)
⑤避免多次读取某些属性
⑥通过绝对位移将复杂的节点元素脱离文档流,形成新的Render Layer,降低回流成本
优化渲染效率的建议:
常见的加密算法:MD5/SHA/DES/RC4/RSA/DSA/IDEA/AES等等;
服务器端验证: 客户端对报问体先进行MD5加密,生成一段字符串A,然后对字符串A进行RSA加密再生成字符串B,把字符串B加入到header然后对服务器发送请求。服务器接收到请求,对请求体(参数)也进行MD5、RSA加密生成字符串C。服务器对字符串C和B进行对比。如果相同,则是认为是客户端正常请求,如果不同:则认为有人恶意请求,不予回复。
客户端验证: 对header里某几个公共参数(或是重要的返回数据进行加密,自定义规则,打乱顺序)进行MD5加密生成字符串A,接着RSA加密生成字符串B,回复给客户端。客户端拿到字符串B,自己对header里的某几个公共参数MD5、RSA加密生成字符串C。判断B与C是否相同。相同即认为是服务器返回的报文,不相同即认为有人恶意修改数据。
标准(W3C)盒模型为content-box
设置width/height属性指的是content部分的宽/高
盒子尺寸:content+padding+border
IE盒模型为border-box
设置width/height属性指的是border + padding + content
盒子尺寸:content
通过设置box-sizing:content-box | border-box可实现盒模型切换
获得盒模型宽高方法:
①window.getComputedStyle(dom).width/height
②dom.getBoundingClientRect().width/height
弹性盒子,通过设置display:flex|inline-flex实现
CSS布局模型,又称为CCS盒布局模型。其实布局模型是建立在盒模型基础之上的,分为以下三种,可以混合使用:
Flow流式布局模型(默认的网页布局模式)
①块级元素都会在所处的最近父级容器元素内自上而下按顺序垂直顺延分布
②内联元素都会在所处的最近父级容器元素内从左到右水平分布显示
Float浮动布局模型
①任何元素在默认的情况下都是处于整个文档流中的,不会浮动的
②当给某一个元素设置浮动时,即可让该元素摆脱当前文档流,成为浮动元素
/**** 脱离当前文档流的意思是,该元素的前后元素在计算位置和偏移时将不再计算该元素的大小和位置 ****/
Layer层级布局模型,有以下三种定位类型:
①绝对定位(position: absolute):脱离文档流,相对于 非static 定位的第一个父元素进行定位
②相对定位(position: relative):没有脱离文档流,相对于其正常位置进行定位
③固定定位(position: fixed):脱离文档流,相对于浏览器窗口进行定位
方法一:(要求元素定宽高)
设置父元素为相对定位,给子元素设置绝对定位
left: 50%; top: 50%; 使元素的左上角移到父元素中间
margin-left: -元素宽度的一半px; margin-top: -元素高度的一半px;使元素往左上移一半元素的宽高。#father { width: 500px; height: 300px; position: relative; } #son { width: 100px; height: 100px; position: absolute; left: 50%; top: 50%; margin-left: -50px; margin-top: -50px; }
方法二:
设置父元素为相对定位,给子元素设置绝对定位
left: 50%; top: 50%;
transform: translateX(-50%) translateY(-50%);
原理与方法一相同,但是不定宽高#father { width: 500px; height: 300px; position: relative; } #son { position: absolute; left: 50%; top: 50%; transform: translateX(-50%) translateY(-50%); }
方法三:
设置父元素为相对定位,给子元素设置绝对定位
top: 0; right: 0; bottom: 0; left: 0;
margin: auto;#father { width: 500px; height: 300px; position: relative; } #son { position: absolute; top: 0; right: 0; bottom: 0; left: 0; margin: auto; }
方法四:
采用弹性盒子#father { width: 500px; height: 300px; display: flex; justify-content: center; align-items: center; } #son { }
方法五:
使用table-cell#father { width: 500px; height: 300px; display: table-cell; text-align:center; vertical-align:middle; } #son { }
主轴(main axis) 由flex-direction定义,交叉轴(cross axis) 垂直于主轴。
①主轴方向flex-direction:row,row-reverse,column,column-reverse
②换行属性flex-wrap:wrap可实现自动换行,flex-wrap:nowrap元素会缩小以适应容器
③简写属性 flex-flow = flex-direction + flex-wrap
④flex-basis 定义了该元素的空间大小
⑤flex-grow 属性可以按比例分配空间,值为1时容器中的可用空间被元素平分
⑥flex-shrink属性是处理flex元素收缩的问题,同级元素中数值越大可以收缩程度越大
⑦简写形式 flex = flex-grow + flex-shrink + flex-basis
⑧align-items规定元素在交叉轴方向对齐方式:stretch,flex-start,flex-end,center
⑨justify-content规定元素在主轴方向对齐方式:stretch,flex-start,flex-end,center,space-around,space-between
①行内样式,直接对HTML标签使用style="":
②内嵌样式,将CSS代码写在head标签之间,并且用style标签进行声明:
③链接样式,head标签之间加上,使用频率最高,最实用
④导入样式(不建议使用)
@import在html中使用:
@import在CSS中使用,如下:
@import url(style.css);
优先级:
1.就近原则
2.理论上:行内>内嵌>链接>导入
3.实际上:内嵌、链接、导入在同一个文件头部,谁离相应的代码近,谁的优先级高
!important >行内样式>ID>类>标签>通配符>继承>浏览器默认属性
JS基本数据类型:按值访问,按值比较,存放在Stack
Undefined、Null、Boolean、Number、String、Symbol (new in ES 6) 、BigInt
string常用APIat() 采用一个整数值,返回对应下标的值(正数从前数,负数从后数)
charAt() 用法同上但是取值范围只有[0,length-1]
concat() 将字符串参数连接到调用字符串,并返回一个新字符串
includes() 判断字符串中是否包含另一字符串(区分大小写)
indexOf() 返回字符第一次出现的下标,不存在返回-1
lastIndexOf 返回字符最后一次出现的下标,不存在返回-1
match() 返回字符串与正则表达式的匹配结果
slice() 同数组,[begin,end)决定的浅拷贝子串
split() 将String分为子字符串的有序列表
substring() 返回string的start和end索引之间或字符串末尾的部分
trim() 从字符串的两端删除空格,另有trimStart()和trimEnd()
JS引用数据类型:按引用访问,按引用比较,存放在Heap
Object 类型(统称)、Array 类型、Date 类型、RegExp 类型、Function 类型等
JS数据结构
Array、Map、Set、WeakMap、WeakSet
【补充map:】
map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数顺序依次处理后的值。map() 不会对空数组进行检测,map() 不会改变原始数组。
Array常用APIconcat() 合并两个或多个数组,不会更改现有数组,而是返回一个新数组
forEach() 对副本的每个元素执行一次给定的函数
indexOf() 返回在副本中可以找到一个给定元素的第一个索引,若不存在则返回-1
join() 将一个数组(一个或类数组对象)的所有元素用分隔符连接成一个字符串并返回这个字符串。如果数组只有一个项目,那么将返回该项目而不使用分隔符
pop() 从数组中删除最后一个元素,并返回该元素的值,会更改数组的长度
shift() 从数组中删除第一个元素,并返回该元素的值,更改数组的长度
push() 方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度
unshift() 将方法或一个元素多个添加到数组的开头,并返回该数组的新长度
reverse() 方法将数组中元素的位置颠倒,并返回该数组,改变原数组
slice() 方法返回一个新的副本对象,该对象是一个由 begin和end决定的原先的浅拷贝(包括begin,不包括end),原始序列不会被改变
sort() 方法用原地算法对数组的元素(看作字符串)进行排序,并返回数组。
splice() 方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。
toString() 返回一个字符串,表示指定的数组及其元素。
①typeof()函数
可以判断原始类型Undefined、Boolean、Number、String和Function
但Null和其他引用类型变量都会返回Object
②instanceof
用来判断一个变量是否是某个对象的实例,不能直接看出是什么类型
一般都是在typeof判断为object时才使用instanceof
③Object.prototype.toString.call()
可以通用的来判断原始数据类型和引用数据类型
但无法判断自定义类型
④constructor
返回对象相对应的构造函数
可使用num.constructor==Number判断一个变量是不是Number类型
①字符串转数组,反转数组,数组转字符串。
②新建空串,用charAt()方法从后往前遍历原字符串填到新串
③新建空串,原字符串挨个pop()后直接push()到新串中达到逆序效果。
原理只是在每个方法调用后返回this,使得链不断掉可以紧接着调用
示例如下,this始终指向A,不断链.
var A={
B:function(){
console.log("It's B")
return this;
},
C:function () {
console.log("It'C")
return this;
}
}
A.B().C()
相同点:
都是用于改变函数this指向;
第一个参数都是this所要指向的对象;
都可以利用后续参数传参。
不同点:
call和apply的区别仅是第二个参数不同:call的第二个参数是目标函数的第一个参数,第三个参数是目标函数的第二个参数,以此类推;而apply的第二个参数是一个目标函数参数的数组。
bind是返回对应函数,便于稍后调用;而call与apply是立即调用。
【ps】:多次 bind() 是无效的。更深层次的原因, bind() 的实现,相当于使用函数在内部包了一个 call / apply 。
其他方式参见JavaScript实现私有属性
function Person(name){
var _name = name;
this.getName = function(){
return _name;
}
}
var person = new Person('Joe');
alert(person._name); // undefined
alert(person.getName()); //'Joe'
50min。1v1。深挖项目,非常非常非常细节,非常非常重实践,对比感觉偏社招风格。基础问题、概念性的问题还是都能答,项目做得早的早就忘了的直接细问到用什么api直接宕机。不太友好,虽然也没有施压,做过的东西看不上,还一直被怼着问根本没实践过的部分就挺无力的。
1XX(信息性状态码)——接受的请求正在处理
2XX(成功状态码)——表明请求被正常处理了
1、200 OK:请求已正常处理。
2、204 No Content:请求处理成功,但没有任何资源可以返回给客户端,一般在只需要从客户端往服务器发送信息,而对客户端不需要发送新信息内容的情况下使用。
3、206 Partial Content:是对资源某一部分的请求,该状态码表示客户端进行了范围请求,而服务器成功执行了这部分的GET请求。响应报文中包含由Content-Range指定范围的实体内容。
3XX(重定向状态码)——需要进行附加操作以完成请求
1、301 Moved Permanently:资源的uri已更新,你也更新下你的书签引用吧。永久性重定向,请求的资源已经被分配了新的URI,以后应使用资源现在所指的URI。
2、302 Found:资源的URI已临时定位到其他位置了,姑且算你已经知道了这个情况了。临时性重定向,和301相似,但302代表的资源不是永久性移动,只是临时性性质的。换句话说,已移动的资源对应的URI将来还有可能发生改变。
3、303 See Other:资源的URI已更新,你是否能临时按新的URI访问。该状态码表示由于请求对应的资源存在着另一个URL,应使用GET方法定向获取请求的资源。303状态码和302状态码有着相同的功能,但303状态码明确表示客户端应当采用GET方法获取资源,这点与302状态码有区别。
ps:当301,302,303响应状态码返回时,几乎所有的浏览器都会把POST改成GET,并删除请求报文内的主体,之后请求会自动再次发送。
4、304 Not Modified:资源已找到,但未符合条件请求。该状态码表示客户端发送附带条件的请求时(采用GET方法的请求报文中包含If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since中任一首部)服务端允许请求访问资源,但因发生请求未满足条件的情况后,直接返回304。
4XX(客户端错误状态码)——表明客户端是发生错误的原因所在
1、400 Bad Request:服务器端无法理解客户端发送的请求,请求报文中可能存在语法错误。
2、401 Unauthorized:该状态码表示发送的请求需要有通过HTTP认证(BASIC认证,DIGEST认证)的认证信息。
3、403 Forbidden:不允许访问那个资源。该状态码表明对请求资源的访问被服务器拒绝了。(权限,未授权IP等)
4、404 Not Found:服务器上没有请求的资源。路径错误等。
5XX(服务器错误状态码)——服务器本身发生错误
1、500 Internal Server Error:貌似内部资源出故障了。该状态码表明服务器端在执行请求时发生了错误。也有可能是web应用存在bug或某些临时故障。
2、503 Service Unavailable:抱歉,我现在正在忙着。该状态码表明服务器暂时处于超负载或正在停机维护,现在无法处理请求。
根据是否需要向服务器重新发起HTTP请求将缓存过程分为两个部分,分别是强缓存和协商缓存。强制缓存优先于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match)。
强缓存: 不会向服务器发送请求,直接从缓存中读取资源,在chrome控制台的Network选项中可以看到该请求返回200的状态码,并且Size显示from disk cache或from memory cache。强缓存可以通过设置两种 HTTP Header 实现:Expires 和 Cache-Control。
Expires:缓存过期时间,用来指定资源到期的时间,是服务器端的具体的时间点。受限于本地时间,如果修改了本地时间,可能会造成缓存失效。
Cache-Control:(更强大完备且优先级更高) 可以在请求头或者响应头中设置,并且可以组合使用多种指令
协商缓存: 就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。主要有以下两种情况:①协商缓存生效,返回304和Not Modified;②协商缓存失效,返回200和请求结果
协商缓存可以通过设置两种 HTTP Header 实现:Last-Modified+If-Modified-Since 和 ETag+If-None-Match。
Last-Modified+If-Modified-Since:Last-Modified是这个资源在服务器上的最后修改时间,标记文件唯一性;浏览器再次请求这个资源会包含If-Modified-Since这个信息,服务器再次收到这个资源请求,会根据 If-Modified-Since 中的值与服务器中这个资源的最后修改时间对比。
ETag+If-None-Match:(在时间精度上高于Last-Modified) Etag是服务器响应请求时,返回当前资源文件的一个唯一标识(由服务器生成),只要资源有变化,Etag就会重新生成。浏览器在下一次加载资源向服务器发送请求时,会将上一次返回的Etag值放到request header里的If-None-Match里,服务器只需要比较客户端传来的If-None-Match跟自己服务器上该资源的ETag是否一致,就能很好地判断资源相对客户端而言是否被修改过了。
【补充】:用户行为对浏览器缓存的影响,指的就是用户在浏览器如何操作时,会触发怎样的缓存策略。主要有 3 种:
1、打开网页,地址栏输入地址: 查找 disk cache 中是否有匹配。如有则使用;如没有则发送网络请求。
2、普通刷新 (F5):因为 TAB 并没有关闭,因此 memory cache 是可用的,会被优先使用(如果匹配的话)。其次才是 disk cache。
3、强制刷新 (Ctrl + F5):浏览器不使用缓存,因此发送的请求头部均带有 Cache-control: no-cache(为了兼容,还带了 Pragma: no-cache),服务器直接返回 200 和最新内容。
通过React16新增的一个API叫做React.createContext()来实现的,我们调用React.createContext时可以传入一个参数,参数就是默认值,返回一个对象,含有一个Provider组件和一个Consumer组件,在需要使用context(上下文)的地方直接使用即可。
<div id="root"></div>
<script type="text/babel">
const {
Provider, Consumer } = React.createContext() //调用React.createContext返回一个Provider和Consumer组件
class Parent extends React.Component{
state = {
height:180}
render(){
return (
<div>
<button onClick={
e=>this.setState({
height:this.state.height+1})}>测试</button>
<Provider value={
{
height:this.state.height}}> //Provider组件内通过value设置contexxt
<Child></Child>
</Provider>
</div>
)
}
}
class Child extends React.Component{
render(){
return
<p>
<Consumer>{
val=>val.height}</Consumer>//子组件内通过Consumer来直接获取值,子节点是一个函数,参数是传递过来的值
</p>
}
}
ReactDOM.render(<Parent></Parent>,root)
</script>
存在跨域问题所以使用const xhr = new XMLHttpRequest()异步实现。数据包格式为json文件,拿到之后判断读取状态、parse解析、再渲染到网页中。
const xhr = new XMLHttpRequest()
xhr.open("GET", "http://127.0.0.1:8080/Page22", true)
//根据情况选择是否要随get请求发送用于身份认证的信息
xhr.withCredentials = false
xhr.send()
xhr.onreadystatechange = () =>{
/**
* 0 UNSENT- open()尚未被调用
1 OPENED- send()尚未被调用
2 HEADERS_RECEIVED- send()已被调用,并且头和状态可用
3 LOADING下载;- responseText的保持部分数据
4 - 的操作完成
*/
// eslint-disable-next-line
if(xhr.readyState == XMLHttpRequest.DONE){
// eslint-disable-next-line
if(xhr.status == 200){
let gotService = JSON.parse(xhr.responseText)
this.setState({
service: gotService
})
}else {
console.log(xhr.readyState + "---加载中")
}
}
render() {
const serviceShows = this.state.service.map((user, index)=>{
return (
<tr key={
index}>
<td>{
user.id}</td>
<td>{
user.username}</td>
<td>{
user.name}</td>
</tr>
)
})
return (
<table>
<tbody>
{
serviceShows}
</tbody>
</table>
)
}
组件不会被实例化,整体渲染性能得到提升
组件不能访问this对象
组件无法访问生命周期的方法
无状态组件只能访问输入的props,无副作用
——浏览器访问网站的过程
①在浏览器地址栏中输入网址
②浏览器通过用户在地址栏中输入的url构建http请求
③浏览器发起DNS解析请求,将域名转换为IP地址
④浏览器将请求报文发送给服务器
⑤服务器接收请求报文,并解析
⑥服务器处理用户的请求,并将处理的结果封装成http响应报文
⑦服务器将http响应报文发送给浏览器
⑧浏览器接收服务器响应的http报文,并解析
⑨浏览器解析html界面展示(渲染), 在解析html页面时 遇到新的资源需要再次发起请求
⑩最终浏览器展示出了html页面
——浏览器和服务端交互的六种方式
1.输入网址,敲回车
2.通过表单,点击登录/注册/提交
3.点击链接
4.js的location.href=""
5.浏览器在识别HTML的时候自动发起请求,例如识别到js文件的时候,发起请求下载js文件
6.AJAX
跨域由同源策略所导致,即规定不同源的策略无法进行资源交互,只有当协议(如http)、域名(如www.baidu.com)、端口(如8080)三者都一致时才算同源。跨域问题本质上是浏览器对于ajax请求的一种安全限制。
可通过CORS:跨域资源共享解决跨域问题。
挂载卸载过程
1.constructor()
2.componentWillMount()
3.componentDidMount()
4.componentWillUnmount ()
更新过程
1.componentWillReceiveProps (nextProps)
2.shouldComponentUpdate(nextProps,nextState)
3.componentWillUpdate (nextProps,nextState)
4.componentDidUpdate(prevProps,prevState)
5.render()
React新增的生命周期(个人补充)
1.getDerivedStateFromProps(nextProps, prevState)
2.getSnapshotBeforeUpdate(prevProps, prevState)
1v1。30min+20min。第一次hr没有经验,很多话术都不会,再加上有点压力面,答得太烂了,感觉很凉。
所有节点两两对比:O(n2)
所有节点两两对比再进行编辑需要遍历一次:O(n3)
所有的节点按层级比较,只会遍历一次:O(n)
React认为:一个ReactElement的type不同,那么内容基本不会复用,所以直接删除节点,添加新节点,这是一个非常大的优化,大大减少了对比时间复杂度。
分制管理:
master:主支
develop:阶段性成果分支
Feature branches:功能分支,分为前端和后端两大块
Release branches:用来发布新版本,因为没有项目迭代所以没太使用
Hotfix branches:修复紧急bug,没太使用
git命令
git clone:从远程仓库克隆一个版本库到本地
git branch:操作 Git 的分支命令。-m修改,-d删除
git checkout:检出命令,用于创建、切换分支等。-b创建并切换
git add:把要提交的文件的信息添加到暂存区中。
git commit:将依据暂存区中的内容来进行文件的提交。
git merge:合并分支。
git diff:比较版本之间的差异。
git pull:从远程仓库获取最新版本并合并到本地。
git push:把本地仓库的提交推送到远程仓库。
前后端分离+rest。数据传输方式:json。
为什么使用前后端分离:
前后端解耦
提高开发效率
精确定位bug
性能原因无法将分类算法一起打包放在前端
为什么选rest:
轻量,直接通过http,不需要额外的协议,通常有post/get/put/deletec操作。
面向资源,一目了然,具有自解释性。
数据描述简单,一般以xml,json做数据交换。
rest包含什么:
如果一个函数操作其他函数,即将其他函数作为参数或将函数作为返回值,将其称为高阶函数。高阶组件(high-order component)类似于高阶函数,接收 React 组件作为输入,输出一个新的 React 组件。高阶组件让代码更具有复用性、逻辑性与抽象特征。可以对 render 方法作劫持,也可以控制 props 与 state。
知识点在于浏览器缓存方面
let person = {
name: 'yhb',
age: 20,
address: {
province: '河北省',
city: '保定'
}
}
// 从对象 person 中找到 address 属性,并将值赋给变量 address
let {
address}=person
// 从对象 address 中找到 province 属性,并将值赋给变量 province
let {
province}=address
//也可简写为如下形式
let {
address:{
province}}=person
SASS是一种CSS的开发工具,提供了许多便利的写法,大大节省了设计者的时间,使得CSS的开发,变得简单和可维护。
只是必须先安装Ruby,然后再安装SASS。
允许变量($和#{})、计算、嵌套、继承(@extend)、重用代码块且可赋参(@mixin+@include)、插入外部文件(@import)、条件、循环、自定义函数(@function)
mark一下按时整理
设备rpx换算px:屏幕宽度/750,px换算成rpx:750/屏幕宽度;
iPhone5 1rpx = 0.42px 1px = 2.34px ;
iPhone6 1rpx = 0.5px 1px = 2rpx ;
iPhone6s 1rpx = 0.552px 1px = 1.81rpx;
这篇写得很好mark一下
匿名函数的作用:
1、通过匿名函数可以实现闭包,关于闭包在后面的文章中会重点讲解。在这里简单介绍一下:闭包是可以访问在函数作用域内定义的变量的函数。若要创建一个闭包,往往都需要用到匿名函数。
2、模拟块级作用域,减少全局变量。执行完匿名函数,存储在内存中相对应的变量会被销毁,从而节省内存。再者,在大型多人开发的项目中,使用块级作用域,会大大降低命名冲突的问题,从而避免产生灾难性的后果。
事件流:事件流分为三个阶段
(1)捕获阶段
(2)目标阶段
(3)冒泡阶段
捕获过程:1.window——>2.document——>3.body——>4.div——>5.text
目标过程:捕获过程的5
冒泡过程:6.text——>7.div——>8.body——>9.document——>10.window
事件捕获:首先window会捕获到事件,之后document、documentElement、body会捕获到,在之后就是body到dom元素一层一层的捕获到事件,有wrap div、inner p;
目标阶段:真正点击元素textSpan的事件发生了两次,因为在上面的JavaScript代码中,textSpan既在捕获阶段绑定事件,又在冒泡阶段绑定了事件,所以发生2次。
事件冒泡:和捕获阶段相反的事件一步一步地冒泡到window
(补充:冒泡为false、捕获为true)
利用事件冒泡的原理,子元素的事件会冒泡到父元素,可以只给父元素添加事件,通过事件目标判断元素。
优点:节省内存,动态添加的子元素也包含事件
父组件向子组件通讯:通过传props
子组件向父组件通讯:props+回调
10.props和state
状态和props主要的区别在于props是不可变的,而state可以根据与用户交互来改变。这就是为什么有些容器组件需要定义state来更新和修改数据。而子组件只能通过props来传递数据。
都是增强型循环
for in是遍历下标,取值用arr[index](es5)
for of是遍历值,取值直接value(es6)
创建一个新对象
将新对象的_proto_指向构造函数的prototype对象
将构造函数的作用域赋值给新对象 (也就是this指向新对象)
执行构造函数中的代码(为这个新对象添加属性)
返回新的对象
var Obj = {
};
Obj._proto_ = Person.prototype();
Person.call(Obj);
meta标签提供关于 HTML 文档的元数据。它不会显示在页面上,但是对于机器是可读的。可用于浏览器(如何显示内容或重新加载页面),搜索引擎(关键词),或其他 web 服务。
1、客户端发出https请求,报文中会包含客户端的TLS版本,和加密列表(主要包含加密算法、密钥长度、压缩算法)
2、服务器收到请求,会从中刷选出一个加密列表和一个CA认证的证书,其中包含公开密钥加密的公钥、证书的域名范围等信息。
3、客户端在接收到这些数据,验证证书可用后,产生随机数并用公钥加密传给服务器。共享密钥由这个随机数生成。
4、服务器接收到数据后用公钥解密得到随机数,此时双方都有共享密钥了。
5、传输数据
6、客户端发送Finished报文,对前面整体数据进行校验。
7、服务器校验完成后返回Finished报文。
8、客户端收到Finished报文后,TLS连接就完成了就用共享密钥传递数据。
为解决回调函数地狱而提出,相当于对回调进行了包装,允许将回调函数的嵌套,改成链式调用。
Promise 构造函数包含一个参数和一个带有 resolve(解析)和 reject(拒绝)两个参数的回调。在回调中执行一些操作(例如异步),如果一切都正常,则调用 resolve,否则调用 reject。
promise
原型:
原型是一个属性可以被继承的对象,原型也可以有自己的原型。
每个对象都有_proto_属性,并且指向它的原型对象
每个构造函数都有它的prototype原型对象
prototype原型对象里的constructor指向它的构造函数
new一个构造函数会形成它的实例对象
原型链:
每个对象都可以有一个原型,这个原型还可以有它自己的原型,以此类推,形成一个原型链。
什么时候使用原型链:
找特定属性的时候,先去这个对象里去找,如果没有的话就去它的原型对象里面去,如果还是没有的话再去原型对象的原型对象里去寻找… 这个操作就是被委托在整个原型链上。
原型链是有终点的,不会一直找下去。当Object.prototype.proto === null时,查找结束,返回undefined。
1)三角形
当height:0,width:0时,边框呈现如下:
只要隐藏掉不需要的三角形,保留需要的就行,不需要的设置为透明transparent;
如果浏览器不支持透明,可设置border-style:dashed(点)
.triangle{
height: 0;
width: 0;
border: 10px solid transparent;
border-bottom-color: red;//下边框不透明,其余透明
}
2)自适应正方形
.square {
width: 50%;
height: 0;/*这个height设置为0,如果元素有内容,则溢出到padding-bottom上面*/
/*如果元素这时候未设置height(:0),则默认height:auto;
如果有内容(子元素)的话,将撑开高度height(不为0的值),则垂直>水平背景了*/
padding-bottom: 50%;/***这里不能用top,因为用top,且高度为0,如果有内容,则溢出到容器外了***/
background: red;/***背景颜色默认是从元素的border开始渲染绘制的***/
}
3)半圆
【补充】css样式上下左右顺序
margin: 20px 30px 40px 50px; 代表:上—右—下—左
margin:20px 20px 30px; 代表:上—左右—下
margin:20px 30px; 代表:上下—左右
maring:20px; 代表:上下左右
.half-round{
width: 100px;
height: 50px;
border:1px solid black;
background-color: blue;
border-radius: 100px 100px 0 0;/*左上—右上—左下—右下*/
}
4)圆
.round{
width:100px;
height:100px;
border:1px solid black;
background-color:blue;
border-radius:100px;
}
var ProxySingletonCreateDiv = (function () {
var instance;
return function (html) {
if (!instance) {
instance = new CreateDiv(html);
}
return instance;
}
})();
var CreateDiv = function (html) {
this.html = html;
this.init();
};
CreateDiv.prototype.init = function () {
var div = document.createElement('div');
div.innerHTML = this.html;
document.body.appendChild(div);
};
var a = new ProxySingletonCreateDiv('sven1');
var b = new ProxySingletonCreateDiv('sven2');