前端小知识总结
一、HTML
二、CSS
三、JS
1、加法运算符的特殊用法
console.log("==============================") let str1 = "abccc"; let numStr = "4"; let num = 10; console.log(numStr + num); //410 console.log(numStr - num); //-6 console.log(numStr * num); //40 console.log(numStr / num); //0.4 console.log(str1 + num); //abccc10 console.log(str1 - num); //NAN console.log(str1 * num); //NAN console.log(str1 / num); //NAN let foo = '20' - 10 + "10" + 10; console.log(foo); //101010
2、JS的执行机制
原文:https://www.jianshu.com/p/fb1c07b4d90d
四、VUE
1、VUE的生命周期
- 什么是生命周期:从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期! - 生命周期钩子:就是生命周期事件的别名而已; - 生命周期钩子 = 生命周期函数 = 生命周期事件
- 主要的生命周期函数分类: - 创建期间的生命周期函数: - beforeCreate:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性 - created:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板 - beforeMount:此时已经完成了模板的编译,但是还没有挂载到页面中 - mounted:此时,已经将编译好的模板,挂载到了页面指定的容器中显示 - 运行期间的生命周期函数: - beforeUpdate:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点 - updated:实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了! - 销毁期间的生命周期函数: - beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。 - destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
2、v-for中key的作用:
Vue与React,在执行列表渲染时也会要求给每个组件添加上key属性。这是由于虚拟DOM的Diff算法,一套虚拟DOM,使我们可以不直接操作DOM元素,只操作数据便可以重新渲染页面,而隐藏在背后的原理便是其高效的Diff算法。
虚拟DOM的Diff算法,其核心是基于两个简单的假设:
1. 两个相同的组件产生类似的DOM结构,不同的组件产生不同的DOM结构。
2. 同一层级的一组节点,他们可以通过唯一的id进行区分。
基于以上这两点假设,使得虚拟DOM的Diff算法的复杂度从O(n^3)降到了O(n)。
当页面的数据发生变化时,Diff算法只会比较同一层级的节点:
如果节点类型不同,直接干掉前面的节点,再创建并插入新的节点,不会再比较这个节点以后的子节点了。如果节点类型相同,则会重新设置该节点的属性,从而实现节点的更新。
当某一层有很多相同的节点时,也就是列表节点时,Diff算法的更新过程默认情况下也是遵循以上原则。
 
在B和C之间加一个F,Diff算法默认把C更新成F,D更新成C,E更新成D,最后再插入E,所以需要使用key来给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点,找到正确的位置区插入新的节点。
 
所以,key的作用主要是为了高效的更新虚拟DOM。另外vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果。
五、服务端与网络
1、http状态码
https://www.cnblogs.com/gitnull/p/9532129.html
2、http请求中请求头和响应头包含哪些内容
1)请求(客户端->服务端[request]) GET(请求的方式) /newcoder/hello.html(请求的目标资源) HTTP/1.1(请求采用的协议和版本号) Accept: */*(客户端能接收的资源类型) Accept-Language: en-us(客户端接收的语言类型) Connection: Keep-Alive(维护客户端和服务端的连接关系) Host: localhost:8080(连接的目标主机和端口号) Referer: http://localhost/links.asp(告诉服务器我来自于哪里) User-Agent: Mozilla/4.0(客户端版本号的名字) Accept-Encoding: gzip, deflate(客户端能接收的压缩数据的类型) If-Modified-Since: Tue, 11 Jul 2000 18:23:51 GMT(缓存时间) Cookie(客户端暂存服务端的信息) Date: Tue, 11 Jul 2000 18:23:51 GMT(客户端请求服务端的时间)
2)响应(服务端->客户端[response]) HTTP/1.1(响应采用的协议和版本号) 200(状态码) OK(描述信息) Location: http://www.baidu.com(服务端需要客户端访问的页面路径) Server:apache tomcat(服务端的Web服务端名) Content-Encoding: gzip(服务端能够发送压缩编码类型) Content-Length: 80(服务端发送的压缩数据的长度) Content-Language: zh-cn(服务端发送的语言类型) Content-Type: text/html; charset=GB2312(服务端发送的类型及采用的编码方式) Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT(服务端对该资源最后修改的时间) Refresh: 1;url=http://www.it315.org(服务端要求客户端1秒钟后,刷新,然后访问指定的页面路径) Content-Disposition: attachment; filename=aaa.zip(服务端要求客户端以下载文件的方式打开该文件) Transfer-Encoding: chunked(分块传递数据到客户端) Set-Cookie:SS=Q0=5Lb_nQ; path=/search(服务端发送到客户端的暂存数据) Expires: -1//3种(服务端禁止客户端缓存页面数据) Cache-Control: no-cache(服务端禁止客户端缓存页面数据) Pragma: no-cache(服务端禁止客户端缓存页面数据) Connection: close(1.0)/(1.1)Keep-Alive(维护客户端和服务端的连接关系) Date: Tue, 11 Jul 2000 18:23:51 GMT(服务端响应客户端的时间) 在服务器响应客户端的时候,带上Access-Control-Allow-Origin头信息,解决跨域的一种方法。 原文链接:https://blog.csdn.net/weixin_37861326/article/details/82216068
六、数据结构与算法
七、ES6
1、let与const
特点:(1)块级作用域(2)不存在变量声明提升(3)存在暂时性死区(4)不能够重复声明
var bar = 1; function foo(){ alert(bar); var bar = 2; } foo();//undefined,因为。。。。 let bar = 1; function foo(){ alert(bar); let bar = 2;//在块级作用域中,变量唯一存在;如果在块级作用域中用let声明了一个变量,那么该变量就唯一属于这个块级作用域,不受外部变量的影响; } foo();// Cannot access 'bar' before initialization
console.log(b);//Cannot access 'b' before initialization==b is not defined; let b=1; console.log(b);//undefined;变量声明提前,但是变量的赋值并没有提前 var b=1;
let a = 1;
console.log(window.a); //undefined 在全局作用域下,不同于var声明的变量,使用let来定义变量,该变量不会成为全局变量的一个属性。
var a = 1;
console.log(window.a); //1
const定义的对象,当对象改变了之后,const定义的值也会跟着改变。
cosnt定义的变量是一个对象的一个属性值,但是当对象属性值改变了以后,const定义的这个值并不会改变。
2、变量的解构赋值(字符串、数值、布尔、数组、对象、函数参数)
ES6新特性,按照一定模式,从数组或者对象中提取值,然后对变量进行赋值,称为解构。(模式匹配)
(1)字符串的解构赋值
const [a,b,c,d,e] = 'hello'; console.log([a,b,c,d,e]); //array ["h","e","l","l","o"] let {length : len} = "hello"; //字符串是类似数组的对象,有length属性 console.log(len); //5
(2)数值和布尔值的解构赋值
解构赋值的时候,如果等号右边是数值或者布尔值,会先将数值或布尔值转为对象;
let {toString: s1} = 123;
console.log(s1) // toString()
console.log(s1 === Number.prototype.toString) //true
let {toString: s2} = true;
console.log(s2) //toString()
console.log(s2 === Boolean.prototype.toString) //true
(3)数组的解构赋值
let [a,b,c] = [1,2,3]; console.log([a,b,c]) //[1,2,3] ;a=1,b=2,c=3 //完全解构 let [head, ...tail] = [1,2,3,4,5,6]; console.log(head); //1 console.log(tail); //[2,3,4,5,6] //不完全解构(右边数组解构一部分) 左<右 let [x,y] = [1,2,3,4,5]; console.log(x) //1 console.log(y) //2 //解构失败 左>右 let [u, v, ...w] = ["a"]; console.log(u); //a console.log(v); //undefined console.log(w); //[]
(4)对象的解构
let {name,age} = {name:"miny",age:18};
console.log(name)  //"miny"
console.log(age)  //18
let {sex:gender} = {sex:"girl"}  
console.log(gender); //"girl"
对象解构赋值的内部机制是先找到同名属性,然后再赋值给对应的变量,真正被赋值的是后者;例如,sex是匹配的模式,gender是变量,真正被赋值的是变量。
var node = {
    loc:{
        start:{
            line:1,
            column:5,
        }
    }
};
var {loc, loc:{start}, loc:{start:{line}}} = node;
console.log(line)  //1
console.log(loc)  //object start:{line:1, column:5}
console.log(start)  //object {line:1, column:5}
(5)函数参数(对象解构的默认赋值)
默认值生效的条件:对象的属性值严格等于undefined。
var {x=3} = {x:undefined}; console.log(x) //3 var {y=3} = {y:null}; console.log(y) //null
//以前
function f(){ var a = a || 5; } //现在 function f(a = 5){}
3、字符串
3.1模板字符串
模板字符串是增强版的字符串,用反引号(`)标识。可以在其中嵌入JavaScript变量或JS代码。
//所有模板字符串中的空格和换行都会被保留,若想删除字符串的首位空格,可使用trim()方法 //arguments是所有非箭头函数都可用的局部变量,可以使用arguments对象在函数中引用函数的参数;arguments[0]:函数的第一个参数。 // replace():该方法用于在字符串中用一些字符替换另一些字符,或者替换一个与正则表达式匹配的子串。 // replace(regExp,替换文本或者替换文本的函数);若regExp中有全局标志g,则替换所有匹配的子串,否则,只替换第一个匹配子串; // 第二个参数中:$2表示与regexp中的第二个子表达式相匹配的文本 let name = "Doe, John"; let name2 = name.replace(/(\w+)\s*, \s*(\w+)/, "$2 $1"); console.log(name2) // John Doe
// eval():可以计算某个字符串,或者执行其中的JavaScript代码。
const name = "小强";
const age = 100;
const str = '${name},突然变成${age}了!';
const replacer = function(){
console.log('match', arguments[0]); //匹配模式的字符串
console.log('$1', arguments[1]); //与模式中的子表达式(分组)匹配的字符串,可以有 0 个或多个这样的参数;/(正则)(.+?)(式)/,"《$1》$2<$3>"
console.log('offset', arguments[2]); //接下来的参数是一个整数,声明了匹配在字符串对象中出现的位置==索引;
console.log('string', arguments[3],'\n'); //最后一个参数是字符串本身。
return eval(arguments[1]); //函数返回字符串,并计算字符串的值;
};
const _str1 = str.replace(/\$\{([^}]+)\}/g, replacer);
console.log(_str1); //小强,突然变成100了!
 
3.1.0带标签的模板字符串
3.2 includes()方法:判断某个字符串中是否包含某个字符串
startsWith()、endsWith()方法:判断某个字符串是否以某个子串开始、结束。
const str = 'abcdminyxyz'; console.log(str.includes('miny')) //true console.log(str.endsWith('a')); //false console.log(str.startsWith('ab')); //true
4、函数
4.1函数的参数:可赋值(设置默认值)、可解构
function fun({x=2, y='默认值', z='默认值'} = {x:100,y:undefined,z:null}){ console.log(x,y,z) } fun(); //100 "默认值" null
4.2箭头函数
(1)如果参数只有一个,可省略小括号;(2)如果不写return,可以不写花括号{ };(3)没有arguments变量;(4)不改变this指向
let sum = (a,b) => a+b; console.log(sum(1,2)) //3
5、数组:数组新方法
// Array.from():将类数组转化为数组 var obj = {"0":'a',"1":'b',"2":'c',length:3}; let arr = Array.from(obj); console.log(arr); //["a", "b", "c"] // Array.of():创建数组 let arr1 = Array.of(1,2,3); console.log(arr1) //[1, 2, 3] // Array.fill(value,start,end):填充数组 let arr2 = [1,2,3,4,5,6] arr2.fill(7,3,5) console.log(arr2); //[1, 2, 3, 7, 7, 6] // Array.includes():判断数组是否有某值 let arr3 = [1,2,3,4,5] console.log(arr3.includes(100)); //false console.log(arr3.includes(1)); //true // Array.find():查找符合条件的第一个返回值 let arr4 = [1,2,3,4,5,6,7,8,9] let res = arr4.find(function (item) { return item > 4; }) console.log(res); // 5 // Array.filter():数组过滤,筛选出符合条件的元素 let arr5 = [1,2,3,4,5,6,7,8,9]; let arr5Res = arr5.filter(function (ele,index) { return index > 5; }) console.log(arr5Res); //[7, 8, 9] let arr5Res2 = arr5.filter(function (ele,index) { return ele > 4; }) console.log(arr5Res2); //[5, 6, 7, 8, 9] // 累加器 Array.reduce(function(total, currentValue, currentIndex, arr){}, initialValue) let arr6 = [1,2,3,4]; let arr6Res = arr6.reduce(function(total, currentValue, currentIndex, arr){ return total + currentValue; }, 100); console.log(arr6Res); //110
6、对象
7、class类
8、Generator
(1)迭代器函数:在普通函数名前加星号*
function *fun() {}
(2)yield 退让
generator函数并不会自动执行,调用generator函数,会返回一个遍历器对象,代表generator内部的指针;以后每次调用遍历器对象的next()方法,都会返回一个包含value和done属性的对象;value值代表当前状态内部状态值,done值为布尔值,代表当前遍历是否结束。
迭代器函数中,遇到yield 暂停中止执行,遇到迭代器的next()方法继续执行;
function *fun() { let [a,b,c] = [1,2,3] yield a; yield b; return c; } let res = fun(); //res是一个迭代器对象Iterator console.log(res.next()) //{value: 1, done: false} console.log(res.next()) //{value: 2, done: false} console.log(res.next()) //{value: 3, done: true} console.log(res.next()) //{value: undefined, done: true} 或者: let res = fun(); function next() { let {value,done} = res.next(); console.log(value); if(!done){ next(); } } next(); //1 2 3
如何往迭代器里面传值?
function *fun() { let a = yield '第一个yield表达式'; console.log(a); let b = yield '第二个yield表达式'; console.log(b); } let res = fun(); //返回迭代器对象 console.log(res.next()); //{value: "第一个yield表达式", done: false} console.log("========================================") console.log(res.next('参数1')); //参数1 //{value: "第二个yield表达式", done: false} console.log("========================================") console.log(res.next('参数2')); //参数2 //{value: undefined, done: true} console.log("========================================") console.log(res.next()); //{value: undefined, done: true}
9、async await
async 用来修饰函数,需要配合await使用;await后只能跟promise使用。
async function initPerson(){ let params = { name:'miny' }; let res = await initPersonInterface(params); console.log(res); }
在JavaScript的世界中,所有的代码都是单线程执行的。由于这个“缺陷”,导致JavaScript所有的网络操作、浏览器事件,都必须是异步执行的。promise是异步编程的一种方式,比传统的解决方案(回调函数与事件)更合理、更强大。
回调:是指一个函数作为参数传递到另一个函数中,并在另一个函数执行结束后执行。
异步回调:是由于JS的单线程,在很多情况下(ajax请求远程数据,IO等),非常耗时。如果一直单线程的堵塞下去,会导致程序等待时间过长页面失去响应,影响用户体验。为解决这个问题,我们将耗时间的都扔给异步去做,做好了再通知我们,再拿着数据往下走。
传统的异步编程(回调函数与事件)缺点:“回调地狱”,有太多的异步步骤需要一步一步执行,或者一个函数里面有太多异步操作,这就产生大量的嵌套的回调,使代码嵌套太深而难以阅读与维护。promise解决了这一问题。
promise原理
(1)对象的状态不受外界影响。promise对象代表一个异步操作,有3种状态:pending(进行中)、fulfilled(已完成)、rejected(以失败)。只有异步操作的结果可以决定当前处于哪一种状态,任何其他操作都无法改变这个状态。
(2)一旦状态改变就不会再改变了,任何时候都可以得到这个结果。promise的状态改变只有两种可能:从pending到fulfilled;从pending到rejected。具体流程如下:
 
Promise的使用:
function loadImg(src) { //1、new Promise一个实例对象,并且将该实例return,作为then方法回调函数的参数,本例中是img //2、该实例对象接受一个函数作为参数,该函数的有两个参数,resolve和reject,它们也是两个函数,由JS引擎提供,不需要自己部署 //3、成功时执行resolve函数,失败时执行reject函数 const promise = new Promise(function (resolve,reject) { var img = document.createElement('img'); img.onload = function () { resolve(img) //成功时执行resolve函数 } img.onerror = function () { reject() //失败时执行reject函数 } img.src = src; }) return promise; } var src = "http://www.imooc.com/static/img/index/logo_new.png"; var result = loadImg(src); //4、then()监听结果;第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数 result.then(function (img) { console.log(img.width);//resolve(成功)时候的回调函数 },function () { console.log("failed");//rejected(失败)时候的回调函数 })
async函数
(1)async函数返回一个promise对象,可以用then(callback)添加回调函数。当函数执行的时候,遇到await会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
(2)async关键字,表明该函数内部有异步操作,调用该函数会立即返回一个promise对象。
promise题目:关于JavaScript执行机制的
promise构造函数是立即执行的
const first = () => (new Promise((resolve,reject)=>{ console.log(3); let p = new Promise((resolve, reject)=>{ console.log(7); setTimeout(()=>{ console.log(5); resolve(6); },0) resolve(1); }); resolve(2); p.then((arg)=>{ console.log(arg); }); })); first().then((arg)=>{ console.log(arg); }); console.log(4); 链接:https://juejin.im/post/5af800fe518825429c594f92
八、浏览器
1、从URL输入到显示页面,发生了什么?
第一步:客户机提出域名解析请求,并将该请求发送给本地的域名服务器。 第二步:当本地的域名服务器收到请求后,就先查询本地的缓存,如果有该纪录项,则本地的域名服务器就直接把查询的结果返回。 第三步:如果本地的缓存中没有该纪录,则本地域名服务器就直接把请求发给根域名服务器,然后根域名服务器再返回给本地域名服务器一个所查询域(根的子域)的主域名服务器的地址。 第四步:本地服务器再向上一步返回的域名服务器发送请求,然后接受请求的服务器查询自己的缓存,如果没有该纪录,则返回相关的下级的域名服务器的地址。 第五步:重复第四步,直到找到正确的纪录。 第2种解释: 一般会经历以下几个过程: 1、首先,在浏览器地址栏中输入url 2、浏览器先查看浏览器缓存-系统缓存-路由器缓存,如果缓存中有,会直接在屏幕中显示页面内容。若没有,则跳到第三步操作。 3、在发送http请求前,需要域名解析(DNS解析)(DNS(域名系统,Domain Name System)是互联网的一项核心服务,它作为可以将域名和IP地址相互映射的一个分布式数据库,能够使人更方便的访问互联网,而不用去记住IP地址。),解析获取相应的IP地址。 4、浏览器向服务器发起tcp连接,与浏览器建立tcp三次握手。(TCP即传输控制协议。TCP连接是互联网连接协议集的一种。) 5、握手成功后,浏览器向服务器发送http请求,请求数据包。 6、服务器处理收到的请求,将数据返回至浏览器 7、浏览器收到HTTP响应 8、读取页面内容,浏览器渲染,解析html源码 9、生成Dom树、解析css样式、js交互 10、客户端和服务器交互 11、ajax查询 原文链接:https://blog.csdn.net/xm1037782843/article/details/80708533
九、问题
1、let arr = JSON.parse(JSON.stringify(this.sealTableData[index])); //对JSON对象实现深拷贝,开辟一个新的存储地址,两个对象彼此新增、删除元素,互不影响;
2、申请发起失败,input表单输入无限制,后台数据库存不进数据,报错;对表单进行限制。
3、文件上传过程,点击复制或者新增一行,表格错位;原因:数据未请求过来网页没有刷新,文件上传前beforeUpload,设置页面加载this.loading=true;文件上传成功或者失败的回调函数中,设置this.loading=false,页面加载关闭,进行下面操作。
4、
十、git
十一、webpack
项目创建、文件打包
零、其他
原文:
https://juejin.im/post/5b037b536fb9a07aa9260b39#heading-32
https://juejin.im/post/5abf531d6fb9a028dc412419#heading-28
 
                     
                    
                 
                    
                 
 
                
            
        