文章目录
- 面-什么是SEO
- 面 - cookie / localstorage / sessionstorage的区别
- 面 - promise面试题
- 面 - 柯里化函数
- 面 - 函数节流
- 面 - 函数防抖
- HTML / CSS 知识点
- 1、讲讲盒模型(蚂蚁金服 2019.03 招行信用卡 2019.04 美团 作业帮)
- 2、根据盒模型解释边距重叠(蚂蚁金服 2019.03 图森未来)
- 3、 宽高比4:3自适应 (蚂蚁金服 2019.03 )
- 4、css选择器的优先级( 百度前端 搜狐 美团 拼多多 VIVO)
- 5、css水平居中 (蚂蚁金服、百度前端、字节跳动)
- 6、CSS3 的 flexbox(弹性盒布局模型)以及适用场景 (猿辅导)
- 7、如何画一个三角形 (星环科技)
- 8、让一个图片无限旋转(蚂蚁金服 2019.03)
- 9、display 有哪些值?说明他们的作用?
- 10、position 的值?
- 11、为什么要初始化 CSS 样式
- 12、简要介绍一下CSS3的新特性
- 13、元素的显示与隐藏
- 14、`display: none`与`visibility: hidden`的区别
- 15.如何让一个不设宽高的div,垂直水平居中
- 16.什么是BFC
- 17.css reset 浏览器样式重置
- 18.常用的几种开发布局方式
- 19-兼容问题,渐进增强和优雅降级
- 20-设置p标签属性,ie6以下为黑。ie7以下为红
- 20-html/xhtml/xml
- 21-对比一下div+css和table布局
- 22-console
- 23-为什么利用多个域名来提供网站资源会更有效
- 24-谈谈以前端角度出发做好 SEO 需要考虑什么?
- 25-rgba()和 opacity 的透明效果有什么不同?
- 26 - sass和less
- 27-css3动画和js动画区别
- 28-css3和html5新特性
- **1、CSS3 新特性有哪些?**
- 2.**html5 有哪些新特性、移除了那些元素?如何处理 HTML5 新标签的浏览器兼容问题?**
- 支持 HTML5 新标签:
- 29-image 和 canvas 在处理图片的时候有什么区别?
- 30-HTML5中的本地存储介绍一下
- 31- margin塌陷解决方式
- 32- 清浮动方法
- 33- flex
- 34- 常见的布局方式
- 35-css中的1px问题
- 36- CSS实现水平垂直居中
- 37- 层叠上下文和层叠等级
- 38- 移动端的1px
- js知识点
- 面 - js对象隐形转成原始数据类型
- 面 - 基础类型使用方法
- 1.数据类型和方法
- 1-1 操作数组方法
- 2- string对象
- 2.操作符
- 5.类和实例和继承
- 原型和原型链
- 7. ES高级
- 8- DOM
- 面 - onload 和 onDomContentLoaded的区别
- 1- 元素查找
- 2- 事件流
- 3- 事件对象
- 9- BOM
- Location对象
- History对象
- Navigation对象
- window对象
- 移动端dom
- 10- js的执行机制
- 10-1 编译过程
- 10-2 代码执行过程
- 10-3 词法作用域/函数作用域/块作用域和闭包
- 10-4 预解析
- 10-5 this
- 面 - 手写new
- 面 - 手写call()
- get和post 的区别
- 面试题
- 3.防抖和节流的区别是什么?怎么实现?
- 4.深拷贝和浅拷贝有什么区别?你能实现一个深拷贝吗?
- 浅拷贝实现 , 只拷贝当前基本属性的值,不会拷贝复杂属性的值 ,俗称:只拷贝地址,不拷贝内容
- 深拷贝实现 拷贝当前的值,复杂属性也一并拿来,拷贝全部属性值,换个地址而已
- 8.实现一个new函数
- 9.箭头函数和普通函数的区别是什么?
- 10.实现一个promise
- 11.promise、async/await、setTimeout的区别是什么?
- vue知识点
- 面- 介绍一下什么是SSR
- 面-vue的跨平台是如何做到的
- 面 - 文件上传的几种方式,聊聊大文件上传
- 面 - 组件设计和状态设计
- 1-vue的使用
- 1-1 插值表达式
- 1-2 指令
- 1-3计算属性 和 过滤器 和 监听属性
- **计算属性** - 多个数据影响一个数据
- 监听属性 - 一个数据影响多个数据
- 每个的使用场景
- 1-4 生命周期
- 1-5 事件监听器
- 1-6 内置组件
- 2-vue高级特性
- 2-1 .$nextTick
- 2-2 组件的name属性 - 递归组件
- 2-3 组件通信
- 面--父传子的生命周期
- 面--父组件监听子组件的生命周期
- 2-3 slot插槽
- 面- 如何在vue中提取可复用的组件
- 2-4 动态组件
- 2-5 异步组件
- 2-6 缓存组件 keep - alive
- 2-7 mixin
- 2-8 自定义指令
- 3-vue底层原理
- 3-1组件化(vue核心)
- 面--说说组件化工程化和模块化
- 3-2响应式(
- 3-3 vdom 和 diff
- 面- 为何要加上key
- 3-4 模板编译
- 3-5 组件更新 和 渲染过程
- 3-6 前端路由原理
- 面- 如何实现vue-router切换页面后,保持在页面顶部/保持原先位置不变
- 4-相关插件
- 4-1 axios工具包
- 面--axios如何解决跨域问题?
- 4-2 vuex
- 核心
- 面-- 页面刷新的时候数据丢失
- 面 - vuex实现双向绑定
- 4-3 vue-router
- 1-使用步骤
- 2- 编程式导航
- 3-路由元信息
- 4-导航跳转流程
- 5- 获取路由跳转的信息
- 面 - 如何监听路由参数的变化
- 面 - 使用动态路由切换时候,组件没有变化,不会触发生命周期函数
- 面 - 实现路由解耦
- 4-4 vue-loader
- 5- vue的性能优化
- 5-1 代码层面的优化
- 5-2 Webpack 层面的优化
- 5-3 **基础的** Web 技术的优化
- 面- vue如何优化首屏加载速度
- React 知识点
- 1- react的使用
- 1-1 创建react元素的方式
- 1-2 jsx{ }嵌入式表达式
- 1-3 条件渲染
- 1-4列表渲染
- 1-5 组件
- 1-6 事件
- 1-7 组件通信
- 1-8 生命周期
- 1-9 setState()
- 2- React 高级特性
- 2-1高阶组件(公共逻辑代码的抽离,minin已经弃用)
- 2-2 render - props (公共逻辑代码的抽离,mixin已经弃用)
- 2-3 Portals 传送门
- 2-4 异步组件
- 2-5 性能优化
- **代码层面优化**
- Webpack 层面的优化
- Web 技术的优化
- 2-6 组件懒加载
- 3- React 核心原理
- 3-1函数式编程
- 3-2 JSX编译
- 3-3 组件渲染过程 和 更新过程
- 3-4 合成事件机制
- 3-5 setState 和 batchUpdate机制
- 面 - React和vue对比
- webpack知识点
- 1. 什么是webpack,webpack的运行原理,如何打包 (字节跳动)
- 2.什么是bundle,什么是chunk,什么是module?
- 3.什么是Loader?什么是Plugin?
- 4. 有哪些常见的Loader?他们是解决什么问题的?
- 5. 有哪些常见的Plugin?
- 6.webpack的构建流程是什么?从读取配置到输出文件这个过程尽量说全
- 7.如何利用webpack来优化前端性能?
- 8. 如何提高webpack的打包速度?
- 9. 介绍模块化发展历程
- 10.webpack 热更新原理
- 11-介绍一下babel
- NODEJS知识点
- 1.模块分类
- 2.node模块类型
- 3-中间件
- 4-node事件循环机制 和 浏览器的事件循环机制
- 4-1 浏览器的事件循环机制
- 小程序
- 面 - 小程序开发和vue开发的区别#$
- 1-文件架构
- 2- 双线程模型
- 3- 小程序执行流程
- 浏览器输入url后发生了什么(网络 / 浏览器)
- 基本流程
- 1.DNS地址查询
- 2.TCP连接
- 3.发送HTTP请求
- 4.服务器处理请求,以及响应
- 5.浏览器根据响应渲染页面
- 6.tcp连接结束
- 1-DNS地址查询
- 1.1什么是DNS
- 1-2 DNS查询
- 1-3 DNS中的安全问题
- 1-4 DNS中的网络性能优化
- 2-TCP连接
- 2-1什么是tcp
- 2-2 三次握手和四次挥手
- 1.**三次握手**
- 2.为什么要三次握手?
- 3.四次握手
- 4.为什么要四次挥手
- 5超时和重传
- 6-tcp的可靠性如何保证
- 3-发送HTTP请求
- 3-1.什么是HTTP协议
- 3-2.HTTP连接方式
- 3-3.HTTP报文
- 1-报文格式
- 2-请求方式
- 3-常见的状态码
- 3-4-HTTP版本
- 3-5-HTTPS
- 1.**什么是HTTPS**
- **2- HTTPS功能实现**
- 1.内容被窃听问题 - 加密
- 2.报文被篡改 - 数字签名
- 3-通信方身份伪装 - 数字证书
- 3-4-带宽和延迟
- 4- 浏览器渲染页面
- 4-1浏览器组成
- 4-2 浏览器如何解析资源渲染页面
- 1.渲染引擎将html和css文档解析成语法树
- 2.渲染引擎将css语法树和html语法树结合成渲染树
- 3.渲染引擎和js引擎
- 4.触发浏览器的paint事件,根据渲染树计算元素位置,绘制
- 5.回流和重绘
- **浏览器缓存
- ajax请求和跨域问题
- 1- get 请求和get 请求的区别
- 2- 网络传输常用的数据格式
- xml
- json
- 3- formdata 对象
- 4- 跨域 / 同源
- 解决跨域
- v8引擎的内存控制
- 垃圾回收机制
- service worker
- 性能优化
- WEB安全
- 1.xss攻击
- 1-1 xss介绍
- 1-2 恶意代码注入方式
- 1-3 XSS攻击分类
- 1-4XSS攻击预防
- 2.CSRF攻击
- 2-1 CSRF介绍
- 2-2 攻击类型
- 2-3 CSRF攻击特点
- 2-4 防护策略
- 同源检测防护
- 双重Cookie验证
- Token防护
- Samesite Cookie属性
- 2-5 CSRF 测试
- 3.点击劫持攻击
- 4.后端一些攻击漏洞:命令行注入和DDos攻击
- 面 - 开发中的数据安全问题
- 开发项目知识点
- yarn
- GIT
- 抓包工具
- linux基本指令
- 开发流程
- 短信验证码和图片验证码
- 移动端的兼容(安卓和iOS手机)
- 2.CSRF攻击
- 2-1 CSRF介绍
- 2-2 攻击类型
- 2-3 CSRF攻击特点
- 2-4 防护策略
- 同源检测防护
- 双重Cookie验证
- Token防护
- Samesite Cookie属性
- 2-5 CSRF 测试
- 3.点击劫持攻击
- 4.后端一些攻击漏洞:命令行注入和DDos攻击
- 面 - 开发中的数据安全问题
- 开发项目知识点
- yarn
- GIT
- 抓包工具
- linux基本指令
- 开发流程
- 短信验证码和图片验证码
- 移动端的兼容(安卓和iOS手机)
-
vue知识点 -
react知识点(完善90%)
等上了redux再继续完善
面试视频redux没看,react面试题没准备
-
webpack知识点 -
html/css知识点 -
浏览器知识点 -
网络知识点 -
安全问题 -
js知识点执行上下文/作用域/闭包 (概念和刷题)this/call/apply/bind (手写)原型/继承 (概念)Promise (看一下)深浅拷贝事件机制函数式编程es常用方法webworker防抖节流- 柯里化函数
-
typescript -
git代码管理 -
小程序 -
性能优化(闲暇看)
- 打包优化
- 网络优化
- 代码优化
-
node -
设计模式
-
数据结构和算
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a7F4lihL-1598189226388)(C:\Users\ADMINI~1\AppData\Local\Temp\1591770445912.png)]
面-什么是SEO
seo
搜索机器人的搜索网页的模式:根据网页类型来进行广度和深度搜索。
搜索机器人在搜索到一个网页时候,会优先看meta标签的元信息。所以meta内容是增加seo的一个手段。
搜索机器人在爬网页的时候,会对网络的内容进行一个过滤,然后根据内容相关度,比如文本相关度进行排行。而爬网页的过程中,如果能让搜索机器人更理解更快更好的处理数据,也会增加seo比如标签语义化。
还有一个很重要的seo就是外链。这是前端能做的增强seo最有效的一个方法。搜索机器人会根据外链的数量,和自己和对方外置的权重来进行一个计算,得出本网站的权重值。
- 合理的 title、description、keywords:搜索对着三项的权重逐个减小,title 值强调重点即可,重要关键词出现不要超过 2 次,而且要靠前,不同页面 title 要有所不同;description 把页面内容高度概括,长度合适,不可过分堆砌关键词,不同页面 description 有所不同;keywords 列举出重要关键词即可
- 重要内容 HTML 代码放在最前:搜索引擎抓取 HTML 顺序是从上到下,有的搜索引擎对抓取长度有限制,保证重要内容一定会被抓取
- 重要内容不要用 js 输出:爬虫不会执行 js 获取内容
- 少用 iframe(搜索引擎不会抓取 iframe 中的内容)
- 非装饰性图片必须加 alt
- 提高网站速度(网站速度是搜索引擎排序的一个重要指标)
面 - cookie / localstorage / sessionstorage的区别
-
cookie:一开始只是用来和服务器通信的,后来用于存储一些本地数据,大小只有4kb,发送ajax时,自动添加cookie。操作cookie的api简陋
-
localStorage(5M) / sessionStorage(20M)
大容量,loacalstorage永久存在浏览器中。sessionstorage只存在当前窗口,关闭则清除
cookie: cookie机制 客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。
cookie 做什么? 一般用来存储数据 比如 用户的登录状态 不过现在经常用token 和localStorage了
HTTP协议本身是无状态的。什么是无状态呢,即服务器无法判断用户身份。Cookie实际上是一小段的文本信息(key-value格式)。客户端向服务器发起请求,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户等状态。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0SGRNVSD-1598189226390)(C:\Users\ADMINI~1\AppData\Local\Temp\1592384871210.png)]
面 - promise面试题
//题目1
const promise = new Promise((resolve, reject) => {console.log(1)resolve()//此处不会阻塞console.log(2)
})
promise.then(() => {console.log(3)
})
console.log(4) //1243//题目2
const promise = new Promise((resolve, reject) => {setTimeout(() => {console.log('once')resolve('success')}, 1000)
})const start = Date.now()
promise.then((res) => {console.log(res, Date.now() - start)
})
//只要promise状态确定了,then函数可以一直调用
promise.then((res) => {console.log(res, Date.now() - start)
})//题目三
Promise.resolve(1).then(2).then(Promise.resolve(3)).then(console.log)
// .then 或者 .catch 的参数期望是函数,传入非函数则会发生值穿透。
面 - 柯里化函数
柯里化函数是指一个函数在内部定义了一个函数处理参数,并将其返回, 运行后可以得到新的函数,并且该函数能够处理接下来的参数。
面 - 函数节流
限制函数一段时间内,只执行一次。防抖和节流都是js性能优化的方式,都用于检测鼠标,滚轮,输入框输入等事件
var throttle = function(func, delay) {var prev = Date.now();return function() {var context = this;var args = arguments;var now = Date.now();if (now - prev >= delay) {func.apply(context, args);prev = Date.now();}}
}
function handle() {console.log(Math.random());
}
window.addEventListener('scroll', throttle(handle, 1000));
面 - 函数防抖
没有防抖前,函数持续触发。浪费性能,最典型的场景是输入框触发input事件时。这时候可以利用闭包实现函数防抖,达到事件出发后一段时间内再执行回调,若期间事件还被触发,则重新计时。
function debounce(fn, wait) {var timeout = null;return function() {if(timeout !== null) clearTimeout(timeout);timeout = setTimeout(fn, wait);}
}
// 处理函数
function handle() {console.log(Math.random());
}
// 滚动事件
window.addEventListener('scroll', debounce(handle, 1000));
HTML / CSS 知识点
1、讲讲盒模型(蚂蚁金服 2019.03 招行信用卡 2019.04 美团 作业帮)
盒子模型就是 元素在网页中的实际占位,有两种:标准盒子模型和IE盒子模型
标准(W3C)盒子模型:内容content+填充padding+边框border+边界margin宽高指的是 content 的宽高
低版本IE盒子模型:内容(content+padding+border)+ 边界margin,宽高指的是content+padding+border 部分的宽高
/* 标准模型 */
box-sizing:content-box;/*IE模型*/
box-sizing:border-box;
复制代码
2、根据盒模型解释边距重叠(蚂蚁金服 2019.03 图森未来)
父子元素、兄弟元素,当有外边距时,会取其中一个边距的最大值,作为实际的边距。 空元素的有上下边距时,也会取其中更大的一个边距值,作为实际的边距。 这就是边距重叠。
BFC: 概念:块级格式化上下文 原理:
- 在BFC这个元素垂直方向的边距会发生重叠
- BFC的区域不会与浮动元素的box重叠
- BFC在页面上是一个独立的容器,其里外的元素不会互相影响
- 计算BFC高度时,浮动元素也会参与计算
3、 宽高比4:3自适应 (蚂蚁金服 2019.03 )
垂直方向的padding: 在css中,padding-top或padding-bottom的百分比值是根据容器的width来计算的。
.wrap{position: relative;height: 0; //容器的height设置为0width: 100%;padding-top: 75%; //100%*3/4
}
.wrap > *{position: absolute;//容器的内容的所有元素absolute,然子元素内容都将被padding挤出容器left: 0;top: 0;width: 100%;height: 100%;
}
复制代码
+ **padding & calc()**: 跟第一种方法原理相同
```css
padding-top: calc(100%*9/16);
复制代码
- padding & 伪元素
- 视窗单位: 浏览器100vw表示浏览器的视窗宽度
width:100vw;
height:calc(100vw*3/4)
复制代码
4、css选择器的优先级( 百度前端 搜狐 美团 拼多多 VIVO)
优先级就近原则,同权重情况下样式定义最近者为准
!important>id >class>tag
important比内联优先级高
元素选择符的权值:元素标签(派生选择器):1,class选择符:10,id选择符:100,内联样式权值最大,为1000
- !important声明的样式优先级最高,如果冲突再进行计算。
- 如果优先级相同,则选择最后出现的样式。
- 继承得到的样式的优先级最低。
5、css水平居中 (蚂蚁金服、百度前端、字节跳动)
一、对于行内元素:
text-align:center;
复制代码
二、对于确定宽度的块级元素:
(1)margin和width实现水平居中
常用(前提:已设置width值):margin-left:auto; margin-right:auto;
(2)绝对定位和margin-left: -(宽度值/2)实现水平居中
固定宽度块级元素水平居中,通过使用绝对定位,以及设置元素margin-left为其宽度的一半
.content{width: 200px;position: absolute;left: 50%;margin-left: -100px; // 该元素宽度的一半,即100pxbackground-color: aqua;}
复制代码
(3)position:absolute + (left=0+top=0+right=0+bottom=0) + margin:auto
.content{position: absolute;width: 200px;top: 0;right: 0;bottom: 0;left: 0;margin: auto;}
复制代码
三、对于未知宽度的块级元素:
(1)table标签配合margin左右auto实现水平居中
使用table标签(或直接将块级元素设值为display:table),再通过给该标签添加左右margin为auto
(2)inline-block实现水平居中方法
display:inline-block;(或display:inline)和text-align:center;实现水平居中
复制代码
存在问题:需额外处理inline-block的浏览器兼容性(解决inline-block元素的空白间距)
(3)绝对定位实现水平居中
绝对定位+transform,translateX可以移动本省元素的50%
.content{position: absolute;left: 50%;transform: translateX(-50%); /* 移动元素本身50% */background: aqua;}
复制代码
(4)相对定位实现水平居中
用float或者display把父元素变成行内块状元素
.contentParent{display: inline-block; /* 把父元素转化为行内块状元素 *//*float: left; 把父元素转化为行内块状元素 */position: relative;left: 50%;}/*目标元素*/.content{position: relative;right: 50%;background-color:aqua;}
复制代码
(5)CSS3的flex实现水平居中方法,法一
.contentParent{display: flex;flex-direction: column;}.content{align-self:center;}
复制代码
(6)CSS3的flex实现水平居中方法,法二
.contentParent{display: flex;}.content{margin: auto;}
复制代码
(7)CSS3的fit-content配合左右margin为auto实现水平居中方法
.content{width: fit-content;margin-left: auto;margin-right: auto;}
复制代码
参考链接 blog.csdn.net/dengdongxia…
6、CSS3 的 flexbox(弹性盒布局模型)以及适用场景 (猿辅导)
该布局模型的目的是提供一种更加高效的方式来对容器中的条目进行布局、对齐和分配空间。在传统的布局方式中,block 布局是把块在垂直方向从上到下依次排列的;而 inline 布局则是在水平方向来排列。弹性盒布局并没有这样内在的方向限制,可以由开发人员自由操作。flexbox设置父元素的display
属性为flex
,则子元素都变成flex item
,通过自己内部的格式化规则。可以控制子元素的排列方式、尺寸、间距等; 试用场景:弹性布局适合于移动前端开发,在Android和ios上也完美支持。
7、如何画一个三角形 (星环科技)
左右边框设置为透明,长度为底部边框的一半。左右边框长度必须设置,不设置则只有底部一条边框,是不能展示的。
{width: 0; height: 0; border-top: 40px solid transparent; border-left: 40px solid transparent; border-right: 40px solid transparent; border-bottom: 40px solid #ff0000;}
复制代码
8、让一个图片无限旋转(蚂蚁金服 2019.03)
<img class="circle" src="001.jpg" width="400" height="400"/>//infinite 表示动画无限次播放 linear表示动画从头到尾的速度是相同的.circle{animation: myRotation 5s linear infinite;}
@keyframes myRotation {from {transform: rotate(0deg);}to {transform: rotate(360deg);}
}
复制代码
9、display 有哪些值?说明他们的作用?
inline默认。此元素会被显示为内联元素,元素前后没有换行符。
block此元素将显示为块级元素,此元素前后会带有换行符。
none此元素不会被显示(隐藏)。
inline-block行内块元素。(CSS2.1 新增的值)
list-item此元素会作为列表显示。
table此元素会作为块级表格来显示(类似table),表格前后带有换行符
10、position 的值?
absolute
生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位。
元素的位置通过 “left”, “top”, “right” 以及 “bottom” 属性进行规定。
fixed
生成固定定位的元素,相对于浏览器窗口进行定位。(老IE不支持)
元素的位置通过 “left”, “top”, “right” 以及 “bottom” 属性进行规定。
relative
生成相对定位的元素,相对于其正常位置进行定位,不脱离文档流。
因此,“left:20” 会向元素的 LEFT 位置添加 20 像素。
static默认值。
没有定位,元素出现在正常的文档流中(忽略 top, bottom, left, right 或者 z-index 声明)。inherit规定应该从父元素继承 position 属性的值。
11、为什么要初始化 CSS 样式
因为浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的,如果没对CSS初始化往往会出现浏览器之间的页面显示差异。
12、简要介绍一下CSS3的新特性
-
在布局方面新增了flex布局;
-
在选择器方面新增了例如:first-of-type,nth-child等选择器;
-
在盒模型方面添加了box-sizing来改变盒模型,
-
在动画方面增加了animation、2d变换、3d变换等。在颜色方面添加透明、rgba等,
-
在字体方面允许嵌入字体和设置字体阴影,同时当然也有盒子的阴影,
-
媒体查询。为不同设备基于它们的能力定义不同的样式。
@media screen and (min-width:960px) and (max-width:1200px){body{background:yellow;} } 复制代码
13、元素的显示与隐藏
元素的显示隐藏方法很多,不同方法的在不同的场景下页面效果不一,对页面的性能也有不同的影响。
元素隐藏方法总结:
-
如果希望元素不可见、不占据空间、资源会加载、DOM 可访问:
display: none
; -
如果希望元素不可见、不能点击、但占据空间、资源会加载,可以使用:
visibility: hidden
; -
如果希望元素不可见、不占据空间、显隐时可以又
transition
淡入淡出效果div{ position: absolute;visibility: hidden;opacity: 0;transition: opacity .5s linear;background: cyan; }div.active{visibility: visible;opacity: 1; } 复制代码
这里使用visibility: hidden
而不是display: none
,是因为display: none
会影响css3的transition
过渡效果。 但是display: none
并不会影响cssanimation
动画的效果。
- 如果希望元素不可见、可以点击、占据空间,可以使用:
opacity: 0
; - 如果希望元素不可见、可以点击、不占据空间,可以使用:
opacity: 0; position: absolute;
; - 如果希望元素不可见、不能点击、占据空间,可以使用:
position: relative; z-index: -1;
; - 如果希望元素不可见、不能点击、不占据空间,可以使用:
position: absolute ; z-index: -1;
display: none
与visibility: hidden
的区别
14、display: none
的元素不占据任何空间,visibility: hidden
的元素空间保留;display: none
会影响css3的transition
过渡效果,visibility: hidden
不会;display: none
隐藏产生重绘 ( repaint ) 和回流 ( relfow ),visibility: hidden
只会触发重绘;- 株连性:
display: none
的节点和子孙节点元素全都不可见,visibility: hidden
的节点的子孙节点元素可以设置visibility: visible
显示。visibility: hidden
属性值具有继承性,所以子孙元素默认继承了hidden
而隐藏,但是当子孙元素重置为visibility: visible
就不会被隐藏。
15.如何让一个不设宽高的div,垂直水平居中
方法一:使用css3方法的transfrom.
11 方法二:给父盒子设置display:table-ceil,这样子盒子就相当于表格内的元素和,可以通过text-align和vertical-align对齐
16.什么是BFC
BFC叫做块级格式化上下文。它制造了一个独立的渲染区域,有着自己特殊的布局方式,和外部不同。
内部布局规则有:
- 块级元素按垂直方向一个个放置
- box的垂直方向距离由margin控制
- bfc不会和浮动元素重叠
- bfc内容高度,包括浮动元素
触发方式:
- 根元素(html)
- float属性不为none
- position为absolute或者fixed
- display为inline-block,table-caption
- overflow不为visible
17.css reset 浏览器样式重置
每个浏览器对页面样式的处理方式不一样。所以有时候写样式的时候,会把这些浏览器差异化的样式统一清除后,编写样式。但是实际上样式初始化会对seo有一定的影响。所以我们要在保持最小损失的情况下达到相对大的效果。
18.常用的几种开发布局方式
流式布局/百分比布局
设置盒子的宽度的时候,采用百分比取值,使之能够小范围内根据,屏幕宽度调整元素距离。但是和设计图会有偏差。
fflex布局
rem布局
媒体查询,通过查询screen宽度来设置根元素字体大小,然后标签属性的尺寸单位设置成rem。
超小<768px
小屏:768-992
中屏:992-1200
大屏:>1200
通常使用响应式框架来开发网页,比如boostrap
19-兼容问题,渐进增强和优雅降级
渐进增强是优先针对低版本的浏览器进行构建页面,保证最基本的功能,然后针对高级浏览器进行效果交互功能的进一步优化。
优雅降级是一开始就是构建一个完整的功能,然后再对低版本浏览器进行一个向下兼容的处理,甚至是阉割。比如css3h5的一些特型,低版本处理不了
20-设置p标签属性,ie6以下为黑。ie7以下为红
这是css hack
p{color: green,//可以理解为特定浏览器下的私有属性*color:red,_color:black
}
20-html/xhtml/xml
html是网页设计的语言,
xhtml是xml的过度语言,和html类似,只是规则上有些差异,比如Xhtml必须有闭合标识。必须有根元素
xml是可拓展标记语言,和html语法规则类似,但是xml它用于传递数据,且xml标签完全自定义
21-对比一下div+css和table布局
table布局其实我基本没用过。只是自己练习的时候操作了一下。所以也只能简单的对比一下两者的差异
div+css:能够提高seo,相对于table来说很大程度上提高了网页的浏览速度。而且容易维护和改版
table:局部麻烦,代码量大,不容易维护,seo差
22-console
console.info(“这是info”);
console.log(“这是log”);
console.debug(“这是debug”);
console.warn(“这是warn”);
console.error(“这是error”);
console.dir(‘这是dir’)
console.group(“第一组信息”);
console.log(“第一组第一条”);
console.log(“第一组第二条”);
console.groupEnd();
23-为什么利用多个域名来提供网站资源会更有效
- 突破浏览器的并发限制 现阶段各大浏览器的同一域名最大的并发请求数量在6个或以上,低版本的IE6、7是2个。
- 节约cookie带宽 在访问服务器时,cookie也会占用一定的带宽,使用多个域名进行分流。
- CDN缓存更方便 多个域名可以更快速的给客户端分配最优下载服务器,传输数据更快。
- 防止不必要的安全问题,例如cookie的隔离 客户端对服务器进行请求时,发送数据到达的地址会用一个第三方的域名。防止上传恶意数据对cookie进行窃取。
- 节约主机域名连接数,优化页面响应速度 这个很显然,每个域名所响应的客户端请求越少,反应时间也就越短,客户端页面可以更快下载数据。
24-谈谈以前端角度出发做好 SEO 需要考虑什么?
搜索机器人的搜索网页的模式:根据网页类型来进行广度和深度搜索。
搜索机器人在搜索到一个网页时候,会优先看meta标签的元信息。所以meta内容是增加seo的一个手段。
搜索机器人在爬网页的时候,会对网络的内容进行一个过滤,然后根据内容相关度,比如文本相关度进行排行。而爬网页的过程中,如果能让搜索机器人更理解更快更好的处理数据,也会增加seo比如标签语义化。
还有一个很重要的seo就是外链。这是前端能做的增强seo最有效的一个方法。搜索机器人会根据外链的数量,和自己和对方外置的权重来进行一个计算,得出本网站的权重值。
-
合理的 title、description、keywords:搜索对着三项的权重逐个减小,title 值强调重点即可,重要关键词出现不要超过 2 次,而且要靠前,不同页面 title 要有所不同;description 把页面内容高度概括,长度合适,不可过分堆砌关键词,不同页面 description 有所不同;keywords 列举出重要关键词即可
-
重要内容 HTML 代码放在最前:搜索引擎抓取 HTML 顺序是从上到下,有的搜索引擎对抓取长度有限制,保证重要内容一定会被抓取
-
重要内容不要用 js 输出:爬虫不会执行 js 获取内容
-
少用 iframe(搜索引擎不会抓取 iframe 中的内容)
-
非装饰性图片必须加 alt
-
提高网站速度(网站速度是搜索引擎排序的一个重要指标)
25-rgba()和 opacity 的透明效果有什么不同?
rgba()和 opacity 都能实现透明效果,但最大的不同是 opacity 作用于元素,以及元素内的所有
内容的透明度,
而 rgba()只作用于元素的颜色或其背景色。(设置 rgba 透明的元素的子元素不会继承透明效果!)
26 - sass和less
sass和less都属于css的预处理器,是专门用一种语言来为css增加一点编程的特性,最终输出css文件。
至于为什么使用这些css预处理器。因为css本身的语法有很多不足,比如不能嵌套书写,没有变量和合理的样式复用机制。难以维护。
less对比sass的优点:
- less使用环境更简单,只要能运行js,就能处理less文件。而cass需要安装ruby环境
- less使用上手简单,十分贴合css,只是增加一个些变量等复用性强的语法规则
-sass优势:
- 有变量作用域,函数,进程控制,继承,数据结构等
27-css3动画和js动画区别
js动画功能更加强大,兼容性更好
- js对于动画的控制粒度更细,css只能通过@keyframs来控制。
- css动画被支持的时间函数很少,不灵活
- 现阶段而言,css动画很难做到多个状态的转化
- 只要支持js的客户端都能展示出来
css优势:性能好
- css是样式制作的动画,性能消耗比较少
- css3属性,有很大的兼容问题
- 对于帧速表现不太好的浏览器,css可以自然降级
28-css3和html5新特性
1、CSS3 新特性有哪些?
答:1.颜色:新增 RGBA,HSLA 模式
\2. 文字阴影(text-shadow、)
3.边框: 圆角(border-radius)边框阴影: box-shadow
\4. 盒子模型:box-sizing
5.背景:background-size 设置背景图片的尺寸 background-origin 设置背景图片的原点
background-clip 设置背景图片的裁切区域,以”,”分隔可以设置多背景,用于自适应布局
6.渐变:linear-gradient、radial-gradient
\7. 过渡:transition,可实现动画
\8. 自定义动画 animate @keyfrom
\9. 在 CSS3 中唯一引入的伪元素是 ::selection.
\10. 媒体查询,多栏布局 @media screen and (width:800px){ … }
\11. border-image
12.2D 转换:transform:translate(x,y) rotate(x,y) skew(x,y) scale(x,y)
\13. 3D 转换
14 字体图标 font-face
15 弹性布局 flex
2、CSS3 选择器有哪些?
答:属性选择器、伪类选择器、伪元素选择器。
属性选择器 例如:[href=“a.mp4”] {color: green;}
伪类选择器 例如:li:nth-child(3) {color: red;} span:empty h2:target li:not(.special) li:nth-last
child(3) {color: blue;}
伪元素选择器 例如:p::selection p::first-line li::first-letter ::after ::bofer
2.html5 有哪些新特性、移除了那些元素?如何处理 HTML5 新标签的浏览器兼容问题?
新特性:
\1. 拖拽释放(Drag and drop) API ondrop
自定义属性 data-id 获取 li.getAttribute(‘data-id’)或者 li.dataset.type = ‘guoji’
\2. 语义化更好的内容标签(header,nav,footer,aside,article,section)
\3. 音频、视频 API(audio,video) 如果浏览器不支持自动播放怎么办?
\4. 画布(Canvas) API 热 canvas 和 image 的区别?
\5. 地理(Geolocation) API
\6. 本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失;
\7. sessionStorage 的数据在浏览器关闭后自动删除
\8. 表单控件,calendar、date、time、email、url、search 、tel、file、number
\9. 新的技术 webworker, websocket, Geolocation
10文件读取
移除的元素-纯表现的元素:basefont,big,center,font, s,strike,tt,u;
支持 HTML5 新标签:
* IE8/IE7/IE6 支持通过 document.createElement 方法产生的标签,
可以利用这一特性让这些浏览器支持 HTML5 新标签,
浏览器支持新标签后,还需要添加标签默认的样式:
* 当然最好的方式是直接使用成熟的框架、使用最多的是 html5shim 框架
<!--[if lt IE 9]> <script> src="http://html5shim.googlecode.com/svn/trunk/html5.js"</script> <![endif]-->
29-image 和 canvas 在处理图片的时候有什么区别?
答:image 是通过对象的形式描述图片的;canvas 通过专门的 API 将图片绘制在画布上。
30-HTML5中的本地存储介绍一下
标签之间的通信和购物车都会用到本地存储
以前我们在存储本地得到时候都会存储在cookie里面,但是cookie存储大小只有4k,而且解析复杂。而且cookie数据,在发送请求的时候,会自动发送给浏览器。造成更大的问题
存储空间html5 localstorage(20m)和sessionStorage(5m)提供了一个新的本地存储方式,存储空间更大,操作更简易。
生命周期:sessionStorage。在浏览器窗口关闭时清除。local storage需要手动清除。cookie在过期之前一直有效。
作用域: sessionStorage要想数据共享,必须在同一个浏览器内。localstorage和cookie在所有的同源窗口中共享
31- margin塌陷解决方式
-
给父元素设定一个border-top / padding-top限定子元素的margin
-
给父元素设定overflow:hidden 触发BFC
-
给父元素设定浮动
-
将父元素转成行内块元素
32- 清浮动方法
-
额外标签法
给父元素后添加块元素,添加属性clear:both
-
伪元素清楚法
原理和额外标签清除一样,只不过换成了为元素
-
给父元素设定overflow:hidden
-
给父元素设定一个高度
33- flex
单行内:
-
水平方向
justify-content : space-between
-
垂直方向
align- center
是否换行:
- flex-wrap:wrap
多行侧轴:
- align-content : space - around
flex - basic 元素初始大小,优先级比width高
34- 常见的布局方式
- 流式布局(百分比布局)
- flex布局(弹性布局)
- 响应式布局
- grid布局
35-css中的1px问题
12 - 哪些操作会导致回流
- 调整窗口大小(Resizing the window)
- 改变字体(Changing the font)
- 增加或者移除样式表(Adding or removing a stylesheet)
- 内容变化,比如用户在input框中输入文字(Content changes, such as a user typing text in
an input box) - 激活 CSS 伪类,比如 :hover (IE 中为兄弟结点伪类的激活)(Activation of CSS pseudo classes such as :hover (in IE the activation of the pseudo class of a sibling))
- 操作 class 属性(Manipulating the class attribute)
- 脚本操作 DOM(A script manipulating the DOM)
- 计算 offsetWidth 和 offsetHeight 属性(Calculating offsetWidth and offsetHeight)
- 设置 style 属性的值 (Setting a property of the style attribute)
36- CSS实现水平垂直居中
划重点,这是一道面试必考题,很多面试官都喜欢问这个问题,我就被问过好几次了
要实现上图的效果看似很简单,实则暗藏玄机,本文总结了一下CSS实现水平垂直居中的方式大概有下面这些,本文将逐一介绍一下,我将本文整理成了一个github仓库,欢迎大家star
仅居中元素定宽高适用
- absolute + 负margin
- absolute + margin auto
- absolute + calc
居中元素不定宽高
- absolute + transform
- lineheight
- writing-mode
- table
- css-table
- flex
- grid
absolute + 负margin
为了实现上面的效果先来做些准备工作,假设HTML代码如下,总共两个元素,父元素和子元素
<div class="wp"><div class="box size">123123</div>
</div>
复制代码
wp是父元素的类名,box是子元素的类名,因为有定宽和不定宽的区别,size用来表示指定宽度,下面是所有效果都要用到的公共代码,主要是设置颜色和宽高
注意:后面不在重复这段公共代码,只会给出相应提示
/* 公共代码 */
.wp {border: 1px solid red;width: 300px;height: 300px;
}.box {background: green;
}.box.size{width: 100px;height: 100px;
}
/* 公共代码 */
复制代码
绝对定位的百分比是相对于父元素的宽高,通过这个特性可以让子元素的居中显示,但绝对定位是基于子元素的左上角,期望的效果是子元素的中心居中显示
为了修正这个问题,可以借助外边距的负值,负的外边距可以让元素向相反方向定位,通过指定子元素的外边距为子元素宽度一半的负值,就可以让子元素居中了,css代码如下
/* 此处引用上面的公共代码 */
/* 此处引用上面的公共代码 *//* 定位代码 */
.wp {position: relative;
}
.box {position: absolute;;top: 50%;left: 50%;margin-left: -50px;margin-top: -50px;
}
复制代码
这是我比较常用的方式,这种方式比较好理解,兼容性也很好,缺点是需要知道子元素的宽高
点击查看完整DEMO
absolute + margin auto
这种方式也要求居中元素的宽高必须固定,HTML代码如下
<div class="wp"><div class="box size">123123</div>
</div>
复制代码
这种方式通过设置各个方向的距离都是0,此时再讲margin设为auto,就可以在各个方向上居中了
/* 此处引用上面的公共代码 */
/* 此处引用上面的公共代码 *//* 定位代码 */
.wp {position: relative;
}
.box {position: absolute;;top: 0;left: 0;right: 0;bottom: 0;margin: auto;
}
复制代码
这种方法兼容性也很好,缺点是需要知道子元素的宽高
点击查看完整DEMO
absolute + calc
这种方式也要求居中元素的宽高必须固定,所以我们为box增加size类,HTML代码如下
<div class="wp"><div class="box size">123123</div>
</div>
复制代码
感谢css3带来了计算属性,既然top的百分比是基于元素的左上角,那么在减去宽度的一半就好了,代码如下
/* 此处引用上面的公共代码 */
/* 此处引用上面的公共代码 *//* 定位代码 */
.wp {position: relative;
}
.box {position: absolute;;top: calc(50% - 50px);left: calc(50% - 50px);
}
复制代码
这种方法兼容性依赖calc的兼容性,缺点是需要知道子元素的宽高
点击查看完整DEMO
absolute + transform
还是绝对定位,但这个方法不需要子元素固定宽高,所以不再需要size类了,HTML代码如下
<div class="wp"><div class="box">123123</div>
</div>
复制代码
修复绝对定位的问题,还可以使用css3新增的transform,transform的translate属性也可以设置百分比,其是相对于自身的宽和高,所以可以讲translate设置为-50%,就可以做到居中了,代码如下
/* 此处引用上面的公共代码 */
/* 此处引用上面的公共代码 *//* 定位代码 */
.wp {position: relative;
}
.box {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);
}
复制代码
这种方法兼容性依赖translate2d的兼容性
点击查看完整DEMO
lineheight
利用行内元素居中属性也可以做到水平垂直居中,HTML代码如下
<div class="wp"><div class="box">123123</div>
</div>
复制代码
把box设置为行内元素,通过text-align
就可以做到水平居中,但很多同学可能不知道通过通过vertical-align
也可以在垂直方向做到居中,代码如下
/* 此处引用上面的公共代码 */
/* 此处引用上面的公共代码 *//* 定位代码 */
.wp {line-height: 300px;text-align: center;font-size: 0px;
}
.box {font-size: 16px;display: inline-block;vertical-align: middle;line-height: initial;text-align: left; /* 修正文字 */
}
复制代码
这种方法需要在子元素中将文字显示重置为想要的效果
点击查看完整DEMO
writing-mode
很多同学一定和我一样不知道writing-mode
属性,感谢@张鑫旭老师的反馈,简单来说writing-mode可以改变文字的显示方向,比如可以通过writing-mode让文字的显示变为垂直方向
<div class="div1">水平方向</div>
<div class="div2">垂直方向</div>
复制代码
.div2 {writing-mode: vertical-lr;
}
复制代码
显示效果如下:
水平方向
垂
直
方
向
复制代码
更神奇的是所有水平方向上的css属性,都会变为垂直方向上的属性,比如text-align
,通过writing-mode
和text-align
就可以做到水平和垂直方向的居中了,只不过要稍微麻烦一点
<div class="wp"><div class="wp-inner"><div class="box">123123</div></div>
</div>
复制代码
/* 此处引用上面的公共代码 */
/* 此处引用上面的公共代码 *//* 定位代码 */
.wp {writing-mode: vertical-lr;text-align: center;
}
.wp-inner {writing-mode: horizontal-tb;display: inline-block;text-align: center;width: 100%;
}
.box {display: inline-block;margin: auto;text-align: left;
}
复制代码
这种方法实现起来和理解起来都稍微有些复杂
点击查看完整DEMO
table
曾经table被用来做页面布局,现在没人这么做了,但table也能够实现水平垂直居中,但是会增加很多冗余代码
<table><tbody><tr><td class="wp"><div class="box">123123</div></td></tr></tbody>
</table>
复制代码
tabel单元格中的内容天然就是垂直居中的,只要添加一个水平居中属性就好了
.wp {text-align: center;
}
.box {display: inline-block;
}
复制代码
这种方法就是代码太冗余,而且也不是table的正确用法
点击查看完整DEMO
css-table
css新增的table属性,可以让我们把普通元素,变为table元素的现实效果,通过这个特性也可以实现水平垂直居中
<div class="wp"><div class="box">123123</div>
</div>
复制代码
下面通过css属性,可以让div显示的和table一样
.wp {display: table-cell;text-align: center;vertical-align: middle;
}
.box {display: inline-block;
}
复制代码
这种方法和table一样的原理,但却没有那么多冗余代码,兼容性也还不错
点击查看完整DEMO
flex
flex作为现代的布局方案,颠覆了过去的经验,只需几行代码就可以优雅的做到水平垂直居中
<div class="wp"><div class="box">123123</div>
</div>
复制代码
.wp {display: flex;justify-content: center;align-items: center;
}
复制代码
目前在移动端已经完全可以使用flex了,PC端需要看自己业务的兼容性情况
点击查看完整DEMO
grid
感谢@一丝姐 反馈的这个方案,css新出的网格布局,由于兼容性不太好,一直没太关注,通过grid也可以实现水平垂直居中
<div class="wp"><div class="box">123123</div>
</div>
复制代码
.wp {display: grid;
}
.box {align-self: center;justify-self: center;
}
复制代码
37- 层叠上下文和层叠等级
-
层叠上下文
如果一个元素内部发生了元素层叠,则称这个元素为层叠上下文元素。
-
在同一个层叠上下文中,层叠等级越高的,越在z轴高出显示
-
不同层叠上下文层叠等级的比较,要先比较层叠上下文叠层等级
38- 移动端的1px
- 根据设备型号,比如375设备和750设计稿,将0.5px转成rem
- 使用边框图边
- 设置meta元属性的视口,以方便适配手机端
39 - input宽度
并不是给所有元素设定display:block,该元素就会填充父元素宽度。input的就不会,input宽度只由size决定
js知识点
面 - js对象隐形转成原始数据类型
- 如果对象存的是原始数据类型,那就不需要转换了。
- 调用x.valueOf(),入股转换成基础数据类型,返回对应的值,
- 调用.toString(),如果转成基础类型,返回
- 如果都没有返回,报错
面 - 基础类型使用方法
基础类型当在调用方法的时候,浏览器内部会将他转成对象,然后调用原型链上的方法。
调用完后,销毁对象,转成初始值
1.数据类型和方法
- number
- string
- boolean
- undefine
- null
- Object
- function
- Array
1-1 操作数组方法
.join() 将数组转成字符串,用自定义的字符串分割
.push() 将数据放在最后一项,返回一个长度
.pop() 将数组最后一项移除,返回移除的值
.shift() 删除数组第一项,返回该项
.unshift()在数组第一项加上一项/多项,返回长度
.sort() 对数组进行排序
.reverse() 反向排序数组
.concat() 合并数组
.slice( index1,index2) 数组截取,返回截取的新数组
.splice() 删除数组项,添加数组项
indexof( ) / lastindexof()查找已知数据,返回第一次/最后一次出现的下标,没有则返回-1
es5
.forEach() 遍历数组,将每项交给回调处理
.map()遍历数组,将每项交给回调处理,返回一个新函数
.filter() 返回一个数组,包含满足回调函数条件的元素
.some() 判断是否有元素满足条件
.every() 判断是否全符合条件
.find() 找到第一个满足条件的元素
2- string对象
简单的数据类型本身是没有操作数据的方法的,他们只有数据,若简单数据类型使用了属性和方法,浏览器底层会将其包装成复杂数据类型,操作结束后,又会基本包装类型
.trim()去除字符串首位空格
.touppercase()转大写字母
.slice()字符串切割
.replace()字符串替换
es6
.startsWith() 是否以指定字符串开头
.endsWith() 是否以指定字符串结尾
.includes()
2.操作符
-
typeof - typeof str 返回数据类型
检测数据类型,基本数据类型都能识别,复杂数据类型都是object。null由于二进制的前三位和对象是一样的,所以也被识别为object
-
instanceof
A instanceof B - 判断B是否在A原型链上,返回布尔值
Object.getPrototypeOf(obj)
-
逻辑运算符
A && B 返回遇到的第一个falsely值,都是ture,返回B
A || B 返回第一个truely值
-
比较运算符
== 类型不同会隐形转换,尽量让他们相等
除非 == null ,其他一律用 ===
-
in 操作符
检查该属性是不是在原型链上
Object.hasOwnProperty()检查属性是不是在该实例上
Object.create(B) 将B添加为对象的原型
Object.keys(obj) 遍历对象,提取key放入数组
Object.assign(target,… sources) 浅复制
-
for … of …
迭代这个对象
5.类和实例和继承
类:是将数据和它相关的行为打包起来就称之为类。在其他语言中,子类和父类,类和实例,都是完全不同的对象,子类将父类的成员复制过来加以处理,形成自己的属性和方法。
原型/构造函数:这两个概念是js里面独有的,在js中用这两者来模拟类的概念。构造函数中有一个属性指向原型,原型有一个默认属性指向构造函数,当构造函数实例化后,new强行构建了一个对象称之为实例。实例上有构造函数执行时获得的方法,当调用自己没有的方法时,实例的内部[[get]]属性会自动向对象的__proto_
属性指向的对象中查找,这个对象就是实例。若该原型的身上也没有该方法,【【get】】内部属性会继续通过–proto–找原型的原型,就这样[[get]]持续查找的过程,直到查找到null,这中间通过–propto–属性链接起来的链式结构,称之为原型链。一些插件就是在原型上添加了相关的接口而已。
继承:是面向对象编程的三大特征之一。就是将有着共同成员的类的成员提取出来单独定义成一个类,若需要定义多个子类的时候,已经在父类定义好了的成员就不用重新定义了。由于js中的原型和构造函数的特殊性,有很多种继承方式。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XuYLpOGh-1598189226398)(C:\Users\ADMINI~1\AppData\Local\Temp\1592389657228.png)]
封装:面向对象编程的三大特征之一。对象内部 可以定义外部访问不到的私有属性
多态:对象在实例化的时候,对类的方法重新赋值。就造成了一个函数名的两种使用方式。
原型和原型链
- 原型:每个函数都有 prototype 属性,该属性指向原型对象;使用原型对象的好处是所有对象实例共享它所包含的属性和方法。
- 原型链:主要解决了继承的问题;每个对象都拥有一个原型对象,通过__proto__ 指针指向其原型对象,并从中继承方法和属性,同时原型对象也可能拥有原型,这样一层一层,最终指向 null。
7. ES高级
-
解构赋值
-
计算变量
-
模板字符串
-
展开运算符
-
set对象去重
-
箭头函数
- 箭头函数没有内部属性this,只能在词法作用域找外部的this。
- 没有内部属性arguments
- 没有propertype属性
- this无法用call等改变
-
模块的导出和导入
es6的模块导入是静态导入,在导入前会先进行编译。所以配合webpack能实现一些代码优化。
-
promise()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HdAfj7bZ-1598189226399)(C:\Users\ADMINI~1\AppData\Local\Temp\1592389471451.png)]
解决异步中的回调函数问题,回调地狱。阅读性差
promise对象内部有一个状态机,当调用reject或者resole函数时候,状态机的值就会改变,执行then或者catch函数。
实质上是对Generator (生成器)函数的包装
-
async 和 await 关键字
async 修饰一个函数,标识这个函数异步执行。
await 会阻塞async函数的执行,直到内部 定义的一个promise对象得到成功的结果。只接收成功的结果,若防止失败。用try/catch包裹整个await代码
-
let/const
声明关键字,会定义一个块作用域,每次声明都会创建一个块作用域。
for(let i = 0 ,i < 10, i++){console.log(i) } //等同于 { let i = 0 ,log(i) } { let i = 1 ,log(i) } { let i = 2 ,log(i) } { let i = 3 ,log(i) } { let i = 4 ,log(i) } ```
代码执行到一块作用域的时候,编译器会创建词法作用域环境,此时声明提升。
- 编译器遇到var关键字的时候,会查找该变量有没有声明,如果声明了,就直接不再创建变量标识符,若没有则创建,并自动赋值为undifine。v
- 当编译器遇到let关键词时,创建和查找过程和var一样,和var不同的是let的词法环境是块作用域内。
- const关键词和let差不多,只是const关键词声明的变量的内部属性的[[write]]属性值为false。
在let/const声明变量后,到js引擎给变量赋值的过程,变量里面没有保存任何数据,连undfine都没有,这段过程称为暂时性死区。
let/const的变量提升,最多只能提升到script作用域变量
-
迭代器
iterator是一个接口,为不同的数据提供一个访问机制,完成遍历操作。
数组的很多高级方法,内部都是调用了迭代里来遍历数组,执行流程如下
- 被遍历的对象会调用[Symbol.iterator]方法,
- 该方法返回一个迭代器对象,对象指针指向1
- 该对象可以调用next()方法,该会返回包含1号项信息的value和done属性的对象。指针指向2
- 一直调用next()
- 直到done变成true
迭代器在es6中使用的场景很多:
- 解构赋值
- 扩展运算符
- 数组/伪数组的方法
- set对象去重
-
es6 moudle
静态导入,编译后才会导入数据。自动采用严格模式。导出的都是值的引用
import()导入会返回一个promise对象,可以通过这个进行懒加载
import(“”).then()
-
Proxy
是一个构造函数,可以生成一个拦截对象实例,访问任何该对象的行为,都要先经过拦截对象。
我们回想一下vue 2+对数组的拦截方式,只能通过在实例和对象之间增加一个拦截原型来监听几个数组方法。而proxy对象是在访问该对象之间建立了一个对象。
宏任务:主代码。i/o,ui render
8- DOM
面 - onload 和 onDomContentLoaded的区别
1- 元素查找
找到的dom元素伪数组
2- 事件流
注册事件
-
事件源.on事件名 = 函数
-
事件源.addEventListener( “事件名”,事件处理函数,布尔值 )
有兼容性,通过布尔值控制事件处理函数的触发时机,true在捕获阶段执行
移除事件
- 事件源.on事件名 = null
- 事件源.removeEventListener( “事件名”,事件处理函数 )
3- 事件对象
在事件触发后,会创建一个事件对象,存入事件相关信息。
浏览器自动将事件对象,存入事件处理函数中,只要在事件处理函数接收就好了
event.target 注册和绑定事件的对象
event.currentTarget 触发点击的对象
event.perventDefault()阻止对象默认行为
event.stopPropagation()阻止事件流传递
9- BOM
Location对象
包含了网站的url信息和操作
History对象
存储浏览器的历史记录
Navigation对象
存储了客户端的信息
window对象
offsetWIdth : 当前元素信息
clientwidth:当前元素可视区信息
scroll 滚动条信息
移动端dom
touch相关事件。click事件会有300ms延迟
事件对象:
e.touches: 屏幕上所有触点
10- js的执行机制
10-1 编译过程
-
阶段一:词法分析阶段
将代码拆分成token词法单元块
-
阶段二: 语法分析
将token转成AST(抽象语法树)
-
阶段三:代码生成
AST 转译成机器码
作用域就是收集和维护所有声明标识符的超集
10-2 代码执行过程
-
编译器声明代码,在词法作用域内查找是否有变量标记符,若没有,则在该作用域创建该标识符
声明提升,预解析过程
- 声明多个函数,后面覆盖前面的
- 声明同名函数和变量,函数生效
-
js引擎执行代码的时候,会在当前词法作用域查找有没有a,若有直接操作数据,没有继续向上查找
LHS查询被赋值的变量,RHS查询查找变量
10-3 词法作用域/函数作用域/块作用域和闭包
作用域:就是一个变量的合法使用范围。在这个范围内,RHS能查询到该变量
词法作用域是词法分析过程就定下来了作用域,而闭包就是指函数在执行的时候,能够访问声明时候所在的词法作用域,此时就产生了闭包。
闭包可以用来保护数据,模块导入,防抖节流
10-4 预解析
10-5 this
this指向函数调用的 执行环境对象,所以this的绑定决定于函数的调用方式,可以通过函数调用栈查找
-
函数自调用
this指向全局对象
-
对象调用
this指向该对象
-
call()/apply()/bind()直接绑定
-
new绑定
-
特殊调用
- 定时器中的函数属于函数自调用
函数发生赋值传递时候,原this指向会丢失
面 - 手写new
- 创建一个新对象,继承构造函数的原型
- 考虑参数
- 绑定this指向
function newOperator(ctor){if(typeof ctor !== 'function'){throw 'newOperator function the first param must be a function';}// ES6 new.target 是指向构造函数newOperator.target = ctor;// 1.创建一个全新的对象,// 2.并且执行[[Prototype]]链接// 4.通过`new`创建的每个对象将最终被`[[Prototype]]`链接到这个函数的`prototype`对象上。var newObj = Object.create(ctor.prototype);// ES5 arguments转成数组 当然也可以用ES6 [...arguments], Aarry.from(arguments);// 除去ctor构造函数的其余参数var argsArr = [].slice.call(arguments, 1);// 3.生成的新对象会绑定到函数调用的`this`。// 获取到ctor函数返回结果var ctorReturnResult = ctor.apply(newObj, argsArr);// 小结4 中这些类型中合并起来只有Object和Function两种类型 typeof null 也是'object'所以要不等于null,排除nullvar isObject = typeof ctorReturnResult === 'object' && ctorReturnResult !== null;var isFunction = typeof ctorReturnResult === 'function';if(isObject || isFunction){return ctorReturnResult;}// 5.如果函数没有返回对象类型`Object`(包含`Functoin`, `Array`, `Date`, `RegExg`, `Error`),那么`new`表达式中的函数调用会自动返回这个新的对象。return newObj;
}
面 - 手写call()
//手写一个call Object.prototype.myCall = function (obj, str) {obj.xxx = this // this是指向函数obj.xxx(str)}dog.say.myCall(cat, '我是')
get和post 的区别
GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息。
GET参数通过URL传递,POST放在Request body中。
GET请求参数会被完整保留在浏览器历史记录里,而POST中的参数不会被保留
GET 请求可被收藏为书签 ,POST 不能被收藏为书签
GET请求只能进行url编码,而POST支持多种编码方式。
GET 请求可被缓存 POST 请求不会被缓存
GET 请求有长度限制,POST 请求对数据长度没有要求
面试题
3.防抖和节流的区别是什么?怎么实现?
- 防抖:触发事件的n秒后执行对应函数,若n秒内事件再次被触发,那么时间将重新计算。
function debounce(fn, time) {let timer = null; // 定时器IDreturn function() {clearTimeout(timer); // 触发事件时将上一次的定时器清除掉timer = setTimeout(() => { // 创建一个新的定时器,只有在一定时间后会执行fn.apply(this, arguments);}, time);}}
复制代码
- 节流:触发事件后,会先判断n秒内是否执行了函数,未执行时才会去执行。
function throttle(fn, time) {let isRun = false; // 定义一个当前事件内是否执行了函数的变量return function () {if (isRun) return; // 如果当前时间内函数执行了,则直接returnisRun = true; // 没执行,则将其设置为truesetTimeout(() => { // 创建一个定时器在n秒后执行函数,并把isRun赋值为falsefn.apply(this, arguments);isRun = false;}, time);}}
复制代码
4.深拷贝和浅拷贝有什么区别?你能实现一个深拷贝吗?
- 浅拷贝只能复制对象的第一层,当对象的属性还是引用类型的时候,则只会复制其引用地址,当值被修改以后所有的引用的值都会改变。
- 赋值拷贝
- Object.assign
- 扩展运算符
- 深拷贝则是解决浅拷贝存在的无法深入拷贝复杂类型
- JSON对象的parse和stringify
- 可以满足基本的深拷贝需求,能够处理所有能用json格式标识的所有数据类型。但是对于正则表达式和函数类型无法进行深拷贝,会丢失很多信息。也会抛弃对象的chonstructor
- 递归函数
- JSON对象的parse和stringify
浅拷贝实现 , 只拷贝当前基本属性的值,不会拷贝复杂属性的值 ,俗称:只拷贝地址,不拷贝内容
var a = function(obj) {// 只拷贝对象if (typeof obj !== 'object') return;// 根据obj的类型判断是新建一个数组还是对象var newObj = obj instanceof Array ? [] : {};// 遍历obj,并且判断是obj的属性才拷贝for (var key in obj) {//查找当前对象是否有这个属性if (obj.hasOwnProperty(key)) {newObj[key] = obj[key];}}return newObj;}
深拷贝实现 拷贝当前的值,复杂属性也一并拿来,拷贝全部属性值,换个地址而已
var c = {name:'wangyu',yu:{age: 18}}function a(obj) {var newobj = null;if(typeof obj == 'object' && obj !== null){newobj = obj instanceof Array ? [] : {};for(var key in obj){newobj[key] = a(obj[key]) }return newobj;}else{return newobj = obj}}var qwe = a(c)qwe.ewq = 20;console.log(qwe);console.log(c);
7.在ES5中比较常见的继承方式有哪些?
8.实现一个new函数
function _new(Fn,...arg) {// 必须为一个函数且不能为箭头函数if(typeof Fn !== "function" || !Fn.prototype) throw Error(`Fn is not a constructor`);// 将新对象的隐式原型赋值为构造函数的prototype,obj.__proto__ = Fn.prototypeconst obj = Object.create(Fn.prototype);// 改变Fn的执行作用域,并传入相应的参数const isRet = Fn.call(obj, ...arg);// 判断构造函数本身是否返回一个objectreturn isRet instanceof Object ? isRet : obj;}
复制代码
9.箭头函数和普通函数的区别是什么?
- 自身无this,其this继承上一级,所以无法使用call、apply、bind绑定this
- 自身无 arguments 对象,会通过作用域链向上查找
- 不能用作 Generator 函数。
- 没有prototype属性,所以无法用new关键字调用
10.实现一个promise
我当时实现的是非常低配的promise,代码就不贴了,推荐坤坤大佬的promise实现
11.promise、async/await、setTimeout的区别是什么?
首先,js的事件循环分为宏任务和微任务,而当前执行栈的执行顺序为同步代码 -> 微任务中的代码 -> 宏任务中的代码。
- promise:promise函数本身是同步执行的,只有其then或者catch等方法是异步执行的并且其回调函数会被放在事件循环中的微任务队列,让同步代码先执行。
- async/await:当一个函数被添加async关键字的时候表明当前函数中可能会有异步方法,await关键字只能在async函数中使用并且后面跟一个表达式,在async函数中遇见await关键字时会同步执行后面的表达式并将表达式后面的代码放入微任务队列,让同步代码先执行。
- setTimeout/setInterval:定时器中的回调函数会被放在宏任务队列,等同步代码和微任务队列中的代码执行完毕后执行
vue知识点
面- 介绍一下什么是SSR
SSR 又称服务端渲染,底层实现逻辑有点像同构。大概的一个流程时在服务端运行一遍代码后,拿到html文件,将其
- 客户端渲染的问题
- 在客户端渲染时,会先加载html,解析html后,再请求一次JavaScript文件,渲染生成页面。首屏加载事件慢,甚至出现白屏。
- 客户端渲染的seo能力很弱。搜索引擎的识别内容主要还是html文件。
- ssr解决方式:ssr技术会让框架代码现在服务端执行一遍,用户第一次请求的时候已经获得了完整的html文件,节省了一个周期的http请求时间。也利于seo。在客户端再执行一遍代码后,又给了静态html交互的能力。
- 缺陷:ssr技术让原本简单的项目执行起来十分复杂,项目的可维护性降低,debugger变得复杂。所以如果项目对首屏加载速度和seo需求不是那么大,尽量不适用ssr
面-vue的跨平台是如何做到的
虚拟dom本质上就是一个js对象,实际开发中,都是对这个对象进行操作。跨平台只要在vue的适配层添加响应的适配代码,根据不同的平台做出不同的对外接口。
面 - 文件上传的几种方式,聊聊大文件上传
1.普通上传方式
将文件进行编码后上传,然后服务端解码 - 图片转base64上传
但是转换后的代码往往比源文件更大,所以只适合传递一些小文件
使用formdata对象上传文件。而且formdata可以直接整合表单信息统一上传。只是使用不灵活,
将整个请求完全交给浏览器,或许会出现请求超时
2.大文件上传
主要问题在于:大文件上传的时候,花费时间太长,如果发送失败,必须从头再来
切片上传
通过编码方式上传文件,通过slice方法对文件二进制内容进行切片处理,给每一个切片添加序号。服务端就可以还原切片了
断点续传
在上传一个文件的时候,如果出现意外,上传失败,下次上传时候,可以接着进度上传文件。可以通过xhr对象的方法检测文件时上传的进度,将其保存在本地,下载上传的时候从本地存储获得进度,重新开始上传
进度暂停和停止
可以通过xhr上的方法对文件上传进行一个暂停和继续
面 - 组件设计和状态设计
根据组件功能分析,设计适合这个组件的状态
- 状态设计
- 要用状态描述所有内容
- 数据要结构化,易于代码执行操作,适配组件使用
- 数据结构要是可拓展性的,比如数组和对象
- 切莫嵌套太深,遍历影响性能
- 组件设计
- 从功能层次拆分代码
- 尽量让组件原子化,一个组件负责一个功能,然后根据需求自由组合
- 区分容器组件(只负责数据,一般是顶层组件)和视图组件(只显示视图和用户交互)
设计步骤:
- 分析页面的功能,然后根据功能逐步拆分成组件
- 分析页面的组件的数据流,决定好数据结构和容器组件
1-vue的使用
1-1 插值表达式
插值表达式中只能访问data数据和部分全局变量,如Math,Date
1-2 指令
vue指令是vue框架对于一些操作的封装,在模板编译的时候,会解析成相对应的js代码执行,通过:接收参数,通过.添加修饰符,以完成不同 的操作。
常传的参数有:v-bind的属性名
常用的修饰符有:
-
处理数据修饰符
- .lazy懒同步,
- .number 数据转成数字类型同步到后台。
- .trim()去掉首尾空白。
- .once()
-
事件修饰符
- .stop() 阻止事件冒泡
- .prevent()阻止默认行为
- .once()事件只触发一次
- .self() 只能在自身触发,不能事件委托
- .capture()在捕获阶段触发
-
按键修饰符
- .键盘码
- .键盘别名
-
v-model
只是一个语法糖,内部封装了针对该元素的事件和属性的绑定。可以通过自定义model,完成很多操作,比如组件之间更方便的传值。
-
v-if 和 v-show
v-if底层是通过js判断改向vnode添加哪项节点,所以如果没有符合要求,该元素直接不会渲染。
v-show则是操作该元素的diaplay属性。
看情况使用两者
-
v-for 和 v-if
v-for 底层和react的列表渲染原理很像,遍历该数据,将该数据每一项转成一个有结构的数据类型,可以说是虚拟dom结构吧。。不能再同一个标签是同时使用这两个,v-for的优先级更高,
-
v-once
只解析一次
1-3计算属性 和 过滤器 和 监听属性
计算属性 - 多个数据影响一个数据
计算属性实质上,是对插值表达式的一个优化方案。将过重的插值表达式逻辑挂载在实例上,但是存在作用域问题。所以出现了过滤器。
而且计算属性对于某个计算结果,会进行缓存,若数据没有变化,多次计算直接返回缓存的值。同时对该数据设置setter和getter,当该数据发生变化时,计算属性能够检测到再重新计算。倘若长时间不调用计算属性,则缓存的空间会被释放。
-
初始化的时候
计算属性不会求值,然后当我们的 render 函数执行访问到 computed相关依赖 的时候,就触发了计算属性的 getter,它会拿到计算属性对应的 watcher,然后执行 watcher.depend(),然后再去求值。
-
初始化过后
当computed的依赖发生变化的时候,就触发了计算属性的 getter,通知所有订阅它变化的 watcher 更新,执行 watcher.update() 方法。如果页面中没有订阅computed的变化,就不会求值,当下次再访问这个计算属性的时候才会重新求值。
我们要记住这一点,不仅仅是计算属性依赖的值发生变化,而是当计算属性最终计算的值发生变化才会触发渲染 watcher 重新渲染。
监听属性 - 一个数据影响多个数据
监听属性,则是对data中的数据,设置了监听,当数据变化的时候,执行对应的函数,必要的时候还要开启深度监听,由于深度监听是递归监听到底,所以这个方法十分消耗性能,要谨慎使用。需要执行异步操作或者一些开销比较大的操作时候,监听属性更实用
计算属性其实和监听属性实现原理方面都是差不多的,vue的data挂载在实例上的时候,当数据变化后,先调用watcher观察者模式。然后调用计算属性和观察属性
每个的使用场景
watch 属性:适用于观测某个值的变化去完成一段复杂的业务逻辑。
computed 属性适合:用在模板渲染中,某个值是依赖了其它的响应式对象甚至是计算属性计算而来如果是一个属性,依赖多个属性变化的时候。当数据监听
过滤器:需要对全局数据进行某种操作的时候
1-4 生命周期
生命周期这个概念其实很抽象,我更原理理解为在组件某个阶段钩子函数的触发。
- 初始化阶段:将data数据挂载到vm实例中,对数据进行数据劫持。
-
beforeCreated 函数 - 是new Vue()后,触发的第一个钩子,当前所有的数据都不能访问
挂载vue-router / vuex
-
created函数 - 实例创建完成后,此时可以使用数据/但无法操作dom,除非使用$nextTick.
-
找html中的挂载节点,通过el属性或者手动$mount()设置
-
找用于渲染的模板
-
beforeMount - 挂载之前,此时模板已经导入渲染函数编译。虚拟dom已经创建完成。此时也可以对数据进行更改,不会触发update。
-
mounted函数,dom完成更新.完成数据双向绑定。可以用$ref获取dom
-
- 更新阶段:当data中依赖项使用的数据发生变化的时候,开始更新阶段
- beforeUpdate 函数 - 响应式数据发生更新,虚拟dom重新渲染前触发,此时修改数据,不会触发重渲染。
- update函数 : 通过虚拟dom进行diff算法对比,通过patch算法对新dom树进行操作,然后渲染出来
- 销毁阶段:从视图中销毁dom,释放子组件,事件监听器等资源,若组件销毁后,对应的事件没有销毁,会报错
- beforeDestroy 函数:实例销毁之前,此时还能操作实例
- destroyed函数:组件销毁完成
1-5 事件监听器
我们可以用$emit定义事件,可以被事件监听器监听到,事件监听函数甚至可以监听生命周期函数
- $on - 持续监听事件
- $once - 只监听一次事件
- $off - 停止监听事件
1-6 内置组件
<component />
<transition />
<Keep - alive />
<slot/>
2-vue高级特性
2-1 .$nextTick
vue在数据改变后,会对dom进行相对于的更新,而nextTick是在dom更新完成后触发的函数。处于减少dom操作次数的性能优化考虑,在一个宏任务里面的只要监听到了数据变化,vue会开启一个队列,并缓冲在这次宏任务中的所有数据变更,都会在最后整合成一次数据变化,达到重复数据修改的去重操作。然后更新虚拟dom,此时nextTick是在dom更新完成后触发的函数。处于减少dom操作次数的性能优化考虑,在一个宏任务里面的只要监听到了数据变化,vue会开启一个队列,并缓冲在这次宏任务中的所有数据变更,都会在最后整合成一次数据变化,达到重复数据修改的去重操作。然后更新虚拟dom,此时nextTick是在dom更新完成后触发的函数。处于减少dom操作次数的性能优化考虑,在一个宏任务里面的只要监听到了数据变化,vue会开启一个队列,并缓冲在这次宏任务中的所有数据变更,都会在最后整合成一次数据变化,达到重复数据修改的去重操作。然后更新虚拟dom,此时nextTick函数触发。所以一方面,我们的数据修改不能依赖上一个数据修改的值,另一方面,想要操作数据修改后的dom,要通过$nextTick函数好
原理:vue会根据当前浏览器环境,优先使用promise.then()和mutationObserver,如果不支持用settimeout代替
2-2 组件的name属性 - 递归组件
可以自己将自己注册成自己的子组件,用name属性调用,达到组件递归的效果。用v-if结束递归。
2-3 组件通信
vue组件之间是封闭的,不能互相访问数据,要想传输数据必须通过传递属性的方式传递。由于单项数据流,父组件数据更新时候,子组件接收的数据自动更新,而且父组件的传递的数据,只能父组件自己来修改。
- 父子:props,parent/parent/parent/children , provide / inject , ref , $attrs / $listeners
- provide / inject 注入依赖,在祖先组件中向后代组件注入数据,无论层级多深,子组件总能访问到该数据,在组件封装的时候,还是很好用的
- 兄弟组件:evenBus , vuex
- 跨级通信:evenBus , vuex , provide / inject , $attr / $listeners
面–父传子的生命周期
父组件给子组件传递数据的时候,
父组件开始更新 - 子组件1开始更新 - 子组件1更新完成- 子组件2开始更新 - 子组件2更新完成 - 父组件更新完成
面–父组件监听子组件的生命周期
方法1- 父组件向子组件传递一个函数,props值为生命周期函数名,子组件通过$emit()提交相应的生命周期函数
// Parent.vue
<Child @mounted=“doSomething”/>// Child.vue
mounted() {
this.$emit(“mounted”);
}
复制代码
复制代码方法2- 在父组件引用子组件时通过 @hook 来监听即可,如下所示:
// Parent.vue <Child @hook:mounted="doSomething" ></Child>doSomething() {console.log('父组件监听到 mounted 钩子函数 ...'); },// Child.vue mounted(){console.log('子组件触发 mounted 钩子函数 ...'); }, // 以上输出顺序为: // 子组件触发 mounted 钩子函数 ... // 父组件监听到 mounted 钩子函数 ... 复制代码 复制代码
当然 @hook 方法不仅仅是可以监听 mounted,其它的生命周期事件,例如:created,updated 等都可以监听。
2-3 slot插槽
插槽在我看来也是只是定制化组件时,让组件通信之间能够实现标签传递,提高组件的复用性和个性化。
根据使用方式不同分为匿名插槽,具名插槽和作用域插槽。
作用域插槽能根据子组件数据来定制化数据
面- 如何在vue中提取可复用的组件
一般我们在开发的时候,如果遇到组件在能在多处使用,或者多个组件需要使用同于一套处理逻辑。我们会考虑将其抽离提取成一个可复用的组件。
复用组件的三个核心api
- prop:接收外部组件传递的数据,定制化可复用的组件
- emit:可以提交触发事件函数
- slot:在可复用组件内根据外部组件传入的数据,定制化可复用的组件
2-4 动态组件
动态组件时根据条件的改变来操作组件的渲染情况,常见于is和v-for
<component :is = "组件名" /> //通过is来控制组件渲染// is属性配合v-for可以实现用动态组件通过数据结构来实现页面展示data:{0:{type:'text',msg:"1111"},1:{type:'img',msg:"2222"},2:{type:'text',msg:"333"}}<div v-for = "(val,key) in data">//根据数据结构的不同,展示不同的组件。<component :is = " value.type === 'text' ? 'textComponent' : 'imgComponent' "/></div>
2-5 异步组件
异步组件主要是针对大组件的加载较慢的问题,让他按需引入。如果不使用这个组件,则永远不加载。
在路由中:component:()=>{return ‘组件地址’}
在组件注册时候,组件地址写成:component:()=>{return ‘组件地址’}
2-6 缓存组件 keep - alive
keep- alive组件包裹组件是,若组件反复切换时候,组件的状态会被缓存下来。
没有缓存的组件每次切换展示的生命周期:mouted - destroy
缓存的组件每次切换展示的生命周期:只有第一次加载的时候会出现mouted,切换时,不会出现destroy
2-7 mixin
mixin挺像react里面的高级组件。将组件相同逻辑的内容抽离出来放置到一个配置对象里面。谁需要这个配置,就用mixin混入该配置选项。
mixin类似于extend继承方法,都是抽离出一个组件配置对象,然后混入,extend的先执行,extend的组件就叫做继承组件
问题:
1.mixin阅读不明确
2.多mixin会有冲突
3.mixin和组件之间存在多对多的关系,逻辑混乱
2-8 自定义指令
通过控制5个钩子函数来实现自定义指令
3-vue底层原理
3-1组件化(vue核心)
组件化并不是一个新鲜的词,前端的组件化是从后端发展过来,加以进化的。后端组件化,也能给组件注入数据,但是没办法做到通过参数定制组件。前端可以通过数据驱动视图来更好的控制和维护组件。
其中vue数据驱动视图的原理就是MVVM。
面–说说组件化工程化和模块化
- 工程化 将项目进行分析构建,达到开发的时候文件结构清晰,分工明确,提高开发效率的目的
- 组件化: 根据业务逻辑的不同,将重复的代码提取出来,合并成一个组件,在需要的使用该功能的地方使用该组件。侧重于业务的解耦。
- 模块化: 将分属于同一功能/业务的代码,单独封装成独立的模块,可以独立运行。在业务的框架层面来通过接口互相调用。降低业务模块之间的耦合。
相互之间的关系,组件化和模块化时工程化的具体体现,而组件往往用于模块中,处理业务模块的功能需求
3-2响应式(
响应式驱动时建立在object.defineProperty()和寄存器getter和setter方法实现的一直设计模型,这个设计模型里面有观察者和订阅者模式,这个设计模型的核心机制和vm模块
- 监听对象(Obeserver ,dep , watcher)
- 通过Observer给data中的每个属性转换成getter和setter的形式。object.defineProperty()
- 当视图元素通过触发watcher来向data里面获取数据,该元素就会被收集到getter里面的依赖项列表中。
- 当数据发生变化的时候,setter会监听到,遍历getter里面的依赖项列表,通过watcher来逐个通知依赖项更新数据
- 递归深度监听对象属性,递归到底,浪费性能
- 新增的数据,无法监听
- 监听数组
- 数组无法直接监听数据本身,因为数组是通过方法来改变数组的内容,所以我们只能监听操作数组的方法,来达到数组的数据的监听。
- 操作数据的方法基本都在数组原型上面,为了不污染全局数组原型,可以用object.creted()在数组实例和原型之间设置一个拦截器。监听拦截器里面的方法。
- 数组操作数据后,本身没有该方法,就顺着原型链往上查找,在找到数组原型之前,就在拦截器上找到了该方法。
- 拦截器上的方法一旦被使用,就会将这个依赖收集起来。
- 一旦数组数据变化,通知所以依赖项
- 只能监听数组的部分方法。
3-3 vdom 和 diff
-
虚拟Dom
由于原生的命令式dom操作十分消耗性能且不容易维护,vue是数据驱动视图,采用了vdom,js用树状对象来模拟dom的结构中的关键节点。将dom操作的计算放到js计算中。数据发生改变的时候,js计算出新旧dom的最小变更,然后一次性操作dom。这样会很大程度节省性能。
<div className = "father">我是div<li> 我是li标签</li> </div>const vDom = {tag:"div",props:{//属性对象className :"father"},children:["我是div",{tag:"li",props:[],children:['我是li标签']}] }
-
diff算法
diff算法用于在数据改变后,比较新旧vdom的数据结构,找出两个数据不同的地方,然后更新改变的节点。由于树数据结构的diff算法时间复杂度是O(n^3),所以vue里面的diff算法有三个规则:
- 只比较同一级别的节点,不跨级比较
- tag属性一旦不同,直接删除重建,不再深入比较
- tag和key相同时,直接认为时相同节点,不再深度比较,也不会动他。
-
vdom操作流程
模板标签 => h 函数 (创建虚拟dom)=> vnode函数 => vnode =>patch 函数(对比新旧dom) => 渲染页面
addvnodes函数 removenode函数
面- 为何要加上key
在进行diff算法的时候,能够快速标记不用遍历检查的vnode,减少性能消耗。在增删节点的时候,key能帮diff算法更加精准的定位要需要更新的位置。
3-4 模板编译
将vue模板转成能在js中操作的代码,js即可执行模板中的插值表达式,指令。
内部实现流程:
-
将模板解析成AST (解析器)
遍历整个模板,找到html标签,标记{{}}插值表达式
-
遍历AST找到{{}}插值表达式 (优化器)
标记解析{{}}插值表达式语法
-
生成渲染函数 (代码生成器)
解析完{{}}插值表达式生成渲染函数
渲染函数核心语法是
with
语法。包含插值表达式的表达式,可以直接访问data中的数据。<div v-if = " flag === true ">我是div标签 </div> //渲染函数 with(this){ //vm实例,每一个插值表达式都通过这样的形式访问vm数据return creatElement ('div'),[flag === true ? '我是div标签',' ' ] // 内部可以直接访问data中的数据 }
-
执行渲染函数,得到vnode
-
将vnode传入patch函数,将vnode渲染到dom节点中。
注:webpack使用vue-loader的时候,会自动编译模板。若没有提前编译,就要在浏览器中编译
3-5 组件更新 和 渲染过程
模板 => 模板编译 => 渲染函数 => vnode => 渲染页面
- 初次渲染流程
- 将模板解析为渲染函数
- 响应式系统收集数据依赖项
- 执行render函数,生成vnode
- 执行patch函数,渲染页面
- 更新阶段流程
- data数据变化触发setter
- 重新执行render函数,生成新的vnode
- patch函数对比新旧vnode,渲染
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7QFy0p5H-1598189226402)(C:\Users\ADMINI~1\AppData\Local\Temp\1591669577786.png)]
3-6 前端路由原理
vue路由是为了实现SPA(单页应用),vue是单页应用,所以当我们在页面进行一些操作改变路由的变化是,是不会向服务器发送请求的,浏览器监听到url的变化,从而更新页面。 有两种模式:
两种模式都是返回单页面应用,只是地址栏显示不一样。
1、hash 例如 juejin.im/#/index 多用于to B 业务的后台管理系统
hash模式是用window.hashchange的方法监听url,当URL的hash部分改变时,页面不会重新加载。并且向服务端发送的请求是https://juejin.im/部分
注意: 页面刷新的时候,不会向服务器发送请求
2、history 例如 [juejin.im/index 多用于toC的业务模式
history模式充分利用 history.pushStateAPI来完成URL跳转而无须重新加载页面。主要使用 history.pushState、history.popState和history.replaceState改变URL。使用history模式,我们需要在路由里面加这行代码mode:history,然后需要后端配置一个覆盖所有情况的候选资源:如果URL匹配不到任何静态资源,则应该返回同一个index.html页面,这个页面就是你 app 依赖的页面。
router.push、 router.replace 和 router.go 跟 window.history.pushState、 window.history.replaceState 和 window.history.go好像, 实际上它们确实是效仿 window.history API 的。
注意: 页面刷新的时候,会向服务器发送请求,而用此时的url向地址发送请求时,后来需要处理url返回根页面。
面- 如何实现vue-router切换页面后,保持在页面顶部/保持原先位置不变
vue-router提供了一个scrollBehavior,在切换路由额时候,可以控制页面是滚到底部还是保持原先位置。只在history模式下可以用。
4-相关插件
4-1 axios工具包
基于promise的http库,底层依赖是XMLHttpRequest
发送ajax的工具包,底层实际上是使用了promise异步实现的。
面–axios如何解决跨域问题?
axios不支持jsonp跨域,
针对后台不支持options,要么让后台使用cors插件,要我么自己写一个后台,进行反向代理
- 请求拦截器,统一处理axios的请求后,发送请求
- 响应拦截器,拿到响应数据后,先处理一遍
4-2 vuex
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。
(1)Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
(2)改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WUv4SEc5-1598189226402)(C:\Users\ADMINI~1\AppData\Local\Temp\1591768522198.png)]
核心
- state 为单一状态树,在state中需要定义我们所需要管理的数组、对象、字符串等等
- getters 类似vue的计算属性,主要用来过滤一些数据。
- mutation 更改store中state状态的唯一方法就是提交mutation,store.commit。
- action actions可以理解为通过将mutations里面处里数据的方法变成可异步的处理数据的方法,简单的说就是异步操作数据。view 层通过 store.dispath 来分发 action。
- module module其实只是解决了当state中很复杂臃肿的时候,module可以将store分割成模块,每个模块中拥有自己的state、mutation、action和getter。
面-- 页面刷新的时候数据丢失
- 使用本地存储vuex数据
- 使用插件
面 - vuex实现双向绑定
如果直接同时使用v-model绑定vuex中的数据,数据修改时会报错,因为state中的数据不是经过mutation修改的。
- 使用设有setter的计算属性绑定v-model,计算属性内部调用mutation方法
- 手动绑定state的值在value身上,然后监听事件,事件回调函数使用mutation的值修改state
4-3 vue-router
1-使用步骤
- 准备好路由组件
- 定制路由规则
- 挂载路由规则到组件上
2- 编程式导航
通过调用函数将hash值调入history栈中,用户后退也鞥返回。声明式导航内部调用了history栈
3-路由元信息
可以在路由跳转的时候存储信息
4-导航跳转流程
- 导航触发
- 在失活的组件中调用离开守卫
- 调用全局前置守卫(判断是否允许该用户访问前往的网页)
- 调用重用组件内的组件更新守卫
- 在路由配置中调用组件
- 解析异步路由
- 全局解析守卫
- 导航被确认
- afterEach函数调用
- dom更新
5- 获取路由跳转的信息
this.$route.query
this.$route.params
面 - 如何监听路由参数的变化
- 使用watch属性来监听hash值的变化
- 使用beforeRouteUpdate守卫
面 - 使用动态路由切换时候,组件没有变化,不会触发生命周期函数
- watch url的变化
- 为router - view 添加唯一的key为路由地址
面 - 实现路由解耦
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wsWEtTel-1598189226403)(C:\Users\ADMINI~1\AppData\Local\Temp\1591668715781.png)]
4-4 vue-loader
作用:1.vue-loader是webpage里面的一个加载器,主要用于解析提取vue文件里面的代码,比如逻辑代码js,样式代码style,已经html模板,再将他们交给对应的loader去处理。
2.提前对html模板进行模板编译
5- vue的性能优化
5-1 代码层面的优化
-
v-if 和 v-show 区分使用场景
-
computed 和 watch 区分使用场景
-
v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
-
长列表性能优化
-
事件的销毁
-
图片资源懒加载
-
路由懒加载
-
第三方插件的按需引入
-
优化无限列表性能
-
服务端渲染 SSR or 预渲染
5-2 Webpack 层面的优化
- Webpack 对图片进行压缩
- 减少 ES6 转为 ES5 的冗余代码
- 提取公共代码
- 模板预编译
- 提取组件的 CSS
- 优化 SourceMap
- 构建结果输出分析
- Vue 项目的编译优化
5-3 基础的 Web 技术的优化
- 开启 gzip 压缩
- 浏览器缓存
- CDN 的使用
- 使用 Chrome Performance 查找性能瓶颈
面- vue如何优化首屏加载速度
首屏加载数据,是指浏览器刚打开页面时候,出现的内容
- 使用CDN资源,减小服务器带宽压力
- 路由懒加载
- 将一些静态js css放到其他地方(如OSS),减小服务器压力
- 按需加载三方资源,如iview,建议按需引入iview中的组件
- 使用nginx开启gzip减小网络传输的流量大小
- 若首屏为登录页,可以做成多入口,登录页单独分离为一个入口
- 使用uglifyjs-webpack-plugin插件代替webpack自带UglifyJsPlugin插件
使用CDN资源,减小服务器带宽压力
- 在index.html中引入cdn资源
...<body><div id="app"></div><!-- built files will be auto injected --><script src="https://cdn.bootcss.com/vue/2.5.2/vue.min.js"></script><script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script><script src="https://cdn.bootcss.com/vuex/3.0.1/vuex.min.js"></script><script src="https://cdn.bootcss.com/vue-resource/1.5.1/vue-resource.min.js"></script></body>...
- 修改 build/webpack.base.conf.js
module.exports = {context: path.resolve(__dirname, '../'),entry: {app: './src/main.js'},externals:{'vue': 'Vue','vue-router': 'VueRouter','vuex':'Vuex','vue-resource': 'VueResource'},... }
- 修改src/main.js src/router/index.js 注释掉import引入的vue,vue-resource
// import Vue from 'vue' // import VueResource from 'vue-resource' // Vue.use(VueResource)
路由懒加载
require.ensure方式
const workCircle = r => require.ensure([], () => r(require('@/module/work-circle/Index')), 'workCircle') const workCircleList = r => require.ensure([], () => r(require('@/module/work-circle/page/List')), 'workCircleList')
import方式
const workCircle = () => import('@/module/work-circle/Index')
将一些静态js css放到其他地方(如OSS),减小服务器压力
注意这里的js文件,需要将结果抛出,然后在需要用到该js的组件中import引入
按需加载三方资源,如iview,建议按需引入iview中的组件
按需引用请查看iview官方文档iview
*使用nginx开启gzip减小网络传输的流量大小
React 知识点
1- react的使用
1-1 创建react元素的方式
- react.creatElement(标签名/组件名,属性对象,子元素 …)
- jsx语法(内部转换成React.creatElement())
1-2 jsx{ }嵌入式表达式
在jsx格式中,{}里面的内容会动态解析,由js执行。
1-3 条件渲染
react中的条件渲染,三种方式
- 在函数中通过条件判断,return哪种结构
- 用||和&&逻辑判断符号
- 用三元运算符
1-4列表渲染
需要知道的一点是,jsx中如果插入数组,数组的内容会全部展示在jsx中,渲染的每一项要加上key属性。
所以,可以通过map方法。将数组里面的每一项数据,来实现相对于的结构,然后后展示在jsx中。
1-5 组件
-
函数组件 (无状态组件)
函数组件是一个纯函数,输入props。输出jsx结构
-
类组件(有状态组件)
-
受控组件
表单元素里面的value/chencked值和state中的值绑定,配合onChange事件,得到输入的值,才能修改state值,表单才能正常显示数值。
受控组件的onChange函数可以总结为一个函数
-
非受控组件
不受state控制,没有和state绑定死值。
通过ref来实现操作该元素dom,拿到dom值
-
1-6 事件
-
事件对象
react用自己的操作事件的逻辑,对事件对象做了一个封装。
传参的时候,事件对象默认放在参数的最后一位
-
this指向
在JavaScript中,函数的传递,会让this指向丢失。
-
箭头函数调用内部函数
onClick ={ ()=> this.handleClick() } //直接在内部调用了事件函数,this借用了render的this
-
类实例方法
//用箭头函数将函数定义在实例上,函数内部使用的时constroctor中的this handleClick = (参数,event) => { console.log(this) }
-
bind返回一个绑定好this的函数
// 1.在事件函数绑定的时候使用bind onClick = this.handleClick.bind(this) //this绑定到了render里面的this// 2.在构造函数中bind好constroctor中的this , 不用每次使用的时候都bind返回一个数据 this.handleClick = this.handleClick.bind(this)
-
1-7 组件通信
-
props
props是组件父组件给子组件传递数据的一个集合,是一个对象。可以通过propType插件来校验和限制props数据的传递,子组件通过this.props得到传递数据的对象
父传子: 父组件通过给子组件标签添加属性,来传递任意类型数据。
子传父:父组件给子组件传入一个能改变自己值的函数。
非父子:状态提升,给组件a,传递数据,给组件b传递操作该数据的方法。
-
context
用于跨组件传递数据,生产者/消费者模型。
提供者组件为子组件提供数据,消费者组件的子组件能够使用这些数据
const {Provider , Consumer} = React.createContext
1-8 生命周期
-
创建阶段
-
constructor()
- 提供初始化数据
- 创建ref等元素挂载到实例身上
- 处理函数的this指向
-
render()
渲染视图
-
componentDidMount()
视图渲染完成
- 发送ajax请求
- 初始化dom操作
-
-
更新阶段
-
shouldComponentUpdate()
更加新旧的比较,来决定的该组件需不需要更新。setState/props更新/强制更新触发
-
render()
-
componentDidUpdate()
-
-
销毁阶段
不展示该组件
-
componentWillUnmount()
卸载完成前,需要手动清除自己添加的定时器和自定义事件
-
1-9 setState()
React中不能直接通过声明式修改state的数据,必须通过setstate更新state的数据。
-
作用
- 修改了state
- 更新了视图
-
特点
-
有时异步(react的普通使用),有时同步(定时器,自定义事件)
在react内部函数使用setstate时,数据异步更新(必须等到此次宏任务的微任务中执行)
-
有时合并更新(对象传入),有时不合并更新(函数传入)
第一个参数是函数的时候,不会合并更新,每次调用的时候,可以依赖于上一个setState的值,但是还是异步更新。
-
-
setState(更新的数据,回调函数)
这里的回调函数类似与vue中的nextTick,回调函数可以拿到最新的state值,在下一个宏任务最开始运行。
2- React 高级特性
2-1高阶组件(公共逻辑代码的抽离,minin已经弃用)
本质为一个函数,采用装饰设计模式,接收一个基础组件,输出一个增强后的组件,实现组件状态的复用。如果已经props穿透,可以多层嵌套。
// 基础组件
class Base extends React.Component{state = {money:0}render(){return <div><h1> 我是Base组件 - 我有{ this.props.money || this.state.money}</div></div>}
}// 高阶组件HOC
function WithMoney (Base){class AddMoney extends React.Component{state ={money:1000}render(){return <Base {...this.props} {...this.state}> </Base>}} renturn AddMoney
}//增强后Base组件
const BaseWithMoney = WithMoney(Base)
2-2 render - props (公共逻辑代码的抽离,mixin已经弃用)
定制一个组件,在这个组件里面完成一部分功能(逻辑/ui),而另外一个组件需要这个功能的时候,将公共组件作为父组件/子组件,传递/接收对方的功能。
//功能组件class AddMoney extends React.Component{state ={money:1000}render(){return this.props.children(this.state.money)}}
//样式组件
class Base extends React.Component{state = {money:0}render(){return <div><h1> 我是Base组件 - 我有{ this.props.money || this.state.money}</div></div>}
}//展示组件
class Home extends React.Component{render(){return <div><Money>(data)=><Base {...data}/></Money></div>}
}
2-3 Portals 传送门
在不改变组件嵌套的结构情况下,实现自定义该组件在哪个节点渲染
class Base extends React.Component{state = {money:0}render(){return <div><h1> 我是Base组件 - 我有{ this.props.money || this.state.money}</div></div>}
}
//该组件在文档自定义位置渲染,即使渲染位置变了,但是和父组件的练习没有改变,事件冒泡也能实现
export default ReactDOM.CreateProtals(<Base/>,document.文档任意节点)
2-4 异步组件
业务中的一些大组件不一定会被使用,如果同步加载,首屏加载时间延长,而且或许这个大组件根本用不到。
React中通过React.lazy达到异步加载组件的效果,使用React.suspense优化加载过程
//引入BigDemo组件
const BigDemo = React.lazy(()=>import("组件地址"))//加载大组件时展示的数据
<React.suspense fallback = { <div> Loading.....</div>}><BigDemo />
</React.suspense>
2-5 性能优化
代码层面优化
-
减轻state数据,非更新视图的数据不需要放在state中
-
优化state的数据结构,避免多层嵌套复杂数据类型
-
避免子组件的不必要更新
-
shouldComponentUpdate( nextprops,nextstate)
可以获取最新的props和state,和旧值作比较,若一样,则该组件不更新
-
使用纯组件(类组件)
内部自动浅层次比较新旧值
-
React.memo(函数组件,比较函数 )
-
-
多使用不可变值
immutable.js,让数据彻底成为不可变量。
基于数据共享,速度快,能达到深拷贝效果
-
长列表性能优化
-
事件的销毁
-
图片资源懒加载
-
路由懒加载
-
第三方插件的按需引入
-
优化无限列表性能
-
服务端渲染 SSR or 预渲染
Webpack 层面的优化
- Webpack 对图片进行压缩
- 减少 ES6 转为 ES5 的冗余代码
- 提取公共代码
- 模板预编译
- 提取组件的 CSS
- 优化 SourceMap
- 构建结果输出分析
- React项目的编译优化
- production自动开启代码优化、混淆、压缩
Web 技术的优化
- 在服务端开启 gzip 压缩
- 浏览器缓存
- CDN 的使用
- 使用 Chrome Performance 查找性能瓶颈
2-6 组件懒加载
1.代码分割 + import()
// 引入一个组件
import {add } from "./math"// 异步引入组件
// 触发import()函数时才异步导入
import("./math").then((math) =>{math.add()
})
当webpack解析到这个语法的时候,自动进行代码分割。
2.React.lazy() + Suspense
// 异步引入组件
//使用MyErrorBoundary包裹,更容易兼容错误
<MyErrorBoundary>//使用suspense组件包裹,更好的兼容等待页面<Suspense fallback={<div>Loading...</div>}>//在组件首次渲染的时候自动导入const Component = React.lazy(()=>{import("./math")})</Suspense>
</MyErrorBoundary>
3- React 核心原理
3-1函数式编程
一种编程范式,主要特征是使用纯函数和不可变量来实现数据驱动视图效果
- 纯函数:接收一个值,输出一个值,不产生其他副作用
- 不可变量:数据不能通过操作自身进行数据改变,setState设置的值只能是一个新值,原来的数据永远不能改变。
3-2 JSX编译
- jsx转译成React.creatElement函数,得到react元素
- render函数执行,得到vnode(描述dom节点的js对象)
- 通过path函数渲染
3-3 组件渲染过程 和 更新过程
-
渲染阶段
- 通过props/state获得数据
- render函数直接生成vnode
- patch函数接收vnode,渲染
-
更新阶段
- setsState(newvalue)
- render()根据newvalue得到newvnode
- patch函数(阶段一):得到vnode。执行diff算法,得到操作dom最少的更新方式
- patch函数(阶段二):将计算结果渲染到视图
**patch阶段的问题:**组件在更新阶段,计算和视图渲染都十分消耗性能,如果此时还有其他复杂dom操作(动画,拖拽),cpu压力很大,很有可能卡顿。
**fiber机制:**将patch第一阶段进行任务拆分。通过window.requestIndleCallback监听到dom是否更新,dom需要更新的时候,暂停diff算法。
3-4 合成事件机制
- 特点
- 所有的事件挂载到document中
- event事件对象不是原生的,是合成事件机制(SyntheticEvent函数)合成的事件对象。event.nativeEvent可以访问到原生的事件对象
- 和vue与原生的事件不同
- 处理流程
- 点击按钮,触发事件冒泡到document
- document挂载了React中的所有事件
- 通过合成事件函数生成合成事件
- 触发对应的事件处理函数
- 作用
- React内部实现一套自己的事件处理逻辑,更好的兼容性和跨平台
- 事件统一的挂载到document,减少内存消耗,解绑事件方便
- 方便事件的统一管理
3-5 setState 和 batchUpdate机制
setState执行流程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mBtei24i-1598189226405)(C:\Users\ADMINI~1\AppData\Local\Temp\1591758044422.png)]
在React内部采用transaction事务机制:
- 每个挂载在React中的函数,在执行前(入口)和执行结束(出口)都会执行一套处理逻辑
- 在挂载函数执行前,调用
isBatchUpdate = true
- 在挂载函数执行结束后,调用
isBatchUpdate = false
- 而在timeout和自定义事件回调函数执行的时候,isBathchUpdate已经是false,所以同步更新
面 - React和vue对比
-
相同
- 都采用组件化
- 都是数据驱动视图
- 都使用vdom操作dom
- 都通过props传递数据
-
使用方式不同
-
React使用Jsx拥抱js体验,vue采用模板拥抱html体验
-
React是函数式编程,vue式声明式编程
-
React只提供框架和核心驱动,vue封装了很多操作
-
React讲究状态不可变,vue提倡状态可变
-
webpack知识点
1. 什么是webpack,webpack的运行原理,如何打包 (字节跳动)
webpack是一个打包模块化javascript的工具,在webpack里一切文件皆模块,通过loader转换文件,通过plugin注入钩子,最后输出由多个模块组合成的文件,webpack专注构建模块化项目。 WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Scss,TypeScript等),并将其打包为合适的格式以供浏览器使用。
2.什么是bundle,什么是chunk,什么是module?
- bundle:是由webpack打包出来的最终的文件
- chunk:代码块,一个chunk由多个模块组合而成,用于代码的合并和分割
- module:是开发中的单个模块,在webpack的世界,一切皆模块,一个模块对应一个文件,webpack会从配置的entry中递归开始找出所有依赖的模块
3.什么是Loader?什么是Plugin?
-
loader
Loader直译为"加载器"。Webpack将一切文件视为模块,但是webpack原生是只能解析js文件,如果想将其他文件也打包的话,就会用到loader。 Loaders是用来告诉webpack如何转化处理某一类型的文件,并且引入到打包出的文件中
-
Plugin
Plugin直译为"插件"。Plugin可以扩展webpack的功能,让webpack具有更多的灵活性。 在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。
4. 有哪些常见的Loader?他们是解决什么问题的?
- file-loader:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件
- url-loader:和 file-loader 类似,但是能在文件很小的情况下以 base64 的方式把文件内容注入到代码中去
- source-map-loader:加载额外的 Source Map 文件,以方便断点调试
- image-loader:加载并且压缩图片文件
- babel-loader:把 ES6 转换成 ES5
- css-loader:加载 CSS,支持模块化、压缩、文件导入等特性
- style-loader:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS。
- eslint-loader:通过 ESLint 检查 JavaScript 代码
5. 有哪些常见的Plugin?
- define-plugin:定义环境变量
- html-webpack-plugin:简化html文件创建
- uglifyjs-webpack-plugin:通过UglifyES压缩ES6代码
- webpack-parallel-uglify-plugin: 多核压缩,提高压缩速度
- webpack-bundle-analyzer: 可视化webpack输出文件的体积
- mini-css-extract-plugin: CSS提取到单独的文件中,支持按需加载
6.webpack的构建流程是什么?从读取配置到输出文件这个过程尽量说全
Webpack 的运行流程是一个串行的过程,从启动到结束会依次执行以下流程:
- 初始化参数:从配置文件和 Shell 语句中读取与合并参数,得出最终的参数;
- 开始编译:用上一步得到的参数初始化 Compiler 对象,加载所有配置的插件,执行对象的 run 方法开始执行编译;
- 确定入口:根据配置中的 entry 找出所有的入口文件;
- 编译模块:从入口文件出发,调用所有配置的 Loader 对模块进行翻译,再找出该模块依赖的模块,再递归本步骤直到所有入口依赖的文件都经过了本步骤的处理;
- 完成模块编译:在经过第4步使用 Loader 翻译完所有模块后,得到了每个模块被翻译后的最终内容以及它们之间的依赖关系;
- 输出资源:根据入口和模块之间的依赖关系,组装成一个个包含多个模块的 Chunk,再把每个 Chunk 转换成一个单独的文件加入到输出列表,这步是可以修改输出内容的最后机会;
- 输出完成:在确定好输出内容后,根据配置确定输出的路径和文件名,把文件内容写入到文件系统。
7.如何利用webpack来优化前端性能?
-
压缩代码。删除多余的代码、注释、简化代码的写法等等方式。可以利用webpack的UglifyJsPlugin和ParallelUglifyPlugin来压缩JS文件, 利用cssnano(css-loader?minimize)来压缩css
-
利用CDN加速。在构建过程中,将引用的静态资源路径修改为CDN上对应的路径。可以利用webpack对于output参数和各loader的publicPath参数来修改资源路径
-
删除死代码(Tree Shaking)。将代码中永远不会走到的片段删除掉。可以通过在启动webpack时追加参数–optimize-minimize来实现
-
提取公共代码。将代码切片分组,公共代码更容易命中缓存
-
懒加载
将代码进行代码分割,一般都是分割需要懒加载的组件或者公共代码。然后组件加载方式为懒加载,再加载该组件
-
小图片编译成base64码
-
bundle命名加hash值,若文件内容不变,则可以命中缓存
-
使用production模式打包,内置了很多优化代码的配置:tree-sharking。es6引入时,执行前静态编译
-
scope Hosting:打包时,减少打包产生的作用域
8. 如何提高webpack的打包速度?
多进程打包压缩代码,忽视打包项,提前打包常用大型静态文件避免担反复编译,利用缓存,缩小编译搜索范围
- happypack插件和ParallelUglifyPlugin插件: 多进程打包和多进程压缩代码,还可以利用hash缓存避免重复不必要操作
- IgnorePlugin和nopare:都可以忽视一些没必要打包项
- dll: 采用webpack的 DllPlugin 和 DllReferencePlugin 引入dll,让一些基本不会改动的代码先打包成静态资源,避免反复编译浪费时间
- 利用缓存: webpack.cache、babel-loader.cacheDirectory、HappyPack.cache都可以利用缓存提高rebuild效率
- 缩小文件搜索范围: 比如babel-loader插件,如果你的文件仅存在于src中,那么可以include: path.resolve(__dirname, ‘src’),当然绝大多数情况下这种操作的提升有限,除非不小心build了node_modules文件
9. 介绍模块化发展历程
- 模块化主要是用来抽离公共代码,隔离作用域,避免变量冲突等。
- IIFE: 使用自执行函数来编写模块化,特点:在一个单独的函数作用域中执行代码,避免变量冲突。
- AMD: 使用requireJS 来编写模块化,特点:依赖必须提前声明好。
- CMD: 使用seaJS 来编写模块化,特点:支持动态引入依赖文件。
- CommonJS: nodejs 中自带的模块化。
- UMD:兼容AMD,CommonJS 模块化语法。
- webpack(require.ensure):webpack 2.x 版本中的代码分割。
- ES Modules: ES6 引入的模块化,支持import 来引入另一个 js 。
10.webpack 热更新原理
自动刷新,是整个网页刷新,状态丢失
热更新,新代码生效,网页不刷新,状态不丢失
热更新是使用了HMR插件,我没有仔细研究原理,但是猜测是监听了系统对这部分文件的保存操作的监听,然后执行更新,而插件内保存了网页的状态。
11-介绍一下babel
babel是一款JavaScript语言的编译器,他能将高es版本的语言规范转换成低版本。当然,高版本一些类似于promise等新增的低版本语言无法替换的新语法是无法转换的
babel 的处理流程:
- 词法解析,将字符串形式的代码转换成Tokens。
- 语法解析,解析器会把tokens转换成抽象语法树AST(核心数据结构)
- 遍历AST,并应用AST转换器,增删改查AST节点(访问者模式)-深度优先的查找原则。
- 根据新AST树,生成新代码
babel架构
访问者会以深度优先
的顺序, 或者说递归地对 AST 进行遍历,其调用顺序如下图所示:
上图中绿线
表示进入该节点,红线
表示离开该节点。
NODEJS知识点
nodejs是一个基于v8引擎的js的运行环境,标准的模块化开发环境,所有功能模块按需导入。
服务器返回html文档的过程:
- 服务器收到请求
- 解析url,了解请求数据
- 找到html文件,解析html文件成字符串格式,发送给客户端
1.模块分类
-
global模块(除了global模块,其他模块都要引入)
在任何地方都能调用
-
path模块
用于操作路径解决路径的兼容问题
-
fs模块
操作文件
-
http模块
- 创建一个服务器
- 监听请求响应
- 设置端口,启动服务器
-
art-template 模块
用于后台渲染
-
url模块
解析url地址
-
mysql模块
操作数据库
2.node模块类型
- 核心模块:随着node一起安装
- 第三方模块:下载引入的
- 自定义模块:自己创建的
3-中间件
项目架构中,保护后端的一种手段,用户只能访问中间件,中间件访问服务器。
中间件会辅助服务器处理部分请求,多个中间件串联使用通过next()进入下一个中间件处理功能
4-node事件循环机制 和 浏览器的事件循环机制
4-1 浏览器的事件循环机制
浏览器是多进程的:
- 主进程:创建和销毁其他进程
- GPU进程
- 第三方插件进程
- 浏览器内核渲染进程:每打开一个窗口就会创建一个
浏览器渲染进程包含多个线程
- GUI渲染进程:浏览器界面渲染
- js引擎线程 ------------主 线程 ----
- 事件触发线程
- 定时器触发线程 ----- 宏任务
- 异步请求线程
当浏览器js引擎这个主线程执行一段代码的时候,会遇到一些异步操作,就会把该任务交给相对应的线程来处理,主线程继续执行自己的代码任务,主线程和定时器线程做的任务称为宏任务( ui渲染/主代码/定时器)。若在宏任务期间一些工作线程的任务完成了,这些任务称之为微任务(promise,nexttick,事件回调)
那么主线程在进入下一个tick之前,会将这次tick产生的微任务执行玩。
这就是浏览器的执行机制。
node是单线程程序,通过异步i/O解决阻塞问题,更高效的使用cpu
node的事件循环机制和浏览器的,其实很类似,都是工作线程配合主线程来进行执行代码。只不过node是在线程池中处理异步任务。但是由于线程池的原因导致node执行微任务的时机和浏览器相比略有差别
浏览器环境下,microtask 的任务队列是每个 macrotask 执行完之后执行。而在 Node.js 中,microtask 会在事件循环的各个阶段之间执行,也就是一个宏任务中的六个阶段中的一个阶段执行完毕,就会去执行 microtask 队列的任务。
node和浏览器的事件循环机制大致逻辑是一样的,只是node的工作线程更为复杂,不同的线程之间还有执行优先级。
小程序
wechat运行在客户端系统,小程序运行在wechat上,h5的升级优化版。
面 - 小程序开发和vue开发的区别#$
小程序开发和vue开发十分类似,都是将一个组件的样式,结构,数据,插槽,而且都可以引入了指令,都是js统一管理。但是在数据驱动和生命周期上面区别挺大。
vue直接通过mvvm将数据和视图双向绑定,讲究可变值,且数据一变,视图立马更新。但是小程序不一样,小程序要想数据改变,视图里面改变,就要通过调用setdata()方法来调用
小程序真的很简单,官方给小程序给了很多限定,同时给给开发者很多便利。官方标签也就几个,还使用数据驱动视图。小程序页面和功能本来就简单,而且微信提供的接口多。小程序开发很简单的。但凡会一点vue的开发者。看几天文档,就会了。
编程范式:
- 编程式 - 手动通过js指令操作dom
- 声明式 - 通过操作数据,后台根据数据帮你操作dom
1-文件架构
- APP
- APP.js全局入口文件
- APP.json 全局配置文件
- APP.wxss 全局样式文件
- 每个组件
- .WXS 存储数据和生命周期函数 , WXS和js代码差不多,只是能够在WXML中运行WXS脚本而已
- .json 存储配置
- .WXML
- .WXSS
2- 双线程模型
- 渲染层线程
- js层线程
通过阻塞和等待响应来配合
3- 小程序执行流程
- 启动小程序
- 解析APP.json
- 注册APP()
- 执行APP组件生命周期
- 加载注册自定义组件
- 加载组件json文件
- 渲染层加载渲染结构文件
- 逻辑层加载js文件
- 执行生命周期
浏览器输入url后发生了什么(网络 / 浏览器)
这是一个好问题,其实细究起来里面的内容挺深的,里面涉及的内容很多。我试着把它讲清楚
基本流程
1.DNS地址查询
2.TCP连接
3.发送HTTP请求
4.服务器处理请求,以及响应
5.浏览器根据响应渲染页面
6.tcp连接结束
1-DNS地址查询
1.1什么是DNS
DNS全程是 Domain Name System 域名系统(服务)协议。 我们访问服务器时,其实访问的是该服务器的ip地址,但是ip地址很难记忆,考虑到访问的便捷性,就提出了DNS。DNS其实就是一个翻译的功能吧。他可以把网址翻译成对应的ip地址,我们就可以通过得到的ip地址访问了。
1-2 DNS查询
他的查询是一种是一层层查询的
-
查询浏览器缓存
从html5过后,浏览器的缓存就用的越来越多了,这时候呢,如果浏览器缓存中有对应的ip地址,整个过程就结束了。
不过因为浏览器的缓存机制,比如浏览器的缓存大小和缓存时间的限制,都会导致DNS解析失败。
-
查询系统的缓存
如果在系统的hosts文件里面设置了DNS映射。也可以完成域名解析。
不过如果本地hosts文件被恶意修改,就会访问到修改后的ip地址,造成域名劫持。
-
查找路由器的缓存
一般一些路由器也会缓存DNS
-
查找本地 DNS缓存服务器
根据网络配置中的DNS服务器地址,访问本地区的域名服务器。这个域名服务器缓存了大量的域名解析的结果,虽然也有时间控制。基本域名解析到这里可以完成。
-
递归查询DNS服务器
-
本地DN服务器会将查询域名的顶级域名服务器的IP地址返回到本地DNS
比如:com
-
本地DNS服务器再向顶级域发送请求,返回二级域的ip地址
比如:baidu
-
然后依次递归查询,直到得到最终的查询结果,将得到的ip地址返回本机
-
1-3 DNS中的安全问题
-
DNS欺骗
就是诱导用户去访问一个指定的ip地址
常见的就是缓存遭到了恶意修改。本机上的hosts文件呐,或者本地DNS服务器。可能造成的结果就是信息泄露啊。
-
对本地DNS服务器进行拒绝服务攻击
让本地DNS拒绝接受查询请求的服务,结果就是,无法上网
而且攻击DNS服务器的手段还挺多
1-4 DNS中的网络性能优化
1-减少DNS的查找次数,减少CDN的重定向(负载均衡)
服务器资源是分布式的,DNS可以就近返回一个服务器ip地址,这就是负载均衡和DNS重定向
CDN 内容分发网络
在各个地区建立缓存服务器,浏览器发送数据请求的时候,经过算法会经过延迟最低的,堵塞最低的网路,访问最近的服务器。而若该服务器没有请求需要的内容,就会发送回源。去往上一层服务器查找
虎牙和阿里云EMS联合
2-在html的meta标签和link标签告诉浏览器,对该页面做预解析
- 用meta信息来告知浏览器, 当前页面要做DNS预解析:
<meta http-equiv="x-dns-prefetch-control" content="on" />
- 在页面header中使用link标签来强制对DNS预解析:
<link rel="dns-prefetch" href="http://bdimg.share.baidu.com" />
2-TCP连接
2-1什么是tcp
tcp是一种可靠的数据传输协议.在网络传输中属于传输层面。
传输时候,包裹了http报文数据,被ip报文包裹。
数据建立连接时候,通过标识位,ACK,FIN,SYN等和对方计算机控制数据传输进程。
2-2 三次握手和四次挥手
1.三次握手
-
客户端发送SYN表示要和服务器建立连接,同时带上ISN序列号 :
SYN + 客户端序列号
-
服务器返回ACK(客户端序列号+1)表示以及收到SYN,同时发送SYN加上自己的序列号
ACK(客户端序列号+1)+服务端序列号
-
客户端发送ACK确认收到对方的回复:
ACK(服务端序列号+1)
2.为什么要三次握手?
确认双方都都能数据传输
- tcp是双向传输的协议,首先是确保双方都能接受和发送数据
- 第一次握手,表示发送方能够发送数据
- 第二次握手,ACK代表接受放能够收受数据,SYN确保接收方能够发送数据。
- 第三次握手:确保发送方能够接受数据
- 经过三次握手就能确定双方都有接受和发送的功能,就没必要四次,两次就实现不了了
握手的次要目的是告知和协商一些信息,****
- MSS–最大传输包
- SACK_PERM–是否支持Selective ack(用户优化重传效率)
- WS–窗口计算指数(有点复杂的话先不用管)
3.四次握手
- 客户端主动关闭的一方发送FIN,表示单方面要关闭数据的传输
- 服务端接收到FIN后,返回一个ACK表示收到
- 等到服务器的数据全部发送完成,也发送一个FIN。表示关闭数据传输
- 客户端回复ACK表示确认
4.为什么要四次挥手
- TCP是双向传输的,所以结束首先要确保双方都关闭了数据传输端口
- 同时TCP是支持半关闭的,一方结束发送,但是能够接收数据
- 因此接受和发送都要关闭,而且收到对方的关闭信息,还要确认回复
- 第一次,客户端发送关闭发送数据的FIN,表示自己没有数据要传送了
- 第二次,服务器表示收到,客户端进入等待状态,但是还需要继续发送数据给对方,不能,马上回复FIN
- 第三次,服务端发送数据全部发送完成的FIN,表示发送完全部数据,进入确定状态
- 第四次,客户端回复ACK表示收到,服务端收到ACK后里立马关闭传输接口。客户端则是处于等待,若短时间内没有再次收到服务端的FIN,则表示ACK以及送达,客户端关闭接口
5超时和重传
数据在传输时,存在一个数据丢失和网络拥堵问题。发送方在发送数据时候会启动一个计时器,如果在一定时间内没有收到对方的接受确定。会重新发送一份数据。如果接收方收到了两份相同的数据,会根据编号删除一份数据
但是超时重传会让本就拥堵的网络更加拥堵
6-tcp的可靠性如何保证
- 分块传送:数据被分割成最合适的数据块(UDP的数据报长度不变)
- 等待确认:通过定时器等待接收端发送确认请求,收不到确认则重发
- 确认回复:收到确认后发送确认回复(不是立即发送,通常推迟几分之一秒)
- 数据校验:保持首部和数据的校验和,检测数据传输过程有无变化
- 乱序排序:接收端能重排序数据,以正确的顺序交给应用端
- 重复丢弃:接收端能丢弃重复的数据包
- 流量缓冲:两端有固定大小的缓冲区(滑动窗口),防止速度不匹配丢数据
3-发送HTTP请求
3-1.什么是HTTP协议
数据传输的规范
Web使用一种名为HTTP(HyperText Transfer Protocol,超文本传输协议)的协议作为规范,完成从客户端到服务器等一系列运作流程。而协议是指规则的约定。可以说,Web是建立在HTTP协议上通信的。
3-2.HTTP连接方式
-
串行连接
每次一个请求都要经过请求连接,请求响应,结束连接。反应速度特别慢,容易达到浏览器的请求上限
-
持久连接
keep-alive模式
http 1.0中默认是关闭的,需要在http头加入"Connection: Keep-Alive”,才能启用Keep-Alive;http 1.1中默认启用Keep-Alive,如果加入"Connection: close “,才关闭。目前大部分浏览器都是用http1.1协议,也就是说默认都会发起Keep-Alive的连接请求了,所以是否能完成一个完整的Keep- Alive连接就看服务器设置情况。
建立连接后的一段时间可以进行多次请求。http1.1协议基本都是持久连接。但是由于一个请求结束才能进行下一个请求,容易造成请求堵塞
-
管道化持久连接
可以同时进行多次请求
-
HTTP 2.0多路复用
-
WebSocket
3-3.HTTP报文
1-报文格式
-
请求行
- 请求方法,协议版本
-
请求头部
- 请求URI,客户端信息,请求配置信息
-
请求体
- 用户信息,数据信息
-
响应行
- 协议版本,状态码
-
响应头部
- 请求服务器信息,资源配置信息
-
响应体
- 返回的资源
2-请求方式
GET - 获取服务器资源
POST - 信息传输
PUT -文件传输
DELETE - 删除文件
HEAD - 获取报文首部
3-常见的状态码
1-1XX 大多数表示请求收到,还在处理
100 :继续发送请求
101:需要切换HTTP协议。
2-2XX 请求已经被接受,理解
200:成功返回数据
201:请求成功,请求想要的资源已经创建
202
3-3XX 需要客户端进行下一步操作才能完成,一般为重定向
304:页面需要重定向
4- 4XX
客户端发生错误,导致服务器的处理。服务器一般会返回一个错误说明
400:语法错误,服务器理解不了,常见表单验证
401: 寻求用户的授权信息
402: 服务里理解请求,但是拒绝执行
404: 服务器上并没有请求需要的资源
5- 5XX 服务器端 发生异常
500 后台代码出错
502 代理服务器出错
3-4-HTTP版本
http1.1 比较 http1.0
缓存处理的方式更多
带宽和网络优化
错误通知的管理
Host管理
长连接
HTTP的版本更新只是在TCP连接等上面做了一系列优化,但是本质没有改变。他本质上还是让数据传输处明文传输的的状态。
-
信息可能被窃听,使用抓包工具
-
无法知道通信双方是谁,可能遭遇伪装
-
信息可能被中间人篡改,无法保证报文的完整性
3-5-HTTPS
1.什么是HTTPS
- 对数据进行加密,建立一个安全的信息通道,保证传输过程中的数据安全
- 对网站服务器进行真实身份验证
HTTPS是在THTTP基础上建立SSL加密层,并且对传输的数据进行加密,能确认数据传输双方信息的HTTP协议升级版
-
优势
- 数据隐私性:内容经过对称加密,每个连接生成唯一一个加密密钥
- 数据完整性:内容的传输经过完整性校验
- 身份认证:第三方无法伪造客户端(服务端)身份
利于seo
-
劣势
- 加密消耗CPU性能和内存
- 证书使用起来费时费钱
2- HTTPS功能实现
https实际上只是披上SSL协议的HTTP协议,通过SSL协议的优势弥补HTTP协议的缺陷。
1.内容被窃听问题 - 加密
方法一:对称性加密
这种加密方式的解密和加密都是用同一套密钥。问题在于,如何安全的将对称加密的密钥发给对象,让对方能够解密信息。
方式二:非对称加密
发送方有两套密钥,将公开密钥发送给接收方,接收方通过公开密钥加密数据,将信息返回。发送方又用私密密钥解锁数据。但是加密解密时间太长
公钥加密的内容,只有私钥可以解开,私钥加密的内容,所有的公钥都可以解开(当然是指和秘钥是一对的公钥)
方式三:对称加密+非对称加密
发送方通过对称加密,将数据进行加密。然后通过对方的非对称加密的公开密钥加密对称加密的密钥。然后将发送数据和密钥。
中间人能够劫持公钥,伪造假公钥发送
2.报文被篡改 - 数字签名
网络传输要经过很多的中间节点,数据虽然无法被解密,但是很有可能被篡改。
数字签名作用
- 能确定消息确实是由发送方签名并发出来的,因为别人假冒不了发送方的签名。
- 数字签名能确定消息的完整性,证明数据是否未被篡改过。
发送者通过哈希函数将一段文本转成消息摘要,再通过私钥加密成数字签名,将数字签名和文本原文发送。接收者解密数字签名生成消息摘要1,用哈希函数处理文本得到消息摘要2,对比两个消息摘要,来确保信息的完整性。
3-通信方身份伪装 - 数字证书
- 数字证书认证机构:通过服务端提供的信息进行认证,发布加密后的证书文件
- 客户端发送请求时,服务端返回数字证书文件。
- 客户端解密检查数字证书的信息。
3-4-带宽和延迟
影响一个 HTTP 网络请求的因素主要有两个:带宽和延迟。
- **带宽:**如果说我们还停留在拨号上网的阶段,带宽可能会成为一个比较严重影响请求的问题,但是现在网络基础建设已经使得带宽得到极大的提升,我们不再会担心由带宽而影响网速,那么就只剩下延迟了。
- 延迟:
-
- 浏览器阻塞(HOL blocking):浏览器会因为一些原因阻塞请求。浏览器对于同一个域名,同时只能有 4 个连接(这个根据浏览器内核不同可能会有所差异),超过浏览器最大连接数限制,后续请求就会被阻塞。
- DNS 查询(DNS Lookup):浏览器需要知道目标服务器的 IP 才能建立连接。将域名解析为 IP 的这个系统就是 DNS。这个通常可以利用DNS缓存结果来达到减少这个时间的目的。
- 建立连接(Initial connection):HTTP 是基于 TCP 协议的,浏览器最快也要在第三次握手时才能捎带 HTTP 请求报文,达到真正的建立连接,但是这些连接无法复用会导致每次请求都经历三次握手和慢启动。三次握手在高延迟的场景下影响较明显,慢启动则对文件类大请求影响较大。
4- 浏览器渲染页面
浏览器收到服务器返回的资源数据后,将资源渲染到浏览器窗口。主要功能就是向服务器发送请求,在浏览器窗口展示返回的网络资源。能够解析的资源必须符合W3C的规定,其他资源需要配置插件
4-1浏览器组成
- 用户界面:地址栏等除去主窗口以外的部分
- 浏览器引擎:在用户界面与渲染引擎之间传输指令
- 渲染引擎:展示请求的资源内容
- 网络:负责网络调用
- 用户界面后端
- js引擎:执行js代码
- 数据存储:持久层
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KNhsXWKD-1598189226416)(C:\Users\Administrator\Desktop\layers.png)]
4-2 浏览器如何解析资源渲染页面
浏览器解析资源是一个边解析边渲染的过程。主要通过渲染引擎和js引擎来处理网络资源
1.渲染引擎将html和css文档解析成语法树
将文档解析成有意义的结构,让浏览器能够使用
阶段一:词法分析
将文档输出解析成token单元
阶段二:语法分析
生成语法树
阶段三:将语法树编译成机器语言
2.渲染引擎将css语法树和html语法树结合成渲染树
3.渲染引擎和js引擎
当解析html文档遇到
4.触发浏览器的paint事件,根据渲染树计算元素位置,绘制
DOM节点中的各个元素都是以盒模型的形式存在,这些都需要浏览器去计算其位置和大小等,这个过程称为回流;当盒模型的位置,大小以及其他属性,如颜色,字体,等确定下来之后,浏览器便开始绘制内容,这个过程称为重绘。页面在首次加载时必然会经历reflow和repain。reflow和repain过程是非常消耗性能的,尤其是在移动设备上,它会破坏用户体验,有时会造成页面卡顿。所以我们应该尽可能少的减少reflow和repain。
5.回流和重绘
回流:浏览器在进行布局操作,进行位置计算的时候发生
重绘:浏览器根据属性渲染页面;
回流一定重绘
优化:
1、浏览器自己的优化:浏览器会维护1个队列,把所有会引起回流、重绘的操作放入这个队列,等队列中的操作到了一定的数量或者到了一定的时间间隔,浏览器就会flush队列,进行一个批处理。这样就会让多次的回流、重绘变成一次回流重绘。
2、我们要注意的优化:我们要减少重绘和重排就是要减少对渲染树的操作,则我们可以合并多次的DOM和样式的修改。并减少对style样式的请求。
**浏览器缓存
不过浏览器发送请求还有一种情况就是http缓存,也叫浏览器缓存。
浏览器和服务器通信的方式为应答模式,浏览器发送http请求 - 服务器响应该请求。
-
浏览器会根据第一次向浏览器发送请求后拿到的响应报文的响应头中的缓存标识来决定是否缓存结果,命中则将请求结果存入浏览器缓存中
-
浏览器下一次发送请求,会查看浏览器缓存有没有缓存此次请求的缓存结果
强缓存 : 浏览器的缓存数据,直接能够使用
协商缓存 : 浏览器的数据不确定是否可用
当浏览器查看浏览器缓存时,会发生几种情况:
- 不存在缓存结果和缓存标识,强缓存失效,直接向服务器发送请求
- 存在该缓存结果和缓存标识,但是此结果超过规定的时间限制已经失效,浏览器缓存返回缓存标识,携带缓存标识向浏览器发送请求,确认此缓存是否可用。
- 缓存能用,返回304,使用缓存
- 缓存不能用,返回200,使用新数据
浏览器离线缓存
HTML5提出的一个新的特性:离线存储。通过离线存储,我们可以通过把需要离线存储在本地的文件列在一个manifest配置文件中,这样即使在离线的情况下,用户也可以正常看见网页。
ajax请求和跨域问题
1- get 请求和get 请求的区别
get和post请求只是两种不同的传送请求的类型,底层都是tcp/ip协议。
- get请求的数据放在请求行中,post放在请求体中
- get发送请求的时候,会将请求头和包含数据的请求行直接一起发送出去;post发送请求时,会先发送请求头和请求行,间隔一段时间才会发送包含数据的请求体
- 网络好的时候,两者请求事件相差不大,网络差的时候post文件更不容易丢失
- get发送请求的数据有格式和大小(4k)的限制,post则没有限制
- get请求参数会保留在浏览器历史记录,post不会
2- 网络传输常用的数据格式
xml和json
xml
可拓展标记语言,能够传输数据
json
js对象标记,轻量级数据交换格式,本质上时特殊格式的字符串,包含了js的数据。
由于对象等一些属性,并不能通过网络传输,只能借助转成json格式的方式传输,使用时再转成对象数据模式。
json.stringfy(js数据)
json.parse(json字符串)
3- formdata 对象
以二进制的方式管理表单数据,用post方式,可以发送大体积文件。
可以通过xhr自带的方法监听上传和下载进度
4- 跨域 / 同源
-
同源:两个网站来自同一个服务器
- 域名相同
- 端口相同
- 协议相同
-
跨域:不同源网站,则跨域
- 不能共享cookie
- 不能相互操作dom
- 不能互相发送qjax请求
解决跨域
-
CORS
通过请求头和响应头来实现跨域资源访问,请求头中包含了请求来源的信息,若服务器同意访问,就可以在响应头中设置相对于的数据
- 简单,支持各种传输类型
- 要对服务端接口进行改造
-
JSONP
在html中,一些标签的资源请求不受同源策略的限制。比如
script
标签。这时候就可以哦那个过script标签的src属性发送请求,获得响应。- 兼容性好
- 只支持get请求,且安全性极低
-
正向代理 / 反向代理
委托能访问目标网站的中间服务器代为发送和接收数据
v8引擎的内存控制
v8使用的内存是有限制的,而进程需要内存时,才会一点点给他。
垃圾回收机制
**分代式回收机制:**按照对象的存活时间,将对象划在分代空间,老生代和新生代空间采用不同的算法处理数据。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7RxfMltW-1598189226423)(C:\Users\ADMINI~1\AppData\Local\Temp\1592199080930.png)]
倘若老生代空间的对象长时间没办法被回收,就造成了内存泄漏。
service worker
是独立于js线程的一个异步线程,不能访问dom和全局变量,他有着自己的全局作用域。可以用于存储和处理数据,多用于pwa(渐进式webapp)
性能优化
页面初始阶段加载慢,一般是资源加载过多过大,减少资源数量和资源大小
-
通过懒加载的方式来处理非首屏的图片和组件
-
小图标使用iconfont , 小图片直接使用base64编码置于html文档中等方式来实现资源合并
-
使用缓存和cdn来减少请求的时间和次数
-
css,js文件混淆压缩
-
图片压缩
-
在服务端开启gzip进行全部文件压缩
-
production模式自动内置优化,混淆+压缩
-
多命中缓存
-
减少网络请求
-
价绍资源体积
-
减少访问次数
-
用cdn
-
懒加载
-
防抖节流
WEB安全
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EOq4WwiW-1598189226424)(C:\Users\ADMINI~1\AppData\Local\Temp\1592382907762.png)]
1.xss攻击
1-1 xss介绍
跨站脚本攻击,简称XSS。是一种代码注入攻击。攻击者在目标网站注入恶意脚本,让他在浏览器运行,即可获得用户信息。
XSS 的本质是:恶意代码未经过滤,与网站正常的代码混在一起;浏览器无法分辨哪些脚本是可信的,导致恶意脚本被执行。
而由于直接在用户的终端执行,恶意代码能够直接获取用户的信息,或者利用这些信息冒充用户向网站发起攻击者定义的请求。
在部分情况下,由于输入的限制,注入的恶意脚本比较短。但可以通过引入外部的脚本,并由浏览器执行,来完成比较复杂的攻击策略。
1-2 恶意代码注入方式
- 用户的ugc信息,表单提交
- 第三方链接
- URL参数
- POST参数
- cookie
- refere
1-3 XSS攻击分类
-
存储型
存储型 XSS 的攻击步骤:
- 攻击者将恶意代码通过提交,放置到目标网站的数据库中。
- 用户打开目标网站,恶意代码也从数据库中提取出来,拼接到HTML中,返回到浏览器。
- 浏览器解析恶意代码。
- 恶意代码窃取用户信息,冒充用户进行操作
这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。
-
反射型
反射型XSS的攻击步骤
-
攻击者构造出特殊的url,包含恶意代码。
-
用户打开恶意代码的URL时,服务端提取URL中的恶意代码,拼接在返回html数据中
-
用户接收到响应数据,开始执行,就执行到了恶意代码。
-
恶意代码窃取用户信息,冒充用户进行操作
需要用户主动打开恶意的 URL 才能生效,攻击者往往会结合多种手段诱导用户点击,常见于网页搜索和跳转。
-
-
DOM型
DOM 型 XSS 的攻击步骤:
- 攻击者构造出特殊的 URL,其中包含恶意代码。
- 用户打开带有恶意代码的 URL。
- 用户浏览器接收到响应后解析执行,前端 JavaScript 取出 URL 中的恶意代码并执行。
- 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。
DOM 型 XSS 跟前两种 XSS 的区别:DOM 型 XSS 攻击中,取出和执行恶意代码由浏览器端完成,属于前端 JavaScript 自身的安全漏洞,而其他两种 XSS 都属于服务端的安全漏洞。
1-4XSS攻击预防
防护两大要素:
-
防止攻击者提交恶意代码
- 在前端过滤恶意代码。 不可行。攻击者可以绕过前端过滤,直接发送请求。
- 过滤后端写入数据库的数据 只能过滤数字,邮件地址等明确性的数据。否则会容易由于数据不确定性,引起乱码问题。
-
防止浏览器执行恶意代码(主要防护途径)
-
防止 HTML 中出现注入。存储型,反射型
方案一:纯前端渲染SSR
纯前端渲染的过程:
浏览器先加载一个静态 HTML,此 HTML 中不包含任何跟业务相关的数据。
然后浏览器执行 HTML 中的 JavaScript。
JavaScript 通过 Ajax 加载业务数据,调用 DOM API 更新到页面上。
方案二:对html进行转义
针对<>等特殊字符串
-
防止 JavaScript 执行时,执行恶意代码。
dom型避免将不可信的html插入到页面中,减少使用innerHTML等方法。
dom的一些事件监听器能够识别字符串当作代码执行。避免传递不可信的数据拼接到字符串,传递给这些API。比如onload,onerroe,href属性,定时器,eval()
-
表单输入长度控制。
-
验证码和cookie保护
-
避免拼接的内联事件。尽量使用事件绑定
-
避免拼接html,框架很大程度减少了攻击
-
2.CSRF攻击
2-1 CSRF介绍
CSRF 跨站请求伪造 :攻击者诱导用户进入第三方网页,窃取用户的信息,绕过被攻击网站的后台验证,来进行某些操作
流程 : 1. 用户登录网站A,保留了登录凭证(Cookie)
- 攻击者诱导受害者登录网站 B 。
3. 网站B通过用户浏览器向网站A服务器发送请求,自动携带用户的Cookie。
4. 网站A后台认为是用户在发送请求,正常执行请求
5. 攻击者借用用户的名义,进行操作
2-2 攻击类型
CSRF攻击简单来说就是冒充用户发送请求,所以能发送请求的操作都能成为它的攻击途径
- GET类型CSRF攻击
- POST类型CSRF攻击
- 链接请求类型的CSRF攻击:前两种情况,用户打开页面就会中招,这种需要用户额外点击
2-3 CSRF攻击特点
- 攻击一般由第三方网站发起,由于冒充用户,被攻击网站无法阻止攻击发生
- 不是窃取用户数据,而是借助Cookie冒充用户提交请求
- 可以用任何跨域请求达到攻击效果
2-4 防护策略
防护策略只能从增强网站的安全性出发,因为后台无法识别这种攻击。根据CSRF攻击特点,指定的方式有:
- 阻止不明外域的访问
- 同源检测
- Samesite Cookie
- 提交时要求附加本域,才能获取信息
- CSRF Token
- 双重Cookie
同源检测防护
通过检测前端请求的Origin Header 和Referer Header来确定请求的来源。检测不到或者不是本域发起的请求,直接阻止这次请求
双重Cookie验证
由于攻击的不能获取Cookie,只是冒用,所以不能发送双重Cookie
-
在用户访问网站页面时,向请求域名注入一个Cookie,内容为随机字符串(例如
csrfcookie=v8g9e4ksfhw
)。 -
在前端向后端发起请求时,取出Cookie,并添加到URL的参数中(接上例
POST https://www.a.com/comment?csrfcookie=v8g9e4ksfhw
)。 -
后端接口验证Cookie中的字段与URL参数中的字段是否一致,不一致则拒绝。
实行成本低
Token防护
通过token字段登录网站。网站开发的时候,面对请求时,手动添加Token,而不是浏览器自动添加。在我看来是最有效而简单的操作方式。除非有XSS攻击泄露了XSS,那么CSRF很难攻击成功。
Samesite Cookie属性
防止CSRF攻击的办法已经有上面的预防措施。为了从源头上解决这个问题,Google起草了一份草案来改进HTTP协议,那就是为Set-Cookie响应头新增Samesite属性,它用来标明这个 Cookie是个“同站 Cookie”,同站Cookie只能作为第一方Cookie,不能作为第三方Cookie
2-5 CSRF 测试
CSRFTester是一款CSRF漏洞的测试工具
3.点击劫持攻击
在WEb页面隐藏了一个透明的iframe元素,诱导用户点击,进行一些不知名操作
4.后端一些攻击漏洞:命令行注入和DDos攻击
DDos攻击:不断发送请求,让网站响应崩溃
面 - 开发中的数据安全问题
前端的安全问题主要发生在代码的安全问题,用户在浏览器操作上的安全问题,和网络传输的安全问题
代码的安全问题
- 规范开发,避免使用引起xss攻击的代码
- 警惕使用第三方提供的页面组件,这些页面组件一般通过iframe方式引入天气等插件。其实这个模块不受我们控制的,很容易造成安全隐患。
- 防范本地内存泄漏,特别是离线应用和spa页面,这些都在本地保存了很多隐私数据,此时如果有xss攻击,意味着数据全部透明了。可以设置用户离开清除数据、数据加密后保存等方式,但是也只是降低了一点风险。
- 还可以通过代码混淆来保护代码吧
网络传输的安全问题
- 有时候出于性能考虑使用CDN,这时候攻击者就可以劫持cdn资源,进行不法操作
- 由于http协议的裸奔性,任何一个节点的抓包工具都能获取,所以更应该使用https协议和token字段
开发项目知识点
yarn
相比于npm的优势
-
采用多线程下载,下载速度更快
-
yarn更加安全稳定
GIT
项目管理工具
常用的使用指令
git log
git reset 回到某个版本号
git branch 创建切换分支
git checkout -b 创建并切换分支
git merge 提交后合并分支
git clone
git push
git pull
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g0XdhDfL-1598189226425)(C:\Users\ADMINI~1\AppData\Local\Temp\1592400824612.png)]
抓包工具
fiddler
linux基本指令
- 本地登录线上机器:SSH 用户名@ip地址
- 查看所有文件夹: ll / ls
- 查看隐藏文件夹:ll -a
- 查看指令文件:ls 文件名
- 创建文件夹: mkdir 文件夹名
- 创建文件: touch 文件名
- 创建并打开文件 : vim 文件名
- 删除文件夹: rm -rf 文件夹名
- 前往文件夹: cd
- 重命名文件夹: mv
- 拷贝:cp 源文件夹名
开发流程
- 需求分析
- 了解背景
- 需求是否合理
- 需求是否闭环
- 开发难度
- 是否需要其他支持
- 结合小组项目给出排期
- 技术方案分析
- 技术求简,只要能实现就行
- 写出产出开发文档
- 找准设计重点
- 开发
- 排期多流出一点时间
- 符合公司开发规范
- 写开发文档
- 及时写单元测试
- mock api 模拟数据
- code review 同事看一下
- 联调
- pm加需求
- 重新评估排期
- pm加需求
- 测试
- 上线
短信验证码和图片验证码
-
图片验证码
后台随机生成一串验证码,返回给客户端,用户输入验证码。发送请求后,后台验证用户是否存在以及验证码是否匹配,若都验证正确,则返回登录成功
-
短信验证码
输入手机号码,提交给后台,后台验证手机号码是否注册。通过一套规则生成验证码,然后将短信码和手机号给运营平台,给用户发送验证码。
后台接收到验证码后,检测是否和后台的验证码匹配
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OeXExIQH-1598189226426)(C:\Users\ADMINI~1\AppData\Local\Temp\1592301482820.png)]
移动端的兼容(安卓和iOS手机)
只有少数情况需要判断操作 基本你就正常写就行
兼容问题自己不常见到 大家记住几个 面试问就说一下 如果面试官说的你不懂?我没有遇见这个很正常
兼容问题 有很多版本都不一样 安卓 ios也有不一样 我们遇见了再去百度解决 如果面试 先记住几个
1 怎么判断是安卓还是 ios**
//获取浏览器的userAgent,并转化为小写
var ua = navigator.userAgent.toLowerCase();
//判断是否是苹果手机,是则是true
var isIos = (ua.indexOf('iphone') != -1) || (ua.indexOf('ipad') != -1);
if(isIos){做苹果手机兼容
}else{做安卓
}
2 兼容问题
1.禁止图片点击放大
部分安卓手机点击图片会放大,如需要禁止放大,只需要设置css属性
img{ pointer-events: none;
}
这个会让img标签的点击事件失效,如果想要给图片添加点击事件就要给上面再写一层
2.禁止 iOS 识别长串数字为电话
<meta name="format-detection" content="telephone=no">
3.禁止复制、选中文本
设置CSS属性 -webkit-user-select:none
4.一些情况下对非可点击元素如(label,span)监听点击事件,不会在IOS下触发,css增加cursor:pointer就搞定了
5.上下拉动滚动条时卡顿、慢
body {
-webkit-overflow-scrolling: touch;
overflow-scrolling: touch;
}
Android3+和iOS5+支持CSS3的新属性为overflow-scrolling
6 安卓不会自动播放视频
安卓autoplay没效果 需要手动触发一下
window.addEventListener('touchstart', function(){audio.play(); // 需要主动调用一下js 让视频播放
}, false);
7.半透明的遮罩层改为全透明
在ios上,当点击一个链接或者通过js绑定了点击事件的元素时,会出现一个半透明的背景,当手指离开屏幕,该灰色背景消失,出现“闪屏”
html, body {-webkit-tap-highlight-color: rgba(0,0,0,0);
}
html进行转义**
针对<>等特殊字符串
-
防止 JavaScript 执行时,执行恶意代码。
dom型避免将不可信的html插入到页面中,减少使用innerHTML等方法。
dom的一些事件监听器能够识别字符串当作代码执行。避免传递不可信的数据拼接到字符串,传递给这些API。比如onload,onerroe,href属性,定时器,eval()
-
表单输入长度控制。
-
验证码和cookie保护
-
避免拼接的内联事件。尽量使用事件绑定
-
避免拼接html,框架很大程度减少了攻击
2.CSRF攻击
2-1 CSRF介绍
CSRF 跨站请求伪造 :攻击者诱导用户进入第三方网页,窃取用户的信息,绕过被攻击网站的后台验证,来进行某些操作
流程 : 1. 用户登录网站A,保留了登录凭证(Cookie)
- 攻击者诱导受害者登录网站 B 。
3. 网站B通过用户浏览器向网站A服务器发送请求,自动携带用户的Cookie。
4. 网站A后台认为是用户在发送请求,正常执行请求
5. 攻击者借用用户的名义,进行操作
2-2 攻击类型
CSRF攻击简单来说就是冒充用户发送请求,所以能发送请求的操作都能成为它的攻击途径
- GET类型CSRF攻击
- POST类型CSRF攻击
- 链接请求类型的CSRF攻击:前两种情况,用户打开页面就会中招,这种需要用户额外点击
2-3 CSRF攻击特点
- 攻击一般由第三方网站发起,由于冒充用户,被攻击网站无法阻止攻击发生
- 不是窃取用户数据,而是借助Cookie冒充用户提交请求
- 可以用任何跨域请求达到攻击效果
2-4 防护策略
防护策略只能从增强网站的安全性出发,因为后台无法识别这种攻击。根据CSRF攻击特点,指定的方式有:
- 阻止不明外域的访问
- 同源检测
- Samesite Cookie
- 提交时要求附加本域,才能获取信息
- CSRF Token
- 双重Cookie
同源检测防护
通过检测前端请求的Origin Header 和Referer Header来确定请求的来源。检测不到或者不是本域发起的请求,直接阻止这次请求
双重Cookie验证
由于攻击的不能获取Cookie,只是冒用,所以不能发送双重Cookie
-
在用户访问网站页面时,向请求域名注入一个Cookie,内容为随机字符串(例如
csrfcookie=v8g9e4ksfhw
)。 -
在前端向后端发起请求时,取出Cookie,并添加到URL的参数中(接上例
POST https://www.a.com/comment?csrfcookie=v8g9e4ksfhw
)。 -
后端接口验证Cookie中的字段与URL参数中的字段是否一致,不一致则拒绝。
实行成本低
Token防护
通过token字段登录网站。网站开发的时候,面对请求时,手动添加Token,而不是浏览器自动添加。在我看来是最有效而简单的操作方式。除非有XSS攻击泄露了XSS,那么CSRF很难攻击成功。
Samesite Cookie属性
防止CSRF攻击的办法已经有上面的预防措施。为了从源头上解决这个问题,Google起草了一份草案来改进HTTP协议,那就是为Set-Cookie响应头新增Samesite属性,它用来标明这个 Cookie是个“同站 Cookie”,同站Cookie只能作为第一方Cookie,不能作为第三方Cookie
2-5 CSRF 测试
CSRFTester是一款CSRF漏洞的测试工具
3.点击劫持攻击
在WEb页面隐藏了一个透明的iframe元素,诱导用户点击,进行一些不知名操作
4.后端一些攻击漏洞:命令行注入和DDos攻击
DDos攻击:不断发送请求,让网站响应崩溃
面 - 开发中的数据安全问题
前端的安全问题主要发生在代码的安全问题,用户在浏览器操作上的安全问题,和网络传输的安全问题
代码的安全问题
- 规范开发,避免使用引起xss攻击的代码
- 警惕使用第三方提供的页面组件,这些页面组件一般通过iframe方式引入天气等插件。其实这个模块不受我们控制的,很容易造成安全隐患。
- 防范本地内存泄漏,特别是离线应用和spa页面,这些都在本地保存了很多隐私数据,此时如果有xss攻击,意味着数据全部透明了。可以设置用户离开清除数据、数据加密后保存等方式,但是也只是降低了一点风险。
- 还可以通过代码混淆来保护代码吧
网络传输的安全问题
- 有时候出于性能考虑使用CDN,这时候攻击者就可以劫持cdn资源,进行不法操作
- 由于http协议的裸奔性,任何一个节点的抓包工具都能获取,所以更应该使用https协议和token字段
开发项目知识点
yarn
相比于npm的优势
-
采用多线程下载,下载速度更快
-
yarn更加安全稳定
GIT
项目管理工具
常用的使用指令
git log
git reset 回到某个版本号
git branch 创建切换分支
git checkout -b 创建并切换分支
git merge 提交后合并分支
git clone
git push
git pull
[外链图片转存中…(img-g0XdhDfL-1598189226425)]
抓包工具
fiddler
linux基本指令
- 本地登录线上机器:SSH 用户名@ip地址
- 查看所有文件夹: ll / ls
- 查看隐藏文件夹:ll -a
- 查看指令文件:ls 文件名
- 创建文件夹: mkdir 文件夹名
- 创建文件: touch 文件名
- 创建并打开文件 : vim 文件名
- 删除文件夹: rm -rf 文件夹名
- 前往文件夹: cd
- 重命名文件夹: mv
- 拷贝:cp 源文件夹名
开发流程
- 需求分析
- 了解背景
- 需求是否合理
- 需求是否闭环
- 开发难度
- 是否需要其他支持
- 结合小组项目给出排期
- 技术方案分析
- 技术求简,只要能实现就行
- 写出产出开发文档
- 找准设计重点
- 开发
- 排期多流出一点时间
- 符合公司开发规范
- 写开发文档
- 及时写单元测试
- mock api 模拟数据
- code review 同事看一下
- 联调
- pm加需求
- 重新评估排期
- pm加需求
- 测试
- 上线
短信验证码和图片验证码
-
图片验证码
后台随机生成一串验证码,返回给客户端,用户输入验证码。发送请求后,后台验证用户是否存在以及验证码是否匹配,若都验证正确,则返回登录成功
-
短信验证码
输入手机号码,提交给后台,后台验证手机号码是否注册。通过一套规则生成验证码,然后将短信码和手机号给运营平台,给用户发送验证码。
后台接收到验证码后,检测是否和后台的验证码匹配
[外链图片转存中…(img-OeXExIQH-1598189226426)]
移动端的兼容(安卓和iOS手机)
只有少数情况需要判断操作 基本你就正常写就行
兼容问题自己不常见到 大家记住几个 面试问就说一下 如果面试官说的你不懂?我没有遇见这个很正常
兼容问题 有很多版本都不一样 安卓 ios也有不一样 我们遇见了再去百度解决 如果面试 先记住几个
1 怎么判断是安卓还是 ios**
//获取浏览器的userAgent,并转化为小写
var ua = navigator.userAgent.toLowerCase();
//判断是否是苹果手机,是则是true
var isIos = (ua.indexOf('iphone') != -1) || (ua.indexOf('ipad') != -1);
if(isIos){做苹果手机兼容
}else{做安卓
}
2 兼容问题
1.禁止图片点击放大
部分安卓手机点击图片会放大,如需要禁止放大,只需要设置css属性
img{ pointer-events: none;
}
这个会让img标签的点击事件失效,如果想要给图片添加点击事件就要给上面再写一层
2.禁止 iOS 识别长串数字为电话
<meta name="format-detection" content="telephone=no">
3.禁止复制、选中文本
设置CSS属性 -webkit-user-select:none
4.一些情况下对非可点击元素如(label,span)监听点击事件,不会在IOS下触发,css增加cursor:pointer就搞定了
5.上下拉动滚动条时卡顿、慢
body {
-webkit-overflow-scrolling: touch;
overflow-scrolling: touch;
}
Android3+和iOS5+支持CSS3的新属性为overflow-scrolling
6 安卓不会自动播放视频
安卓autoplay没效果 需要手动触发一下
window.addEventListener('touchstart', function(){audio.play(); // 需要主动调用一下js 让视频播放
}, false);
7.半透明的遮罩层改为全透明
在ios上,当点击一个链接或者通过js绑定了点击事件的元素时,会出现一个半透明的背景,当手指离开屏幕,该灰色背景消失,出现“闪屏”
html, body {-webkit-tap-highlight-color: rgba(0,0,0,0);
}