对于做前端的朋友,或者做了前端几年了,基础不好的,或者想进大厂的想了解深入,下面的知识点很多前端朋友都没有深入了解。很重要,看完有种茅塞顿开感觉,**关注+收藏哦,总有一天用的得。**
涉及到知识点:HTML知识,JS,ES5/ES6,Vue, Webpack, 前端HTTP网络知识,css/css3。
持续整理更新中
js部分
面试官:JS的数据类型都有哪些?
ES5的5种:Null,undefined,Boolean,Number,String, ES6新增:Symbol表示独一无二的值
ES10新增:BigInt 表示任意大的整数
null 和 undefined 的区别?
在 if 语句中 null 和 undefined 都会转为false两者用相等运算符比较也是相等
首先 Undefined 和 Null 都是基本数据类型,这两个基本数据类型分别都只有一个值,就是 undefined 和 null。
不同:
undefined 代表的含义是未定义,
定义了形参,没有传实参,显示undefined
一般变量声明了但还没有定义的时候会返回 undefined
对象属性名不存在时,显示undefined
函数没有写返回值,即没有写return,拿到的是undefined
null 代表的含义是空对象。也作为对象原型链的终点
null 主要用于赋值给一些可能会返回对象的变量,作为初始化。
js数据类型的判断方式有哪些?
1.typeof
缺点:typeof null的值为Object,无法分辨是null还是Object
2.instanceof
缺点:只能判断某对象是否存在于目标对象得的原型链上
3.constructor
4.Object.prototype.toString.call()
一种最好的基本类型检测方式 Object.prototype.toString.call() ;它可以区分 null 、 string 、
boolean
、 number
、 undefined
、 array
、 function
、 object
、 date
、 math
数据类型。
缺点:不能细分为谁谁的实例
// -----------------------------------------typeof
typeof undefined // 'undefined'
typeof '10' // 'String'
typeof 10 // 'Number'
typeof false // 'Boolean'
typeof Symbol() // 'Symbol'
typeof Function // ‘function'
typeof null // ‘Object’
typeof [] // 'Object'
typeof {} // 'Object'
// -----------------------------------------instanceof
function Foo() { }
var f1 = new Foo();
var d = new Number(1)
console.log(f1 instanceof Foo);// true
console.log(d instanceof Number); //true
console.log(123 instanceof Number); //false -->不能判断字面量的基本数据类型
// -----------------------------------------constructor
var d = new Number(1)
var e = 1
function fn() {
console.log("ming");
}
var date = new Date();
var arr = [1, 2, 3];
var reg = /[hbc]at/gi;
console.log(e.constructor);//ƒ Number() { [native code] }
console.log(e.constructor.name);//Number
console.log(fn.constructor.name) // Function
console.log(date.constructor.name)// Date
console.log(arr.constructor.name) // Array
console.log(reg.constructor.name) // RegExp
//-----------------------------------------Object.prototype.toString.call()
console.log(Object.prototype.toString.call(undefined)); // "[object Undefined]"
console.log(Object.prototype.toString.call(null)); // "[object Null]"
console.log(Object.prototype.toString.call(123)); // "[object Number]"
console.log(Object.prototype.toString.call("abc")); // "[object String]"
console.log(Object.prototype.toString.call(true)); // "[object Boolean]"
function fn() {
console.log("ming");
}
var date = new Date();
var arr = [1, 2, 3];
var reg = /[hbc]at/gi;
console.log(Object.prototype.toString.call(fn));// "[object Function]"
console.log(Object.prototype.toString.call(date));// "[object Date]"
console.log(Object.prototype.toString.call(arr)); // "[object Array]"
console.log(Object.prototype.toString.call(reg));// "[object RegExp]"
面试官:==
和===
有什么区别?
===
是严格意义上的相等,会比较两边的数据类型和值大小
- 数据类型不同返回false
- 数据类型相同,但值大小不同,返回false
==
是非严格意义上的相等,
- 两边类型相同,比较大小
- 两边类型不同,根据下方表格,再进一步进行比较。
- Null == Undefined ->true String == Number ->先将String转为Number,在比较大小
- Boolean == Number ->现将Boolean转为Number,在进行比较 Object ==
- String,Number,Symbol -> Object 转化为原始类型
面试官:NaN === NaN返回什么?
返回 false
,NaN
永远不等于NaN
,判断是否为NaN
用一个函数 isNaN
来判断;
isNaN
传入的如果是其他数据类型,那么现将它使用Number()
转为数字类型在进行判断
深拷贝和浅拷贝是什么,区别在哪?
浅拷贝主要是对指针的拷贝,拷贝后两个指针指向同一个内存空间,深拷贝需要不但对指针进行拷贝,并对指针指向的内容进行拷贝,经过深拷贝后的指针是指向两个不同地址的指针。
代码方式理解和使用:
// ----------------------------------------------浅拷贝
// 只是把对象的属性和属性值拷贝到另一个对象中
var obj1 = {
a: {
a1: { a2: 1 },
a10: { a11: 123, a111: { a1111: 123123 } }
},
b: 123,
c: "123"
}
// 方式1
function shallowClone1(o) {
let obj = {}
for (let i in o) {
obj[i] = o[i]
}
return obj
}
// 方式2
var shallowObj2 = { ...obj1 }
// 方式3
var shallowObj3 = Object.assign({}, obj1)
let shallowObj = shallowClone1(obj1);
shallowObj.a.a1 = 999
shallowObj.b = true
console.log(obj1); //第一层的没有被改变,一层以下就被改变了
// ----------------------------------------------深拷贝
// 简易版
function deepClone(o) {
let obj = {}
for (var i in o) {
// if(o.hasOwnProperty(i)){
if (typeof o[i] === "object") {
obj[i] = deepClone(o[i])
} else {
obj[i] = o[i]
}
// }
}
return obj
}
var myObj = {
a: {
a1: { a2: 1 },
a10: { a11: 123, a111: { a1111: 123123 } }
},
b: 123,
c: "123"
}
var deepObj1 = deepClone(myObj)
deepObj1.a.a1 = 999
deepObj1.b = false
console.log(myObj);
// 简易版存在的问题:参数没有做检验,传入的可能是 Array、null、regExp、Date
function deepClone2(o) {
if (Object.prototype.toString.call(o) === "[object Object]") { //检测是否为对象
let obj = {}
for (var i in o) {
if (o.hasOwnProperty(i)) {
if (typeof o[i] === "object") {
obj[i] = deepClone(o[i])
} else {
obj[i] = o[i]
}
}
}
return obj
} else {
return o
}
}
function isObject(o) {
return Object.prototype.toString.call(o) === "[object Object]" || Object.prototype.toString.call(o) === "[object Array]"
}
// 继续升级,没有考虑到数组,以及ES6中的map、set、weakset、weakmap
function deepClone3(o) {
if (isObject(o)) {//检测是否为对象或者数组
let obj = Array.isArray(o) ? [] : {}
for (let i in o) {
if (isObject(o[i])) {
obj[i] = deepClone(o[i])
} else {
obj[i] = o[i]
}
}
return obj
} else {
return o
}
}
// 有可能碰到循环引用问题 var a = {}; a.a = a; clone(a);//会造成一个死循环
// 循环检测
// 继续升级
function deepClone4(o, hash = new map()) {
if (!isObject(o)) return o//检测是否为对象或者数组
if (hash.has(o)) return hash.get(o)
let obj = Array.isArray(o) ? [] : {}
hash.set(o, obj)
for (let i in o) {
if (isObject(o[i])) {
obj[i] = deepClone4(o[i], hash)
} else {
obj[i] = o[i]
}
}
return obj
}
// 递归易出现爆栈问题
// 将递归改为循环,就不会出现爆栈问题了
var a1 = { a: 1, b: 2, c: { c1: 3, c2: { c21: 4, c22: 5 } }, d: 'asd' };
var b1 = { b: { c: { d: 1 } } }
function cloneLoop(x) {
const root = {};
// 栈
const loopList = [ //->[]->[{parent:{a:1,b:2},key:c,data:{ c1: 3, c2: { c21: 4, c22: 5 } }}]
{
parent: root,
key: undefined,
data: x,
}
];
while (loopList.length) {
// 深度优先
const node = loopList.pop();
const parent = node.parent; //{} //{a:1,b:2}
const key = node.key; //undefined //c
const data = node.data; //{ a: 1, b: 2, c: { c1: 3, c2: { c21: 4, c22: 5 } }, d: 'asd' } //{ c1: 3, c2: { c21: 4, c22: 5 } }}
// 初始化赋值目标,key 为 undefined 则拷贝到父元素,否则拷贝到子元素
let res = parent; //{}->{a:1,b:2,d:'asd'} //{a:1,b:2}->{}
if (typeof key !== 'undefined') {
res = parent[key] = {};
}
for (let k in data) {
if (data.hasOwnProperty(k)) {
if (typeof data[k] === 'object') {
// 下一次循环
loopList.push({
parent: res,
key: k,
data: data[k],
})
} else {
res[k] = data[k];
}
}
}
}
return root
}
function deepClone5(o) {
let result = {}
let loopList = [
{
parent: result,
key: undefined,
data: o
}
]
while (loopList.length) {
let node = loopList.pop()
let { parent, key, data } = node
let anoPar = parent
if (typeof key !== 'undefined') {
anoPar = parent[key] = {}
}
for (let i in data) {
if (typeof data[i] === 'object') {
loopList.push({
parent: anoPar,
key: i,
data: data[i]
})
} else {
anoPar[i] = data[i]
}
}
}
return result
}
let cloneA1 = deepClone5(a1)
cloneA1.c.c2.c22 = 5555555
console.log(a1);
console.log(cloneA1);
// ------------------------------------------JSON.stringify()实现深拷贝
function cloneJson(o) {
return JSON.parse(JSON.stringify(o))
}
// let obj = { a: { c: 1 }, b: {} };
// obj.b = obj;
// console.log(JSON.parse(JSON.stringify(obj))) // 报错 // Converting circular structure to JSON
深拷贝能使用hash递归的方式写出来就可以了
不过技多不压身,推荐还是看一看使用while实现深拷贝方法
面试官:为什么JS是单线程的?
**答:**因为JS里面有可视的Dom,如果是多线程的话,这个线程正在删除DOM节点,另一个线程正在编辑Dom节点,导致浏览器不知道该听谁的
面试官:说说 Promise 的原理?你是如何理解 Promise 的?
promise是一个对异步操作进行封装并返回其结果的构造函数. 使代码更加简洁和避免回调地狱。
promise是浏览器引擎自带的(但不是所有浏览器都支持promise)
Promise是异步编程的一种解决方案,可以替代传统的解决方案–回调函数和事件。ES6统一了用法,并原生提供了Promise对象。作为对象,Promise有一下两个特点: * (1)对象的状态不受外界影响。 * (2)一旦状态改变了就不会在变,也就是说任何时候Promise都只有一种状态。
Promise有三种状态,分别是:**Pending **(进行中), ** Resolved (已完成), Rejected ** (已失败)。Promise从Pending状态开始,如果成功就转到成功态,并执行resolve回调函数;如果失败就转到失败状态并执行reject回调函数。
基本用法
var promise = new Promise(function(resolve,reject)
setTimeout(function(){
console.log("hello world");},2000);
});
function greet(){
var promise = new Promise(function(resolve,reject){
var greet = "hello world";
resolve(greet);
});
return promise;
}
greet().then(v=>{
console.log(v);//*
})
function greet(){
var promise = new Promise(function(resolve,reject){
var greet = "hello world";
resolve(greet);
});
return promise;
}
var p = greet().then(v=>{
console.log(v);
})
console.log(p);
面试官:async 和await 理解,以下代码的执行顺序是什么?
关于async
async 其实就是promise的语法糖。函数前面必须加一个async,异步操作的方法前加一个await 关键字。顾名思义,就是让你等一下,执行完了再继续往下走。注意:await 只能在async函数中执行,否则会报错
关于await
await的意思就是等待。它后面可以跟一个表达式。如果是值(如字符串、数字、普通对象等等)的话,返回值就是本身的值。 通常使用方式为在后面跟一个promise对象。await会等待这个promise的状态由pending转为fulfilled或者rejected。在此期间它会阻塞,延迟执行await语句后面的语句。
如果promise对象的结果是resolve,它会将resolve的值,作为await表达式的运算结果。
async function async1() {
console.log('async1 start')
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2')
}
async1()
console.log('script start')
//执行到await时,如果返回的不是一个promise对象,await会阻塞下面代码(当前async代码块的代码),会先执行async外的同步代码(在这之前先看看await中函数的同步代码,先把同步代码执行完),等待同步代码执行完之后,再回到async内部继续执行
//执行到await时,如果返回的是一个promise对象,await会阻塞下面代码(当前async代码块的代码),会先执行async外的同步代码(在这之前先看看await中函数的同步代码,先把同步代码执行完),等待同步代码执行完之后,再回到async内部等promise状态达到fulfill的时候再继续执行下面的代码
//所以结果为
//async1 start
//async2
//script start
//async1 end
面试官:var let const 有什么区别⭐⭐⭐⭐⭐
答:
-
var
- var声明的变量可进行变量提升,let和const不会
- var可以重复声明
- var在非函数作用域中定义是挂在到window上的
-
let
- let声明的变量只在局部起作用
- let防止变量污染
- 不可在声明
-
const
- 具有let的所有特征
- 不可被改变
- 不可改变只适用于直接地址。如果使用const声明的是对象的话,是可以修改对象内部的值的。
模块化
面试官:为什么要使用模块化?都有哪几种方式可以实现模块化,各有什么特点?⭐⭐⭐
为什么要使用模块化
- 防止命名冲突
- 更好的分离,按需加载
- 更好的复用性
- 更高的维护性
面试官:exports
和module.exports
有什么区别?⭐⭐⭐
导出方式不一样
- exports.xxx=‘xxx’
- module.export = {}
exports是module.exports的引用,两个指向的是用一个地址,而require能看到的只有module.exports
面试官:JS模块包装格式有哪些?⭐⭐⭐
commonjs
- 同步运行,不适合前端
AMD
- 异步运行
- 异步模块定义,主要采用异步的方式加载模块,模块的加载不影响后面代码的执行。所有依赖这个模块的语句都写在一个回调函数中,模块加载完毕,再执行回调函数
CMD
- 异步运行
- seajs 规范
面试官:ES6和commonjs的区别
Commonjs、AMD、CMD、UMD、ESM 都有什么区别
问:require 和 import的区别?
调用时机
require 是运行时调用,所以其实是可以放在任何地方的
Import 是编译时调用,所以必须放在文件的开头
使用时,
require 需要使用 module.exports = fs 或者exports.fs = xxx
import 用 export default 或 export const xx
解构赋值
require 是赋值的过程
import 是解构的过程
面试官:箭头函数和普通函数的区别?箭头函数可以当做构造函数 new 吗?
- 箭头函数是普通函数的简写,但是它不具备很多普通函数的特性
- 第一点,this指向问题,箭头函数的this指向它定义时所在的对象,而不是调用它的对象 不会进行函数提升
- 没有arguments对象,不能使用arguments,如果要获取参数的话可以使用rest运算符
- 没有yield属性,不能作为生成器Generator使用
- 不能new
- 没有自己的this,不能调用call和apply
- 没有prototype,new关键字内部需要把新对象的_proto_指向函数的prototype
js 遍历数组的方法⭐⭐⭐⭐⭐
reduce、map、filter、every、some、foreach.
数组可以改变原数组的方法⭐⭐⭐⭐⭐
Push、pop、shift、unshift、splice、sort、reverse
不改变的
join 变成字符
Slice,截取
concat 合并数组
foreach 和 map 有什么区别⭐⭐⭐⭐
foreach 没有返回值,一般如果用来遍历修改原数组的话可以用 foreach 方法
localstorage 怎么存储图片⭐⭐⭐⭐
创建一个canvas对象,把图片保存在 canvas 中,然后 canvas 对象 toDataUrl,在把 dataurl 数据存储在 localstorage 中。
或者使用 blob 二进制流存储,canvas 对象toBlob
**如何实现大文件上传?**⭐⭐⭐⭐
使用 input 接受大文件,使用file.slice进行分割分块上传(制定好一个块的大小,然后进行分割),等所有块上传完毕之后,promise.all(),运行成功回调
如何实现 localstorage 定时清除⭐⭐⭐⭐
自己重写一个 set 方法,内部逻辑就是添加一个现在的时间以及有效时长
再重写一个 get 方法,每当 get 的时候先进行判断是否过期,如果过期就删除,并返回 null,没过期的话正常返回
秒传、分片传输、断点传输⭐⭐⭐⭐
秒传
文件上传前,服务器先对文件做MD5校验,如果服务器上有同样的文件,则返回一个新地址,如果不想秒传也可以,修改文件中的内容就可以了(改名字不行)
分片传输
利用Blob提供的slice方法把大文件分割为一个个小文件分别传输。全部上传完成时候由服务端进行归总整合
断点传输
在分片上传的基础上,分成一个个小文件之后,每个小文件上传完毕之后对其进行状态的存储(localStorage),如果中间发生网络断线或者刷新,下次可以接着上次的进度上传
面试官:说说你知道的状态码⭐⭐⭐⭐⭐
- 2开头的表示成功
- 一般见到的就是200
- 3开头的表示重定向
- 301永久重定向
- 302临时重定向
- 304表示可以在缓存中取数据(协商缓存)
- 4开头表示客户端错误
- 403跨域
- 404请求资源不存在
- 5开头表示服务端错误
- 500
**面试官:https和http有什么区别,https的实现原理?**⭐⭐⭐⭐⭐
- http无状态无连接,而且是明文传输,不安全,默认连接80端口
- https 是有不可否认性的,可以保证对方身份的真实性,默认端口是443端口,加密传输,而且会保证数据的完整性
- https实现原理⭐⭐⭐
- 首先客户端向服务端发送一个随机值和一个客户端支持的加密算法,并连接到443端口。
- 服务端收到以后,会返回另外一个随机值和一个协商好的加密算法,这个算法是刚才发送的那个算法的子集
- 随后服务端会再次发送一个 CA 证书,这个 CA 证书实际上就是一个公钥,包含了一些信息(比如颁发机构和有效时间等)
客户端收到以后会验证这个 CA 证书,比如验证是否过期,是否有效等等,如果验证未通过,会弹窗报错。 - 如果验证成功,会生成一个随机值作为预主密钥,客户端使用刚才两个随机值和这个预主密钥组装成会话密钥;再使用刚才服务 - 端发来的公钥进行加密发送给服务端;这个过程是一个非对称加密(公钥加密,私钥解密)
- 服务端收到以后使用私钥解密,随后得到那两个随机值和预主密钥,随后再组装成会话密钥。
- 客户端在向服务端发起一条信息,这条信息使用会话秘钥加密,用来验证服务端时候能收到加密的信息
- 服务端收到以后使用刚才的会话密钥解密,在返回一个会话密钥加密的信息,双方收到以后 SSL 建立完成;这个过程是对称加密(加密和解密是同一个)
面试官:localStorage、SessionStorage、cookie、session 之间有什么区别⭐⭐⭐⭐⭐
- localStorage
生命周期:关闭浏览器后数据依然保留,除非手动清除,否则一直在
作用域:相同浏览器的不同标签在同源情况下可以共享localStorage - sessionStorage
生命周期:关闭浏览器或者标签后即失效
作用域:只在当前标签可用,当前标签的iframe中且同源可以共享 - cookie
一开始cookie 不是用来存储的,而是为了弥补 http 的状态的不足,http 是无状态协议。每当向服务器发起请求、请求结束,下次发送请求的时候服务端就不知道是谁了,所以 cookie 是用来弥补这个不足的
cookie 有很多缺陷,比如:- 容量缺陷。cookie 的存储空间只有4KB
- 性能缺陷。有时候 cookie 我们用不到,但是不管用的到用不到,http 在发送请求的时候一定会带着 cookie,这就造成了性能的浪费
- 安全缺陷。cookie 在 http 下很容易被非法用户获取。尤其是设置了 http-only 为 false 的情况下,这个时候 js 可以读取到 cookie,很容易受到 xss攻击。
- cookie 是保存在客户端的,一般由 server 设置值及过期时间
- cookie 没有提供删除的 API,如果想要删除的 的话可以把 max-age 设为0或者把 expire 设置为当前时间(立刻过期)即可
- cookie 的属性有
- http-only
- 不能被客户端更改访问,防止 XSS 攻击
- max-age
- 生效后存活的时间
- Secure
- 是否只允许在 https 下传输
- expire
- 过期时间
- http-only
- session
- session 是保存在服务端的
- session 的运行依赖 sessionId,sessionId 又保存在 cookie 中,所以禁用了 cookie之后 session 也是用不了的,如果硬要用也可以,可以把 sessionId 存储在 url 中
- session一般是用来跟踪用户状态的
- session 比较安全,因为存储在服务器中,不过为了减少服务端的压力,很多信息还是推荐存在 cookie 中的
**问:服务端渲染和客户端渲染的区别,各自的优缺点?**⭐⭐⭐⭐⭐
- 服务端渲染(SSR Server Site Rendering)
- 有利于 SEO,首屏加载快,但是重复请求次数多,开发效率低,服务器压力大
- 渲染的时候返回的是完整的 html 格式
- 应用场景:可能被搜索到的
- 客户端渲染(CSR Client Site Rendering)
- 不利于 SEO,首屏加载慢,前后端分离开发,交互速度快、体验好
- 渲染的时候返回的是 json 数据格式,由浏览器完成渲染
- 应用场景:app 内部"嵌套"的 h5页面
问:什么是JWT(Json Web Token)?⭐⭐⭐⭐⭐
答:
在没有 JWT 之前,验证客户端的方式就是通过 token,具体方式如下
- 用户输入账号密码以后,向服务端发起请求,服务端生成token返回给客户端,然后下次客户端请求数据的时候会携带着 token,服务端收到之后,会与之前保存的 token进行验证,验证通过以后返回数据,验证不通过就不返回。
- 不过这种方式的扩展性很差,因为如果有上万个用户发起请求的话就需要保存上万条 token,这样对服务端而言无疑是压力巨大的
后来出现了 JWT,这种方法可以把 token 保存在客户端
JWT 相当于把数据转换成 JSON 对象,这个特殊的 JSON 对象分为三部分:头部、负载、签名,他们之间分别用.区分开
- 头部(header)
保存的是JWT 的元数据,表明所使用的 hash 算法,以 JSON 对象的方式存储,然后转换成 Base64URL 的格式 - 负载(payload)
也是 JSON 对象格式,用来存放自己的数据 - 签名(Signature)
确保消息的完整性
###############美丽的分割线##################
Vue系列面试题
Vue双向绑定
数据劫持: vue.js是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()
来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调
阐述一下你所理解的MVVM响应式原理⭐⭐⭐⭐⭐
vue是采用数据劫持配合发布者-订阅者的模式的方式,通过Object.defineProperty()来劫持各个属性的getter和setter,在数据变动时,发布消息给依赖收集器(dep中的subs),去通知(notify)观察者,做出对应的回调函数,去更新视图
MVVM作为绑定的入口,整合Observer,Compile和Watcher三者,通过Observer来监听model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer,Compile之间的通信桥路,达到数据变化=>视图更新;视图交互变化=>数据model变更的双向绑定效果。
Vue 如何监听数组的?
首先第一点是要看数组里面是不是还存在对象,如果存在对象的话在进行深层遍历是否还依然存在对象,再把对象进行 defineProperty
监听。然后数组,数组的改变实质上只是几个方法,什么 pop
,unshift
,push
…Vue 重写了这几个方法,只要在调用这些方法的时候做出回调更新就可以了
为什么 Vue 要采用异步更新
因为首先 Vue 本身是组件级更新的,更改数据如果非常多,更新非常频繁,如果不采用异步更新的话每次都需要重新渲染。
每次有数据需要更新的时候,Vue 会把它放在一个队列中,等最后的时候会调用 nexttick 方法。nexttick就会清空这个队列。
用户也可以手动调用 nexttick(callback) 方法,会同样把callback 回调函数放入队列中,保证视图更新完之后被调用(因为会把 callback 放进队列的最后),并且是依次链式调用。
Vue中的nextTick
nextTick
解释
nextTick:在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
应用
想要在Vue生命周期函数中的created()操作DOM可以使用Vue.nextTick()回调函数
在数据改变后要执行的操作,而这个操作需要等数据改变后而改变DOM结构的时候才进行操作,需要用到nextTick
Vue中的nextTick是微任务还是宏任务⭐⭐⭐⭐
nextTick的内部实现如果支持 promise 那就使用 promise,没有就用MutationObserver(微任务),在没有就用 setImmediate(宏任务),还没有就用 setTimeOut;所以nextTick 有可能是宏任务,也有可能是微任务
面试官:说说vue的生命周期⭐⭐⭐⭐⭐
beforeCreate
创建之前,此时还没有data和MethodCreated
创建完成,此时data和Method可以使用了
在Created之后beforeMount之前如果没有el选项的话那么此时生命周期结束,停止编译,如果有则继续beforeMount
在渲染之前mounted
页面已经渲染完成,并且vm实例中已经添加完$el了,已经替换掉那些DOM元素了(双括号中的变量),这个时候可以操作DOM了(但是是获取不了元素的高度等属性的,如果想要获取,需要使用nextTick())beforeUpdate
data改变后,对应的组件重新渲染之前updated
data改变后,对应的组件重新渲染完成beforeDestory
在实例销毁之前,此时实例仍然可以使用destoryed
实例销毁后
面试官:vue中父子组件的生命周期⭐⭐⭐⭐⭐
- 父子组件的生命周期是一个嵌套的过程
- 渲染的过程
父beforeCreate
->父created
->父beforeMount
->子beforeCreate
->子created
->子beforeMount
->子mounted
->父mounted
- 子组件更新过程
父beforeUpdate
->子beforeUpdate
->子updated
->父updated
- 父组件更新过程
父beforeUpdate
->父updated
- 销毁过程
父beforeDestroy
->子beforeDestroy
->子destroyed
->父destroyed
面试官:computed 、watch、method的区别⭐⭐⭐⭐⭐
computed
计算属性,依赖其他属性,当其他属性改变的时候下一次获取computed值时也会改变,computed
的值会有缓存watch
- 类似于数据改变后的回调
- 如果想深度监听的话,后面加一个
deep:true
- 如果想监听完立马运行的话,后面加一个
immediate:true
method
在使用 method 的时候,是这样使用的{{fn{xx}}},渲染的时候如果没有发生变化,这个也是会被执行的。而 computed 是有缓存的,如果没有变化就不用再去执行了
面试官:Vue-router的模式⭐⭐⭐⭐⭐
- hash模式
监听hashchange事件实现前端路由,利用url中的hash来模拟一个hash,以保证url改变时,页面不会重新加载。 - history模式
利用pushstate和replacestate来将url替换但不刷新,但是有一个致命点就是,一旦刷新的话,就会可能404,因为没有当前的真正路径,要想解决这一问题需要后端配合,将不存在的路径重定向到入口文件。
面试官:MVC与MVVM有什么区别⭐⭐⭐⭐⭐
-
MVC
- Model(模型)是应用程序中用于处理应用程序数据逻辑的部分。通常模型对象负责在数据库中存取数据。处理数据的crud
- View(视图)是应用程序中处理数据显示的部分。通常视图是依据模型数据创建的。视图层,前端
- Controller(控制器)是应用程序中处理用户交互的部分。一般包括业务处理模块和router路由模块,通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据。
-
mvvm
mvvm是前端图层的概念,mvvm是双向的,视图层可以通过 ViewModel 转换成模型层,模型层也可以通过 ViewModel 转换成视图层- Model(每个页面的单独的数据)
- ViewModel (双向绑定,M和V之间的枢纽)
- View(视图,相当于HTML结构)
面试官:讲讲diff算法⭐⭐⭐⭐⭐
diff算法是指对新旧虚拟节点进行对比,并返回一个patch对象,用来存储两个节点不同的地方,最后利用patch记录的消息局部更新DOM
diff 算法
-
diff算法是虚拟节点的比较
-
先进行key值的比较
-
先进行同级比较,
-
然后再比较是不是一方有儿子,一方没儿子。如果是这样,直接在旧节点中插入或删除儿子即可
-
在比较两方都有儿子的情况
- 情况一:旧:ABCD,新:ABCDE;从头向尾比较,最后插入即可
- 情况二:旧 :ABCD,新:EABCD;从尾向头比较,最后插入即可
- 情况三:旧:ABCD,新:DABC;头和尾先进行一次比对,发现D 时,把 D 移至前面,再继续从头向尾比较,
- 情况四:旧:ABCD,新 BCDA;从头向尾比较后发现不对,就会从尾向头比,把 A 移至最后,再继续比较
- 情况五:旧 :ABCD,新CDME;从头向尾比较,把 CD 移至前面,最后 新建 ME,再把 CD 至为空
递归比较子节点
虚拟DOM的优缺点⭐⭐⭐⭐⭐
缺点
首次渲染大量DOM时,由于多了一层虚拟DOM的计算,会比innerHTML插入慢
优点
减少了dom操作,减少了回流与重绘
保证性能的下限,虽说性能不是最佳,但是它具备局部更新的能力,所以大部分时候还是比正常的DOM性能高很多的
Vue的Key的作用 ⭐⭐⭐⭐
key主要用在虚拟Dom算法中,每个虚拟节点VNode有一个唯一标识Key,通过对比新旧节点的key来判断节点是否改变,用key就可以大大提高渲染效率,这个key类似于缓存中的etag。
**为什么 v-for 会要有key?**⭐⭐⭐⭐⭐
因为在 vue 中会有一个 diff 算法,假如子节点 AB 调换了位置,它会比较 key 值,会直接调换,而不是一个销毁重新生成的过程
Vue组件通信⭐⭐⭐⭐⭐
父组件向子组件传值
- 父组件发送的形式是以属性的形式绑定值到子组件身上。
- 然后子组件用属性props接收
- 在props中使用驼峰形式,模板中需要使用短横线的形式字符串形式的模板中没有这个限制
子组件向父组件传值
- 子组件用$emit()触发事件
- $emit() 第一个参数为 自定义的事件名称 第二个参数为需要传递的数据 $(event)来接收
- 父组件用v-on 缩写为@ 监听子组件的事件
兄弟之间的传递
- 兄弟之间传递数据需要借助于事件中心,通过事件中心传递数据
提供事件中心 var hub = new Vue() - 传递数据方,通过一个事件触发hub.$emit(方法名,传递的数据)
- 接收数据方,通过mounted(){} 钩子中 触发hub.$on()方法名
Vue中key是用来做什么的?为什么不推介使用index作为key?⭐⭐⭐⭐⭐
1、key的作用主要是为了高效的更新虚拟DOM(使用key,它会基于key的变化重新排列元素顺序,并且会移除key不存在的元素)
2、当以数组的下标index作为index值时,其中一个元素(如增删改查)发生了变化就有可能导致所有元素的key值发生变化
Vue导航守卫的钩子函数有哪些?⭐⭐⭐⭐⭐
全局守卫
- router.beforeEach:全局前置守卫,进入路由之前
- router.beforeResolve:全局解析守卫,在beforeRouteEnter调用之后调用
- router.afterEach:全局后置钩子,进入路由之后
路由组件内的守卫
- beforeRouteEnter():进入路由前
- beforeRouteUpdate():路由复用同一个组件时
- beforeRouteLeave():离开当前路由时
vue 常见的性能优化⭐⭐⭐⭐⭐
- spa 使用 keep-alive
- key 的使用
- v-if 和v-show
- v-if 不要和 v-for 一起使用
- v-for 的优先级要早于 v-if,如果一起使用的话,会先遍历在判断 v-if,会造成性能问题;
- 使用Object.freeze()方式冻结data中的属性,从而阻止数据劫持
- 组件销毁的时候会断开所有与实例联系,但是除了addEventListener,所以当一个组件销毁的时候需要手动去removeEventListener
- 图片懒加载
- 路由懒加载
- 防抖节流
- 长列表固定个数
- 为减少重新渲染和创建dom节点的时间,采用虚拟dom
vue3 相比于vue2有什么升级⭐⭐⭐⭐
- 采用 ts 编写
- composition API
- 响应式原理使用的 proxy
##################美丽的分割线#################
Webpack
webpack常用字段及解释⭐⭐⭐⭐⭐
##################美丽的分割线#################
css系列面试题
1、对BFC规范(块级格式化上下文)的理解
BFC 块级格式化上下文 一块独立的区域,有自己的规则,bfc中的元素与外界的元素互不影响
BFC是一块用来独立的布局环境,保护其中内部元素不受外部影响,也不影响外部。
怎么触发BFC
- float的值left或right
- overflow的值不为visible(默认)
- display的值为inline-block、table-cell、table-caption
- position的值为absolute(绝对定位)或fixed固定定位
规则:
1、BFC的区域不会与float box重叠。
2、BFC是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。
3、计算BFC的高度时,浮动元素也会参与计算。
4、内部的Box会在垂直方向上一个接一个放置。
5、Box垂直方向的距离由margin决定,属于同一个BFC的两个相邻Box的margin会发生重叠。
BFC的应用
1、可以用来自适应布局
利用BFC的这个原理可以实现两栏布局,左边定宽,右边自适应。不会相互影响,哪怕高度不相等。
给左边盒子加浮动,右边盒子加overflow:hidden;变成BFC,就可以消除外部左边盒子因浮动对他的影响
2、可以清除浮动
一个父元素中的子元素,设置浮动时,父元素没有设置高度,这时子元素脱离文档流,父元素感知不到子元素的高度,造成父元素的塌陷。 这时候给父元素添加overflow:hidden / auto,变成BFC就可以解决这种问题。
3、解决垂直边距重叠
1.父子关系的边距重叠
父子关系,如果子元素设置了外边距,在没有把父元素变成BFC的情况下,父元素也会产生外边距。
解决办法: 是给父元素添加一个 overflow:hidden,这样父元素就变为BFC,不会随子元素产生外边距
2.同级兄弟关系的重叠
同级元素在垂直方向上外边距会出现重叠现象,最后外边距的大小取两者绝对值大的那个
可通过添加一个空元素或伪类元素,设置overflow:hidden;解决
2、什么是渐进增强优雅降级
渐进增强:针对低版本浏览器进行构建页面,保证最基本的功能,然后在针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。
优雅降级:一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。
3、CSS优化、提高性能的方法有哪些?
- 避免过度约束
- 避免后代选择符
- 避免链式选择符
- 使用紧凑的语法
- 避免不必要的命名空间
避免不必要的重复
最好使用表示语义的名字。一个好的类名应该是描述他是什么而不是像什么
避免!important,可以选择其他选择器 尽可能的精简规则,你可以合并不同类里的重复规则
4、CSS特性:继承性,层叠,优先级
1、继承性:子标签会继承父标签的某些样式,如文本颜色和字号。(text- font- color)
2、层叠性:样式冲突,遵循的原则是就近原则。
3、优先级:定义CSS样式时,经常出现两个或更多规则应用在同一元素上,此时,谁的权重高显示谁的样式。
(选择器相同,则执行层叠性;选择器不同,就会出现优先级的问题。)
!Important > 行内式 > id > 类/伪类/属性 > 标签选择器 > 全局
(对应权重:无穷大∞>1000>100>10>1>0)
5、定位有哪几种?分别举例?Z-index熟悉在使用的时候注意什么 ?
static: 默认值 没有定位,元素出现在正常的流中
relative(相对定位):生成相对定位的元素,相对于其正常(原先本身)位置进行定位
absolute(绝对定位):生成绝对定位的元素,相对于static定位以外的第一个父元素进行定位
fixed(固定定位):生成绝对定位的元素,相对于浏览器窗口进行定位
sticky 粘性定位 当前元素设置了粘性定位,滚动到顶部就会吸附顶部,往下滑还回到原来位置。
z-index规则
1、值可以是正整数、负整数或0,数值越大,盒子越靠上;
2、如果属性值相同,则按照书写顺序,后来居上;
3、数字后面不能加单位。
4、z-index 只能应用于相对定位、绝对定位和固定定位的元素,其他标准流、浮动和静态定位无效
6、页面导入时,使用link和@import有什么区别
页面中使用CSS的方式主要有3种:行内添加定义style属性值,页面头部内嵌调用和外面链接调用,其中外面引用有两种:Link引入和@import导入,两者都是外部引用CSS的方式,但是存在一定的区别:
1、从属关系: link是标签,@import是css提供的.
-
加载差异: link: 结构和样式同时加载;而@import 先加载结构,后加载样式
-
兼容性:link没有兼容问题,@import不兼容ie5以下的浏览器.
4.可操作性: link可以通过js操作dom插入link标签改变样式,而@import不能
7、简述src和href的区别
src用于替换当前元素
href用于在当前文档和引用资源之间确立联系.
扩展: src是source的缩写,指向外部资源的位置,指向的内容将会嵌入到文档中当前标签所在位置 href是Hypertext Reference的缩写,指向网络资源所在位置,建立和当前元素(锚点)或当前文档(链接)之间的链接
8、上下margin重合的问题
1、相邻块元素垂直外边距的合并
解决方案:尽量给只给一个盒子添加margin值
2、嵌套块元素垂直外边距的合并(塌陷)
解决方案:
可以为父元素定义上边框。
可以为父元素定义上内边距
可以为父元素添加overflow:hidden。
9、浏览器常见的兼容性问题?
1、不同浏览器margin和padding不同
2、ie6中,父级元素浮动以后,内部元素内容撑不开宽度
3、标签嵌套不规范,如p和h1-h6里面嵌套div
4、ie6小于19px,会当成19px处理,也就元素宽高小于19px的bug
5、图片3像素问题
6、IE8下给图片添加超链接时,图片会有蓝色边框
7、鼠标滑过时,不显示小手
10、li与li之间有看不见的空白间隔是什么原因引起的?有什么解决办法?
1、浏览器的默认行为是把inline元素间的空白字符(空格换行tab)渲染成一个空格
解决方案:
为li设置左浮动
将li写在同一行 中间不要有空格
将ul内font-size:0,但是单独li设置文字大小
将ul的letter-spacing:-8px,但是单独li设置字符间距normal
11、Html5新增的语义化标签。
头部标签:
导航标签:
内容区块表签:
页脚标签:
侧边栏:
页面内独立的内容区域:
12、flex弹性盒布局与传统盒模型布局的区别和优点?以及Flex布局哪些属性失效?
区别:
-
普通盒模型中的子元素分配其父元素的空间,而弹性盒模型中的子元素分配其父元素的可用空间。
-
普通盒模型主要针对块级元素和行级元素的布局,而弹性盒是建立在弹性流上,也就是元素可以随着可视区域的变化而呈现流式布局。
弹性盒的优点:
能为盒模型提供最大的灵活性,即使是不定宽高的元素依然好用,可以简便、完整、响应式地实现各种页面布局。
传统布局的特点:兼容性好、布局繁琐、局限性,不能在移动端很好的布局
设为 Flex 布局以后,子元素的float、clear和vertical-align属性将失效
13、 什么是rem、px、em区别。
rem是一个相对单位,rem的是相对于html元素的字体大小,没有继承性
em是一个相对单位,是相对于父元素字体大小有继承性
px是一个“绝对单位”,就是css中定义的像素,利用px设置字体大小及元素的宽高等,比较稳定和精确。
14、什么是视口
在pc端中,视口指的是在pc端中浏览器的可视区域;
在移动端中,它涉及3个视口:1是布局视口,2是视觉视口,3是理想视口
移动端指的视口就是布局视口
15、什么是媒体查询。
媒体查询是CSS3新语法。
使用媒体查询,可以针对不同的媒体类型定义不同的样式
媒体查询可以针对不同的屏幕尺寸设置不同的样式
当你重置浏览器大小的过程中,页面也会根据浏览器的宽度和高度重新渲染页面
目前针对很多苹果手机、Android手机,平板等设备都用得到多媒体查询
16、响应式布局有哪些实现方式?什么是响应式设计?响应式设计的基本原理是什么?
1.百分比布局,但是无法对字体,边框等比例缩放
2.弹性盒子布局 display:flex
3.rem布局,1rem=html的font-size值的大小
- css3媒体查询 @media screen and(max-width: 750px){}
5.vw+vh
6.使用一些框架(bootstrap,vant)
什么是响应式设计:响应式网站设计是一个网站能够兼容多个终端,智能地根据不同设备环境进行相对应的布局
响应式设计的基本原理:基本原理是通过媒体查询检测不同的设备屏幕尺寸设置不同的css样式 页面头部必须有meta声明的
17、什么叫CSS盒模型?有哪几种盒模型?有什么区别?box-sizing属性有什么用?
1、什么是CSS盒模型?
在我们的HTML页面中,每一个元素都可以被看成一个盒子,而这个盒子由:内容(content)、内边距(padding)、 边框(border)、外边距(margin) 四部分组成.
2、有哪几种盒模型?
对于盒模型,分为标准盒模型和怪异盒模型一下两种
标准(W3C)盒模型的范围包括margin、border、padding、content,并且宽高只包含content,不包含其他部分
怪异(IE)盒模型的范围包括margin、border、padding、content,和标准盒模型不同的是,怪异盒模型的宽高包含了padding和 border
box-sizing作用
用来控制元素的盒子模型的解析模式,默认为content-box context-box标准盒模型 border-box怪异盒模型
18、 Doctype作用? 标准模式与兼容模式(兼容模式)如何区分?
文档声明;用于告知浏览器该以何种模式来渲染文档.
严格模式和混杂模式的区别:
严格模式:页面排版及 JS 解析是以该浏览器支持的最高标准来执行
混杂模式:不严格按照标准执行,主要用来兼容旧的浏览器,向后兼容
19、 为什么会出现浮动?浮动会带来哪些问题?清除浮动的方式有哪些?哪种最好?
1、为什么会出现浮动:
由于浮动元素脱离了文档流,所以文档流的块框表现得就像浮动框不存在一样。浮动元素会漂浮在文档流的块框上.
2、浮动带来的问题:
父元素的高度无法被撑开,影响与父元素同级的元素
若非第一个元素浮动,则该元素之前的元素也需要浮动,否则会影响页面显示的结构.
与浮动元素同级的非浮动元素(内联元素)会跟随其后
3、清除浮动的方式:
父级div定义height
结尾处加空div标签clear:both
父级div定义伪类:after、before
父级div定义overflow:hidden
父级div定义overflow:auto。
父级div也浮动,需要定义宽度。
父级div定义display:table。
结尾处加br标签clear:both
比较好的是第3种,无需多余标签,方便维护,通过伪类就可以解决
20、元素的alt和title有什么异同
不同点: 元素的alt是表示图片加载失败显示的文本内容,而title是表示鼠标悬停图片时显示的文本内容.
相同点: 在alt和title同时设置的时候,alt作为图片的替代文字出现,title是图片的解释文字
21、Div+CSS较table相比有什么样的优点?
正常场景一般都适用div+CSS布局,Div+CSS优点:
开发中结构与样式分离,便于后期项目的维护和迭代
代码语义性好
更符合HTML标准规范
SEO友好
table缺点:
太深的嵌套,比如table>tr>td>h3,会导致搜索引擎读取困难,而且,最直接的损失就是大大增加了冗余代码量
灵活性差,比如要将tr设置border等属性,是不行的,得通过td
代码臃肿,当在table中套用table的时候,阅读代码会显得异常混乱
混乱的colspan与rowspan,用来布局时,频繁使用他们会造成整个文档顺序混乱,不够语义化。
22、 ::before和:before有何异同?
单冒号(:)用于CSS3伪类,
双冒号(::)用于CSS3伪元素。伪元素和伪类之所以这么容易混淆,是因为他们的效果类似而且
伪类: 用于已有元素处于某种状态时为其添加对应的样式,这个状态是根据用户行为而动态变化的。
例如: 当用户悬停在指定元素时,可以通过:hover来描述这个元素的状态,虽然它和一般css相似,可以为已有元素添加样式,但是它只有处于DOM树无法描述的状态下才能为元素添加样式,所以称为伪类。
伪元素: 用于创建一些不在DOM树中的元素,并为其添加样式。
例如: 我们可以通过:before来在一个元素之前添加一些文本,并为这些文本添加样式,虽然用户可以看见这些文本,但是它实际上并不在 DOM文档中。
23、什么是回流什么是重绘以及区别?
回流:
当render tree中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建。这就称为回流(reflow)。每个页面至少需要一次回流,就是在页面第一次加载的时候,这时候是一定会发生回流的,因为要构建render tree.
重绘:
当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。则就叫称为重绘.
区别:
回流必将引起重绘,而重绘不一定会引起回流。比如:只有颜色改变的时候就只会发生重绘而不会引起回流,当页面布局和几何属性改变时就需要回流
24、.简单说一下H5新增了哪些新特性
语义化标签:header、footer、section、nav、aside、article
增强型表单:input 的多个 type calendar、date、time、url、search、tel、file、number 新增表单属性:placehoder、required、min 和 max
音频视频:audio、video
canvas 画布
kan wa si 地理定位(Geolocation)
拖拽释放:拖拽是一种常见的特性,即抓取对象以后拖到另一个位置,在HTML5中,
本地存储: localStorage 没有时间限制的数据存储; sessionStorage, session 的数据存储,当用户关闭浏览器窗口后,
数据会被删除 新事件:onresize、ondrag、onscroll、onmousewheel、onerror、onplay、onpause
WebSocket:建立持久通信协议,新的技术:webworker、websocket、Geolocation
25、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(线性渐变):
eg: background-image: linear-gradient(100deg, #237b9f, #f2febd);
radial-gradient (径向渐变)
7、过渡:transition可实现动画
8、自定义动画: animate@keyfrom
9、媒体查询:多栏布局@media screen and (width:800px)
10、border-image
11、2D转换:transform:translate(x,y) rotate(x,y)旋转 skew(x,y)倾斜 scale(x,y)缩放
12、3D转换
13、字体图标:font-size
14、弹性布局:flex
26、浏览器是如何渲染页面的
浏览器将获取的HTML文档解析成DOM树。
处理CSS标记,构成层叠样式表模型CSSOM(CSS Object Model)。
将DOM和CSSOM合并为渲染树(rendering tree),代表一系列将被渲染的对象。
渲染树的每个元素包含的内容都是计算过的,它被称之为布局layout。浏览器使用一种流式处理的方法,只需要一次绘制操作就可以布局所有的元素。
将渲染树的各个节点绘制到屏幕上,这一步被称为绘制painting。
构建对象模型(DOM,CSSOM)
构建渲染树(RenderTree)
布局
渲染
27、元素居中的方式、以及垂直上下居中
方法一:给父元素设置成弹性盒子,子元素横向居中,纵向居中
方法二:父相子绝后,子部分向上移动本身宽度和高度的一半,也可以用transfrom:translate(-50%,-50%)(最常用方法)
方法三:父相子绝,子元素所有定位为0,margin设置auto自适应
28、两/三栏布局(圣杯双飞翼)
两栏布局,左边定宽,右边自适应
三栏布局、圣杯布局、双飞翼布局
圣杯布局和双飞翼布局是前端工程师需要日常掌握的重要布局方式。两者的功能相同,都是为了实现一个两侧宽度固定,中间宽度自适应的三栏布局。(中间先加载渲染)
-
首先要给两侧设置padding预留出相应的空间
-
随后分别为三列设置宽度与浮动,同时对footer设置清除浮动
-
根据浮动的特性,由于center的宽度为100%,即占据了第一行的所有空间,所以left和right被“挤”到了第二行。
-
接下来的工作是将left放置到之前预留出的位置上,这里使用负外边距
-
这里使用position: relative和right: 200px将left的位置在原有位置基础上左移200px,以完成left的放
三栏布局两栏布局css代码
29、flex布局属性以及使用场景
Flex 布局,可以简便、完整、响应式地实现各种页面布局,任何一个容器都可以指定为 Flex 布局,行内元素也可以使用 Flex 布局。
我在项目中常用到的有九宫格布局,列表布局等,都会经常用到。
flex的属性:
flex-direction :设置主轴的方向
justify-content :设置主轴上的子元素排列方式
flex-wrap :设置子元素是否换行
align-content :设置侧轴上的子元素排列方式(多行)
align-items :设置侧轴上的子元素排列方式(单行)
flex-flow :复合属性,相当于同时设置了flex-direction和flex-wrap
flex:1;的原理
flex-grow:1;flex-shrink:1;flex-basis:auto; 这三个样式的和写
flex: 1 1 auto; 简写 flex:1;
flex-grow:0; 扩展比率
默认值为0,容器中项目没有占满时,不分配剩余空间。
flex-shrink:1; 收缩比率
默认值为1,容器中项目超出容器大小时,把项目平均压缩到容器内。
flex-basis:auto; 伸缩基准值
默认值为auto,定义容器中项目的占据空间,一般用百分数设值
30、常见的块级、行级、空元素
在CSS中规范规定,每个元素都有display属性,确定该元素的类型,每个元素都有默认的display值,比如div默认display属性值为“block”,成为“块级”元素;span默认display属性值为“inline”,是“行内”元素。
我们在平常的项目中经常使用到的有
· 行内元素有:span a b i img input select strong
· 块级元素有:div p h1-h6 ul table form ul ol li dl dt dd…
· 空元素(没有内容):
31、css hack
概念:CSS hack是通过在CSS样式中加入一些特殊的符号,让不同的浏览器识别不同的符号(什么样的浏览器识别什么样的符号是有标准的,CSS hack 就是让你记住这个标准),以达到应用不同的 CSS 样式的目的
1、 条件hack
条件注释只有在IE浏览器下才能执行,这个代码在非IE浏览下被当做注释视而不见。可以通过IE条件注释载入不同的CSS、JS、HTML和服务器代码等。
2、 选择符Hack
比如IE6能识别 html .class{},IE7能识别+html .class{}
3、属性Hack 比如IE6能识别下划线和星号,IE7能识别星号,但不能识别下划线,而firefox两个都不能认识。
1、写CSS hack需要遵循以下三条原则:
· 有效: 能够通过 Web 标准的验证
· 只针对太古老的/不再开发的/已被抛弃的浏览器, 而不是目前的主流浏览器
· 代码要丑陋。让人记住这是一个不得已而为之的 Hack, 时刻记住要想办法去掉它。现在很多hacks已经抛弃了最初的原则,而滥用hack会导致浏览器更新之后产生更多的兼容性问题。因此,并不推荐使用CSS hack来解决兼容性问题。
32、html和XML
html被称为超文本标记语言, 是一种描述性语言,用html 可以创建能在互联网上传输的信息页,是构成网页文档的主要语言,它是由很多的标签组成
xml 即可扩展标记语言,是Internet环境中跨平台的、依赖于内容的技术,是当前处理结构化文档信息的有力工具,满足了Web内容发布与交换的需要,适合作为各种存储与共享的通用平台。
都可以通过DOM 变成方式来访问。
都可以通过CSS来改变外观。
html和xml 都是标记语言,都是基于文本编辑和修改的。
xml不是要来取代html的,是对html的补充,用来与html协同工作的语言,基于上面这些优势,xml将来成为所有的数据处理和数据传输的常用工具非常可观。
34、毛玻璃效果
background: rgba(244, 243, 244, 0.18);
box-shadow: 0 0.3px 0.7px rgba(0, 0, 0, 0.126),
0 0.9px 1.7px rgba(0, 0, 0, 0.179), 0 1.8px 3.5px rgba(0, 0, 0, 0.224),
0 3.7px 7.3px rgba(0, 0, 0, 0.277), 0 10px 20px rgba(0, 0, 0, 0.4);
backdrop-filter: blur(10px);
35、web worek
新开了一个子线程,而且子线程不受线程的影响
大数据处理,耗费时间较长的操作
36、canvas 常用api有哪些
常用API:
- fillRect(x,y,width,height) 实心矩形;
- strokeRect(x,y,width,height) 空心矩形;
- fillText( “Hello world” , 200 , 200 ) 实心文字;
- strokeText( “Hello world” , 200 , 300 ) 空心文字;
37、语义化的好处
在我们开发中,语义化让,页面结构更加清晰,便于后期的维护,便于浏览器,搜索引擎解析
理由搜索引擎的爬取,利于seo
38、浏览器兼容性的问题
在不同的浏览器中,浏览器的内核都是不相同的,所以各个浏览器对网页的解析存在一定的差异。
简单来说就是写的代码在各个浏览器上显示不同的效果
解决:
1、css3新属性,加浏览器前缀兼容早期浏览
-moz- 火狐浏览器
-webkit- Safari, 谷歌浏览器等使用Webkit引擎的浏览器
-o- Opera浏览器(早期)
-ms- IE
2、css hack解决浏览器兼容性不同浏览器,识别不同的样式,css hack本身就是处理浏览器兼容的
3、图片默认有间距:
几个img标签放在一起的时候,有些浏览器会有默认的间距,通配符清除间距也不起作用。 可以通过使用float属性为img布局(所有图片左浮)
4、不同浏览器的标签默认的 margin 和 padding 不同
解决办法:可以通过设置全局样式来解决这个问题,这样所有的样式都会重置,初始值都会相同了。
39. 用纯CSS实现三角形的原理是什么?
首先,需要把元素的宽度、高度设为0。然后设置边框样式为透明,代码如下:
div{
width: 0;
height: 0;
border-top: 40px solid transparent;
border-left: 40px solid transparent;
border-right: 40px solid transparent;
border-bottom: 40px solid #ff0000;
}
2种更简单
div{
width: 0;
height: 0;
border: 100px solid transparent;
border-bottom-color:red;
}
40. style标签写在body前和body后有什么区别?
页面加载自上而下 当然是先加载样式.
写在body标签后由于浏览器以逐行方式对HTML文档进行解析,当解析到写在尾部的样式表(外联或写在style标签)会导致浏览器停止之前的渲染,等待加载且解析样式表完成之后重新渲染,在windows的IE下可能会出现FOUC现象(即样式失效导致的页面闪烁问题)
41. px,em,rem,vw,vh,rpx等单位的特性
px:像素
em:当前元素的字体大小
rem:根元素字体大小
vw:100vw是总宽度
vh:100vh是总高度
rpx:750rpx是总宽度