Html5新特性?
<! DOCTYPE >声明
canvas绘图
增强型表单
视频和音频
SVG绘图
地理定位
拖放API
WebWorker
WebStorage
WebSocket
css选择器优先级顺序是什么?
important > 行内样式 > id选择器 > 类选择器 > 标签选择器 > 子代选择器 >后代选择器 > 伪类选择器
css3新特性?
新增选择器(属性选择器,伪类选择器,伪元素选择器)
盒子模型border-box
![](https://i-blog.csdnimg.cn/blog_migrate/8561ebfd9a773c60db7bb10508bd6826.png)
filter滤镜
transition过度
transform2D转换
动画animation
垂直居中的方法有哪些?
伪类和伪元素的区别?
伪类存在于dom文档中,无法被dom树选中,伪元素:不存在于dom文档中是一个虚拟元素
三行省略方法?
display:webkit-box;-webkit-box-curanten:vartatical,-webkit-line-clamp:3
浏览器从输入url到前端页面展示发生了什么?
浏览器在本地查找域名的ip地址;
浏览器与服务器建立tcp连接;
浏览器发送请求;
某些服务会做永久重定向;
浏览器会跟踪重定向地址;
服务器处理请求发出HTML响应;
释放tcp连接;
浏览器显示页面
tcp的三次握手?
第一次握手:客户端TCP进程也先建立传输控制块TCB,然后向服务端发送连接请求报文段,此时SYN=1,随机选定一个初始序号seq=x,,此报文不能携带数据,但是要消耗掉一个序号,发送完毕后,客户端进入SYN-SENT(同步已发送)状态
第二次握手:服务端收到客户端请求连接报文段后,若同意建立连接,则发送确认报文,确认报文中SYN=1、ACK=1,确认号ack=x+1,同时随机选定一个自己序号seq=y,确认报文段同样不能携带数据,但是也要消耗掉一个序号,发送完毕后服务端进入SYN-RCVD(同步收到)状态
第三次握手:客户端收到确认报文后,检查ACK=1,ack=x+1是否正确,若正确,则向服务端发送确认报文,确认报文中ACK=1,ack=y+1,seq=x+1,发送后进入ESTAB-LISHED状态,服务端收到确认报文后,也进入ESTAB-LISHED状态,此时双方TCP连接正式建立。
$set原理?
$set是在vue原型上添加$set方法,针对以下三种情况分别进行处理。
1.当key已经存在于target上的时候,直接修改target中对应key的值;
当target是数组的时候,借助vue内部拦截处理后数组的splice方法进行赋值,vue对数组的原生方法进行拦截处理成响应式,调用这些方法,可以触发界面的更新(后续添加这部分解说),如果只是通过arr[2]=2的方式进行赋值不会触发视图更新
对于新增的属性,通过defineReactive把数据转化成getter和setter的方式,并触发数据变化通知
$nextTic原理?
将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。
new干了那几件事?
创建一个空对象,将它的引用赋给 this,继承函数的原型
通过 this 将属性和方法添加至这个对象
返回 this 指向的新对象,如果没有手动返回其他的对象
BFC是什么?
BFC是块级格式化上下文,是指浏览器中创建了一个独立的渲染区域,并且拥有一套渲染规则,他决定了其子元素如何定位,以及与其他元素的相互关系和作用.
重绘:只改变自身样式,不会影响到其他元素
回流:当我们对 DOM 的修改引发了 DOM 几何尺寸的变化时,浏览器需要重新计算元素的几何属性然后再将计算的结果绘制出来.
node中的事件循环和浏览器中的事件循环有什么区别?
浏览器事件循环机制中,微任务的任务队列是在每个宏任务执行完之后执行。Node事件循环机制中,微任务会在事件循环的各个阶段之间执行。
vue中created钩子里面如何获取DOM元素?
this$nextic(()=>{获取dom}) setTimeOut(()=>{获取dom},time)
vue父子组件生命周期?
加载渲染:父beforeCreate —> 父created —> 父beforeMount —> 子beforeCreate —> 子created —> 子beforeMount —> 子mounted —> 父mounted
更新数据:父beforeUpdate —> 子beforeUpdate —> 子updated —> 父updated
销毁:父beforeDestroy —> 子beforeDestroy —> 子destroyed —> 父destroyed
Vuex、localStorage、sessionStorage和cookie的区别?
vuex:vuex的数据存储在内存中,保密性较高.组件之间传值,响应式
缺点:刷新页面(这里的刷新页面指的是--> F5刷新,属于清除内存了)时vuex存储的值会丢失
2.localStorage:存放的数据大小一般为20Mb生命周期永久生效,除非手动删除否则关闭页面也会存在
同浏览器的不同页面间可以共享相同的localStorage,页面之间传值,非响应式.
3.sessionStorage:存放的数据大小一般为5Mb同源页面数据可共享
缺点:数据随着窗口关闭而清除
4.cookie:存放的数据大小一般为4kb,cookie 可以设置有效时间,如果不设置有效期,那么他默认是随着窗口关闭而清除
缺点:Cookie存储于浏览器,可以被篡改,服务器接收后必须先验证数据的合法性
Vue项目优化:
Vue 代码层面的优化
v-if 和 v-show 区分使用场景
computed 和 watch 区分使用场景(computed: 当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算.
watch: 当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作)
v-for 遍历必须为 item 添加 key. 且避免同时使用 v-if
图片资源懒加载(使用vue-lazyload 插件)
第三方插件的按需引入
webpack 配置层面的优化
Webpack 对图片进行压缩
减少 ES6 转为 ES5 的冗余代码
提取公共代码
基础的 Web 技术层面的优化
开启 gzip 压缩(gizp压缩是一种http请求优化方式,通过减少文件体积来提高加载速度。html、js、css文件甚至json数据都可以用它压缩,可以减小60%以上的体积)
浏览器缓存
浏览器缓存机制
强缓存
协商缓存
vue有哪几种路由守卫?
beforeEach 前置路由守卫
afterEach 后置路由守卫
beforeRouterEnter 进入组件前触发
beforeRouteUpdate 路由更新但是内容不会改变
beforeRouteLeave 离开前触发
vue双向绑定原理?
通过objest.defineproperty()劫持数据的set和get方法,再结合发布订阅模式来实现
vue2.0与vue3.0响应式原理对比?
vue3.0采用Proxy代理整个对象
Proxy优势:
可以直接监听整个对象而非属性;
可以直接监听数组的变化;
有13中拦截方法,如ownKeys、deleteProperty、has 等是 Object.defineProperty 不具备的;
返回的是一个新对象,我们可以只操作新的对象达到目的,而Object.defineProperty只能遍历对象属性直接修改;
proxy 的拦截方式,除了上面的 get 和 set ,还有 11 种拦截方式;
Object.defineProperty 的优势如下:
兼容性好,支持 IE9,而 Proxy 的存在浏览器兼容性问题
引入插件
npm install px2rem-loader -S
npm install postcss-px2rem -S
npm i lib-flexible -S
在根目录新建文件vue.config.js
// 引入等比适配插件
const px2rem = require('postcss-px2rem')
// 配置基本大小
const postcssRem = px2rem({
// 基准大小 baseSize,需要和rem.js中相同
remUnit: 16
})
module.exports = {
publicPath: "./",
lintOnSave: true,
css: {
loaderOptions: {
postcss: {
plugins: [
postcssRem
]
}
}
}
}
在src下新建util/flexible.js文件
(function(win, lib) {
var doc = win.document;
var docEl = doc.documentElement;
var metaEl = doc.querySelector('meta[name="viewport"]');
var flexibleEl = doc.querySelector('meta[name="flexible"]');
var dpr = 0;
var scale = 0;
var tid;
var flexible = lib.flexible || (lib.flexible = {});
if (metaEl) {
console.warn('将根据已有的meta标签来设置缩放比例');
var match = metaEl.getAttribute('content').match(/initial\-scale=([\d\.]+)/);
if (match) {
scale = parseFloat(match[1]);
dpr = parseInt(1 / scale);
}
} else if (flexibleEl) {
var content = flexibleEl.getAttribute('content');
if (content) {
var initialDpr = content.match(/initial\-dpr=([\d\.]+)/);
var maximumDpr = content.match(/maximum\-dpr=([\d\.]+)/);
if (initialDpr) {
dpr = parseFloat(initialDpr[1]);
scale = parseFloat((1 / dpr).toFixed(2));
}
if (maximumDpr) {
dpr = parseFloat(maximumDpr[1]);
scale = parseFloat((1 / dpr).toFixed(2));
}
}
}
if (!dpr && !scale) {
var isAndroid = win.navigator.appVersion.match(/android/gi);
var isIPhone = win.navigator.appVersion.match(/iphone/gi);
var devicePixelRatio = win.devicePixelRatio;
if (isIPhone) {
// iOS下,对于2和3的屏,用2倍的方案,其余的用1倍方案
if (devicePixelRatio >= 3 && (!dpr || dpr >= 3)) {
dpr = 3;
} else if (devicePixelRatio >= 2 && (!dpr || dpr >= 2)){
dpr = 2;
} else {
dpr = 1;
}
} else {
// 其他设备下,仍旧使用1倍的方案
dpr = 1;
}
scale = 1 / dpr;
}
docEl.setAttribute('data-dpr', dpr);
if (!metaEl) {
metaEl = doc.createElement('meta');
metaEl.setAttribute('name', 'viewport');
metaEl.setAttribute('content', 'initial-scale=' + scale + ', maximum-scale=' + scale + ', minimum-scale=' + scale + ', user-scalable=no');
if (docEl.firstElementChild) {
docEl.firstElementChild.appendChild(metaEl);
} else {
var wrap = doc.createElement('div');
wrap.appendChild(metaEl);
doc.write(wrap.innerHTML);
}
}
function refreshRem(){
var width = docEl.getBoundingClientRect().width;
if (width / dpr > 540) {
width = width * dpr;
}
var rem = width / 100;
docEl.style.fontSize = rem + 'px';
flexible.rem = win.rem = rem;
}
win.addEventListener('resize', function() {
clearTimeout(tid);
tid = setTimeout(refreshRem, 300);
}, false);
win.addEventListener('pageshow', function(e) {
if (e.persisted) {
clearTimeout(tid);
tid = setTimeout(refreshRem, 300);
}
}, false);
if (doc.readyState === 'complete') {
doc.body.style.fontSize = 12 * dpr + 'px';
} else {
doc.addEventListener('DOMContentLoaded', function(e) {
doc.body.style.fontSize = 12 * dpr + 'px';
}, false);
}
refreshRem();
flexible.dpr = win.dpr = dpr;
flexible.refreshRem = refreshRem;
flexible.rem2px = function(d) {
var val = parseFloat(d) * this.rem;
if (typeof d === 'string' && d.match(/rem$/)) {
val += 'px';
}
return val;
}
flexible.px2rem = function(d) {
var val = parseFloat(d) / this.rem;
if (typeof d === 'string' && d.match(/px$/)) {
val += 'rem';
}
return val;
}
})(window, window['lib'] || (window['lib'] = {}));
在main.js里面引入即可
import './util/flexible.js'
方法二,其他vue项目,pc端屏幕自适应的方法:
第一步 安装lib-flexible
npm i lib-flexible --save
第二步 在项目入口文件main.js中引入lib-flexible
import 'lib-flexible/flexible.js'
第三步 在项目根目录的index.html 头部删除自动生成的meta标签, lib-flexible会根据屏幕自动生成相对于的meta标签
// 删除
<meta name="viewport" content="width=device-width, initial-scale=1.0">
第四步 使用postcss-pxtorem,用于将像素单元生成rem单位。
//安装依赖
npm install postcss-pxtorem -D
第五步 设置规则(在package.json中配置如下)
"postcss": {
"plugins": {
"autoprefixer": {},
"postcss-pxtorem": {
"rootValue": 64,
"propList": [
"*"
]
}
}
}
//另一种可以新建postcss.config.js,写入如下代码
module.exports = {
plugins: {
// 兼容浏览器,添加前缀
autoprefixer: {
overrideBrowserslist: [
"Android 4.1",
"iOS 7.1",
"Chrome > 31",
"ff > 31",
"ie >= 8",
"last 10 versions", // 所有主流浏览器最近10版本用
],
grid: true,
},
"postcss-pxtorem": {
rootValue: 16, //结果为:设计稿元素尺寸/16,比如元素宽320px,最终页面会换算成 20rem
propList: ["*"], //是一个存储哪些将被转换的属性列表,这里设置为['*']全部,假设需要仅对边框进行设置,可以写['*', '!border*']
unitPrecision: 5, //保留rem小数点多少位
//selectorBlackList: ['.radius'], //则是一个对css选择器进行过滤的数组,比如你设置为['fs'],那例如fs-xl类名,里面有关px的样式将不被转换,这里也支持正则写法。
replace: true, //这个真不知到干嘛用的。有知道的告诉我一下
mediaQuery: false, //媒体查询( @media screen 之类的)中不生效
minPixelValue: 12, //px小于12的不会被转换
},
},
}