理解(解决问题, 控制反转设计原理, 依赖问题)
依赖注入是一种编程技能(去掉)new, 降低component 与service 耦合)
控制反转是一种设计模式: 控制是对程序流程的控制, 逆转是将控制权从程序员手中交给外部框架。
@Optional 找不到就给null,
@Host 相当于 self
@Self 从自身找
@SkipSelf 父组件找
(几种方式):
媒体查询, flex 布局, 流体布局;
自适应布局与响应布局的区别:
自适应布局: 多套页面(静态页面)需要根据不同场景开发, 静态页面, 页面元素不随窗口大小的调整发生变化; 位置会改变,但大小不会改变;使用媒体查询时, 同一设备或固定布局;
响应布局:根据检测屏幕分辨率,客户使用不同的代码(只需开发一套页面),结合流布局和弹性布局+媒体查询;=流布局+自适应布局; 每个分辨率下都会有布局风格, 即大小和布局都会发生变化
(如何形成)
W3C标准盒模型: width = content padding border margin;
IE盒子模型(怪异模型): width content padding border;
:
选择器: nth-child(n), last-child, only-child, p~ul:每一个前面都有p元素ul
新样式:border-radius, box-shadow, border-image
背景:background-clip(背景画区),background-origin(左上角对齐),backgroun-break
文字: word-warp, text-overflow,text-shadow,text-decoration,
颜色: rgba, hala(色相, 饱和度、亮度、 透明度 )
过渡: transition: css属性, 花费时间, 效果曲线(ease),默认延迟;
转换: transform, transform-origin
动画: animation
渐变:linear-gradient(线性渐变),radial-gradient(径向渐变)
flex 布局, 栅格布局...
:
flex-direction, flex-wrap,flex-flow,justify-content, align-items,align-content, flex-grow, flex-shrink,
字体系列属性, 文本系列,元素可见性(visibility), 表格布局属性,列表属性,光标属性,
字符串, 数字, 布尔, 对空, 未定义,symbol, 引用数据类型: 对象, 数组, 函数
基本数据类型: 放在栈内存中,
引用类型:地址:数据, 地址放在栈内存中, 堆内存中放置数据
意外的全局变量;被遗忘的定时器或回调函数;脱离DOM的引用, 闭包,
利用 Map 对象和数组 filter 方法;Set对象和数组Array.from();Set 扩展运算符
转字符串,判断是否=={}; for in 判断; jq 的 isEmptyObject(); getOwnPropertyNames() 获取属性名的数组判断长度; Object.keys();
:(事件捕获阶段, 目标阶段, 事件冒泡阶段)
pending(未决), fulfilled(成功), rejected(拒绝)。
作用: 异步计算;按预期顺序执行, 返回预期结果;可在对象之间传输和操作队列,
.then(), .catch(), 多处理时, 一个catch, 直接进入后面, 状态变为reject
.all(), 一切成功都会成功, 否则就会失败, 第一个返回rejected的对象;
.race(), 所有的成功都会变成 resolve(成功)状态;
vm视图模型层,model 层, view 层, 前后端更好的分离;
{ {}}, v-bind:html == :html, v-html,
双向数据绑定: Object.defineProperty(), 数据劫持, 遍历数据或递归对象;
通过动态重写与用户互动。
只在页面初始化时加载html, js, css。页面加载完成后, 不会重新加载或跳转, 通过路由机制可以实现html内容切换。
优点: 桌面应用的即时性, 网站的可移植性, 用户体验好, 快, 内容的变化不需要重新加载整个页面;良好的前后分离, 分工明确;
缺点: 不利于搜索引擎的抓取;首次渲染速度比较慢;
优化资源加载和页面渲染;
PWA模式:
输入url的过程:
1. 浏览器输入URL 按下回车; 2. 检查是否为缓存, 比较是否过去; 3. DNS 解析当前URL 的IP; 4. 根据IP建立TCP连接 (三次握手); 5. HTTP发送请求; 6. 服务端接收处理请求, 浏览器接收HTTP响应; 7. 渲染页面, 构建DOM树; 8. 关闭TCP连接(四次挥手);
计算首屏时间;
加载缓慢的原因:
网络延迟问题; 要求资源是否过多; 资源文件体积是否过大; 资源是否重复发送加载请求;加载脚本时, 渲染内容堵塞;
优化方法:减少入口文件体积(懒加载, );本地缓存静态资源(localStorage); UI按需加载框架(antd); 图片资源压缩();图片懒加载;组件重复包装; 开启GZip压缩; 使用SSR, 部分数据在服务端渲染;
是一个Object 对象, 与真实dom 一对应,直接操作DOM会影响用户体检,卡顿, 影响性能, 一次性计算。
优点: 保证性能下限; 无需手动操作dom;跨平台;
缺点: 无法进行极端优化;
工厂模式: 不在乎内部结构, 只需输出结果;
单例模式: 只允许一个例子;
适配器模式: 转换;
代理模式:事件代理;
发布-订阅模式:
策略模式; 分别判断
迭代模式: 指提供顺序访问的方法;
1. display:none;2. overflow: hidden;3. 设置元素的宽高盒属性为 0;4. 定位隐藏; 5. 设置元素透明度为 0; 6. 通过visibility 隐藏; 7. z-index: 0;
1. 将获得浏览器TML文本解析成dom树;2. 处理css标记, 构成层叠样式表CSSOM模型;3. 将DOM与CSSOM合并成渲染树; 4. 渲染树的每个元素都是计算过的 ,称为layout, 使用一种流式处理的方法,只需要一次绘制操作就可以布局所有元素; 5. 将渲染树的各个节点绘制到屏幕上, 这一过程称为绘制; painting;
DOM树在构建的过程中可能会因为js或css的加载而堵塞; css 解析与dom解析同时进行, 但是不能与js执行同时进行;渲染树与dom树不完全对应, display:none的元素不在渲染树中, 但是在dom树中;visibility:hidden 的元素在渲染树中;
渲染树布局:布局阶段输出的就是我们所说的盒子模型, 但是使用了定位, float 的会脱离文档流,即脱离render tree;
渲染树绘制:浏览器会遍历渲染树, 该工作是由浏览器的UI后端组件完成的 ;
浏览器组件结构:
渲染阻塞: js阻塞,js修改dom,或者修改css样式, 会导致DOM树或者CSSOM树解析暂停, 等脚本执行结束才会继续构建。 使用 defer或者 async 异步执行, 后续追加。css 阻塞:渲染树需要等DOM 树与CSSOM树都解析完,才能进行下一步 , 所以在css样式表没有解析完的时候页面是空白的 ; 样式解析是从右往左
display:none 回流;
visibility:hidden 重绘;
reflow:浏览器布局发生变化,一般只要用户发生交互就会触发回流;
repaint:颜色字体背景边框颜色能发生变化需要重新绘制触发重绘;
引起reflow:1. 页面第一次渲染(初始化);2. resize浏览器窗口变化; 3. DOM树变化(增删改查);4. Render树变化(padding 等); 5. 获取元素的某些属性(offsetLeft等, scrollTop等,clientHeight等, getComputedStyle());
引起repaint:回流必定引起重绘, 字体颜色, 背景等,字体大小会触发回流;
如何减少回流重绘的次数:1. 用tranform做形变和位移减少reflow; 2. 避免逐个修改节点样式, 尽量一次修改; 3. 使用documentFragment将需要多次修改的dom元素缓存, 最后一次append 到真实dom 中; 4. 可以将需要修改的元素display:none, 操作完再显示;5. 避免多次读取某些属性; 6. 通过绝对位移使复杂的节点脱离文档流, 形成新的Render Tree,降低回流成本;
渲染优化建议: 1. 不能忘记文档编码类型; 2. 样式在head之前, js脚本在body结束之前; 3. 优化css选择器, 减少嵌套层; 4. dom的读写操作应该归类写在一起; 5. 尽量使用tranform;6.尽量操作离线dom; 7. 复杂dom操作先display:none; 8. window.requestAnimationFrame(), window.requestIdleCallback().
js 是一个单线程, 如何执行任务):
Event Loop: 事件循环, 指浏览器或者node环境为了解决js单线程运行时不会阻塞的一种机制,实现异步的原理, js本身没有异步操作,是由其宿主提供的。
js在解析代码的时候, 同步任务放到执行栈中, 异步任务放到任务队列中, 优先执行执行栈,然后再执行任务队列,碰到同步与异步任务的时候都如此处理, 形成事件循环, 所有执行都遵循先进先出;
Event Loop 负责其他线程与主线程进行通信(称为消息线程)
函数入栈, 执行到异步任务 ---> WebAPIs, 接着执行同步任务, 直到 Stack 为空,在此期间, WebAPIs把回调函数放入 CallbackQueue 等待, Stack 空了之后, 就把第一个任务放进去执行
任务队列中又分为微任务与宏任务。Event Loop 在执行或协调各种任务时, 也将任务分为Task Queue(宏任务) 和Mirco Task Queue(微任务)。
常见宏任务: 鼠标IO操作;所有的网络请求; SetTimeout, setInterval, setImmediate;
常见微任务:Promise( then,catch,finally);MutationObserver; Process.nextTick
执行顺序:
1. 主线程按顺序执行所有代码; 2. 同步任务直接进入执行栈立马执行; 3. 所有的异步任务放入 WebAPIs (任务队列)中; 4. 异步任务有结果之后注册回调函数,等待主线程执行; 5. 主线程执行结束之后,获取异步的回调函数并执行; 6. 回调函数作为任务从头开始;
, watch , computed, v-bind, solt,v-if 与v-show 的区别
beforeCreate -> created - > dom加载 -> beforeMounte ->mounted -> beforeUpdate -> updated -> activated -> deactivated ->beforeDestroy -> destroy
计算属性computed 与 watch 的区别:
computed: 1. 支持缓存, 依赖数据发生变化才会计算; 2. 不支持异步,异步操作无效; 3. 默认会走缓存, 所有数据都是依赖于data中声明的变量或者props父组件传递的数据而计算; 4. 若一个属性是由其他属性计算而来,这个属性依赖于其他属性, 一对一或者一对多;5. 如果属性是函数, 默认走get方法 , 当属性变化时, 调用set方法。
watch: 1. 不支持缓存, 数据变化会直接触发操作; 2. 支持异步; 3. 监听的函数接收两个参数, 第一个是新值, 第二个是旧值; 4. 当一个属性发生变化, 需要执行对应的操作; 5. 监听数据必须是data定义的或者父组件传递的props值; immediate: 组件加载立即触发回调函数执行。
:拦截器, 越权
:
:
优点: 1. 解决加载缓慢的第三方内容等问题; 2. Security sandbox;3. 并行加载脚本;
缺点:1. 会阻塞主页面的onload 事件;2. 即时内容为空,加载也需要时间; 3. 没有语意;
:
1XX: 请求信息;
2XX: 成功状态;
3XX: 重定向;
4XX:客户端错误;
5XX:服务器错误;
204:服务器成功处理, 但未返回内容; 206: 是对资源一部分的请求; 301: 永久性重定向; 302: 临时性重定向;303: 查看其他地址; 304: 客户端通常会通过缓存访问资源(未修改); 307: 同302; 400: 客户请求中存在语法错误, 服务器无法理解; 401: 请求要求客户的身份认证; 403: 服务器可以接收客户端的请求, 但是拒绝执行此请求;404: 您说请求的资源无法找到, 一般写法有误; 500: 服务器内部错误, 无法完成请求; 501: 服务器不支持请求的功能; 503: 由于超载或者维护, 服务器暂时无法处理;
(HTTP缓存机制):
缓存的位置:
Service Worker: 独立线程, 传输协议必须是https, 可以让我们自由控制缓存的文件, 如何匹配等问题, 并且是可持续性的。
Memory Cache: 内存中的缓存, 一旦关闭tab页, 缓存也会被释放,
Disk Cache:磁盘中的缓存,读取速度慢,
Push Cache: 只在会话中存在, 一旦结束就释放。
缓存策略: 强缓存和协商缓存, 并且缓存策略都是通过设置Http Header 来实现的。
注: 1. 浏览器每次发起请求,都会先在浏览器缓存中查找该请求的结果以及缓存标识。
2. 浏览器每次拿到返回的请求结果, 都会把该结果和缓存标识存到浏览器缓存
强缓存: 直接从缓存中获取资源,查看network 状态200的size, 为 from disk cache或者from memory cache。可以通过设置 Http Header为 Cache-Control或者 Expires。
Expires:缓存过期时间,用来指定资源的到期时间,一般是服务器的时间。受限于本地时间, 若修改本地时间, 则缓存失效。
Cache-Control: Cache-Control:max-age=300, 表示在五分钟之内, 再次加载资源,就会命中缓存。
Cache-Control 优先于Expires,在某些不支持http1.1的环境, Expires起作用,强制缓存的判断依据来源于是否超出某个时间,并不会关心服务器文件是否更新。
协商缓存: 强缓存失效之后, 浏览器携带缓存标识请求服务器, 服务器决定是否使用缓存的过程,生效返回 304 或者 Not Modified, 失效返回 200 和请求结果。可以通过设置 Http Header 实现:Last-Modified 和 ETag。
Last-Modified: Fri, 22 Jul 2016 01:47:00 GMT
服务器返回资源的同时 , 在response header 中添加 last-Modified :XX, 浏览器缓存资源与header,下次请求资源的时候, 浏览器监测到有 last-Modified , 于是添加 If-Modified-Since, 值是上次 last-Modified的值, 服务器会根据这个值去比较, 若没有变化 , 则返回304,直接从缓存读取。
本地打包缓存文件, 也会被默认为修改; 而且时间以秒计, 若是修改时间小于秒,则会被命中缓存。
ETag 和 If-None-Match : Etag 是服务器响应时,返回资源中的一个唯一标识(由服务器生成),只要资源有变化 , Etag就会重新生成。浏览器在下一次请求时, 会将Etag的值放入 If-None-Match中, 服务器通过比较决定是否返回304,
比较: 负载均衡的服务器, 各个服务器生成的可能会不一样。性能上Last-Modified优于Etag, 优先级(服务器优先选择 Etag)。
如果浏览器没有设置缓存, 采用启发式算法:通常会取响应头中的Date减去Last-Modified的10%作为缓存时间。
实际应用: 1. 频繁变动的资源:(Cache-Control: no-cache), 再配合服务器的Last-Modified 和Etag; 2. 补偿变化的资源: Cache-Control: max-age=31536000(一年);3. 用户行为。
32. mouseover,mouseout,mouseenter, mouseleave
一般使用mouseenter, mouseleave, 移入之后只会触发一次
14. WebSocket:
网络通信协议(服务器推送技术)。
特点: 1. 建立在TCP协议之上; 2. 与Http协议有着良好的兼容性,默认端口是 80, 443; 3. 数据格式比较轻量级,性能开销小,效率高; 4. 可以发送文本,也可以是二进制;5. 没有同源限制, 客户端可以与任意服务端通信; 6. 协议标识符是 ws(加密,wss)服务器网址就是URL;
1. 创建实例:
ws = new WebSocket('ws://localhost:8080');
2. readyState(实例对象当前状态)connection: 0, 正在连接;open:1,连接成功;closing:2,正在关闭; closed:3,连接关闭或者打开失败。
3. websocket.open = function(); // 连接成功的函数回调;
4. websocket.onclose = function(); // 关闭后的回调函数;
5. websocket.onmessage = function(); // 收到服务器数据后的回调;
6. websocket.send = fucntion(); // 客户端发送数据;
备注信息:
1. webworker js 线程问题, 创建多线程,一旦创建,就会一直运行, (注)同源限制;DOM限制(navigation, location);通信联系(Worker线程和主线程不在一个上下文环境, 不能直接通信,需要通过消息); 脚本限制;文件限制;
2. html 新特性: webworker, websocket, geolocation, 音频, 视频, 表单控件, 拖拽API;
3. css3新特性: canvas,媒体查询, rem, 圆角, 阴影,text-shadow,渐变,transform , rgba。
4. BFC:块级格式化上下文。
5. 兼容性: 不同浏览器margin 与padding 不一致, 需要统一设置; chrome 小于12px会默认显示12px, 可通过 -webkit-text-size-adjust:none 解决;
6. 箭头函数的特点: 不需要function创建函数; 省略return 关键字; 改变this指向;
7. 同源策略: 协议, 域名, 端口相同,是一种安全策略, 只能读取同一个窗口的属性;
8. 闭包: 有权访问另一个函数的变量, 函数内部创建函数 。 特点: 函数嵌套函数; 函数内部可以引用外部的变量和参数; 参数 和变量不会被垃圾回收机制回收。 使用不当会增大内存使用, 造成内存泄漏。
9. 垃圾回收机制: 标记清除法; 引用计数法;
10. 原型链: 每个对象都有一个prototype对象。
11. vue
MVVM: model(数据模型, 数据,业务逻辑), view(UI视图, 负责数据的展示), viewmodel (负责监听model中数据的改变并且控制视图的更新,处理用户交互操作)。 Model 与 viewModel中有着数据双向绑定的联系。
Vuex:状态管理模式,核心是store(仓库),即是一个容器。 vuex的状态时响应式的,当 vue组件从 store中读取数据时,若是store的状态发生变化 , 那么相应的组件也会更新; 改变store的状态唯一途径就是commit (mutation)显式的提交, 这样可以方便跟踪每一个状态的变化。
State: 基本数据, 可以定义了应用状态的数据结构, 可以设置默认的初始化状态。
Getter: 从基本数据派生的数据, 允许组件从store获取数据。
Mutation:同步函数,修改数据的唯一方法。
Action:包裹mutation,使之异步,用于提交mutation
Module:模块化vuex,可以将单一的store拆分为多个store保存在单一的状态树中。
vue的单向数据流: prop使得父子组件之间形成了单向数据流, 但是反向不行;为了防止子组件修改父组件的属性。 父组件每次更新时, prop的所有值都会刷新为最新的值。子组件要修改时, 使用$emit 传递数据。
vue 组件中的data 为什么是一个函数: 组件是会复用的, 并且js 的对象使用的是引用地址。 如果使用对象的话无法做到作用域隔离, 子组件之间会相互影响。
new vue 中的data是一个对象 , 因为new vue 的实例 不会被复用。
vue 组件间通信:
1. props / $emit 父子组件之间通信;2. ref 与$parent / $children 父子组件; 3. EventBus($eimt / $on) 父子,隔代, 兄弟组件: 通过创建一个空的vue实例作为事件中心,用来触发事件和监听时间。 4. $attr / $listeners 隔代组件。 $attr:v-bind=“$attr”, 当组件没有声明 props时使用。$listeners:父作用域中的v-on事件监听器; 5. provide / inject 隔代通信:祖父组件提供provide, 子组件中使用inject注入变量,解决跨级组件通信,建立了一种依赖注入与主动提供的关系。 6. vuex 父子, 隔代, 兄弟;
SSR: 把html在服务端渲染完成直接返回给客户端。
优点: SEO方便(搜索引擎工具); 首屏加载的更快;
缺点: 开发条件限制; 服务器负载;
vue-router路由模式: history,hash, abstract
hash:使用url hash值做路由,支持所有浏览器;
history:依赖HTML5 History API和服务器配置;
abstract: 支持所有js的运行环境;
es6 新语法:
1. 箭头函数,this,2. let const; 3. 增加了 Classes 类的概念; 4. 解构赋值; 5. 对象字面量扩展; 6. 模板字符串; 7. interators 迭代器; 8. Generators; 9. for of, for in; 10. Map, Set, (Set 对象是一组不重复的值 ) 10. Proxy 监听对象身上发生的事情 , 并且执行一些操作; 10. Symbol 值是唯一的;11. promise;
promise 链式
angular 数据双向绑定原理;
less
rem 布局的原理
前端框架 数据双向绑定的原理
回调地狱
js 工程性的内容 模板
http协议(3家)
请求的方法, get post put 不同点
vue 为什么做了单向数据流 props, 流向混乱, 被谁修改,
v-for , key的优缺点
计算属性
指令修饰符
虚拟加载, 多条数据的渲染优化,
es6 find 与foreach 的区别
promise async awite(语法糖), 捕获异常处理,
websocket, ws 与http 协议的不同
localStorage, sessionStorage
url 里面的 # 号谁来解析
作用域与作用链的区别
闭包
相同点: 改变this的指向, 第一个参数是this指向的对象, 如果第一个参数是null或者undefined, 则不改变this指向。
不同点:
1. apply 与 call 可以对函数直接进行调用, 但是 bind 需要手动调用
2. 传参方式不同, call 与bind 传递的参数是一一对应的 ,而apply传递的是一个参数(数组元素与方法内的参数一一对应), bind 也可以在调用的时候传参;
常见使用: 1. 将类数组转换成真数组,(类数组: 有length属性与数值下标属性,但是不具有数据的方法, 是一个Object);2. 获取无序数组的最大最小值;3. 合并数组;4. 判断数组是数组;
new 关键字
1. 创建一个对象; 2. 将构造函数的作用域赋给新对象(this 指向这个对象); 3. 执行构造函数中的代码(为对象添加属性); 4. 返回新对象
rxjs:
new Observalbe 定义流, 通过.subscribe() 启动; subscribe 不是订阅,而是启动这个流,也可以多次启动, 之间互不干扰; unsubscribe 终止流
Observalbe 定义了要生成一个什么样的数据;
subscribe:接受一个observer 数据,并开始产生数据, 该方法的返回值是 subscription, 存储了这个已经开始的流,并且具有 unsubscribe
Subscription = Observable.subscribe(observer) observable: 随着时间产生的数据集合,可以理解为流,其subscribe方法可以启动该流 observer: 决定如何处理数据 subscription: 存储已经启动过的流,其unsubscribe方法可以停止该流
手机适配问题: 300ms的延迟问题, fastclick, border-radius与overflow 不能一起使用
前端工程化: 模块化, 组件化, 规范化,自动化;--prod --build-optimizer=false