title: 仔显示图片的时候,鼠标以上可以显示一些信息,一般为建议、提示类型
alt : 当网速不佳,或者因其他原因图片加载不出来,代替图片解释的信息
有区别,但区别不明显,浏览器显示不出来。
section:定义文档中的一个章节
nav:定义只包含导航链接的章节
header:定义页面或章节的头部。它经常包含 logo、页面标题和导航性的目录。
footer:定义页面或章节的尾部。它经常包含版权信息、法律信息链接和反馈建议用的地址。
aside:定义和页面内容关联度较低的内容——如果被删除,剩下的内容仍然很合理。
a. 去掉或者丢失样式的时候能够让页面呈现出清晰的结构
b. 有利于SEO:和搜索引擎建立良好沟通,有助于爬虫抓取更多的有效信息:爬虫依赖于标签来确定上下文和各个关键字的权重;
c. 方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)以意义的方式来渲染网页;
d. 便于团队开发和维护,语义化更具可读性,遵循W3C标准的团队都遵循这个标准,可以减少差异化。
a. HTML5 现在已经不是 SGML 的子集,主要是关于图像,位置,存储,多任务等功能的增加。
b. 拖拽释放(Drag and drop) API
c. 语义化更好的内容标签(header,nav,footer,aside,article,section)
d. 音频、视频API(audio,video)
e. 画布(Canvas) API
f. 地理(Geolocation) API
g. 本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失
h. sessionStorage 的数据在页面会话结束时会被清除
i. 表单控件,calendar、date、time、email、url、search
j. 新的技术webworker, websocket等
移除的元素:
a. 纯表现的元素:basefont,big,center, s,strike,tt,u;
b. 对可用性产生负面影响的元素:frame,frameset,noframes;
答:
cookies:服务器和客户端都可以访问,大小只有4KB左右,有有效期,过期后将会删除;
localStorage:将数据保存在本地的硬件设备,没有时间限制,关闭浏览器也不会丢失。永久保cun
sessionStorage:将数据保存在session对象中,关闭浏览器后数据也随之销毁。临时保存。
答:
它们之间的共同点:都是保存在浏览器端,且是同源的。
它们之间的区别:
答:
get方式和post方式提交数据的区别:
1) 大小不同,get方式传输的数据量较小,而post可以传输大量的数据。
2) 安全程度不同,get方式传输数据能够被别人轻易的看到数据内容,所以安全程度较低,
而post则可以很好的隐藏。
3) 速度不同,post方式速度较慢,而get方式速度较快。
4) 在服务器上的作用不同,get是从服务器上获取数据,而post是向服务器上传送数据。
在实际开发中的应用:
1)在重要数据进行传输数据的时候,用post的方式进行提交数据。
2)在做数据查询的时候,用get的方式进行提交数据。
3)在做增加、删除和修改数据的时候,用post的方式进行提交数据。
答:
块级元素:div、p、h1-h6、ol、ul、table、form
行内元素:span、a、img、input、select、small
空元素:没有内容的元素、 br、 hr
答:
1)src用于替换当前元素;href用于在当前文档和引用资源之间确立联系。
2)src是source的缩写,指向外部资源的位置,指向的内容将会嵌入到文
档中当前标签所在位置。
3)href是Hypertext Reference的缩写,指向网络资源所在位置,建立和
当前元素(锚点)或当前文档(链接)之间的链接。
常见的布局方式:固定布局、流式布局、弹性布局、浮动布局、定位布局、margin和padding
a. 添加额外标签,例如
<div style="clear:both"></div>
b. 父元素设置 overflow:hidden auto;
c. 父元素也设置浮动
a. link属于HTML标签,而@import是CSS提供的,且只能加载 CSS
b. 页面被加载时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载
link方式的样式的权重 高于@import的权重
相同:
a. 改变行内元素的呈现方式,display被置为block
b. 让元素脱离普通流,不占据空间
c. 默认会覆盖到非定位元素上
区别:
absolute的”根元素“是可以设置的,而fixed的”根元素“固定为浏览器窗口。
当你滚动网页,fixed元素与浏览器窗口之间的距离是不变的。
absolute:生成绝对定位的元素,相对于 static 定位以外的第一个祖先元素进行定位
fixed:生成绝对定位的元素,相对于浏览器窗口进行定位。 (IE6不支持)
relative:生成相对定位的元素,相对于其在普通流中的位置进行定位
static:默认值。没有定位,元素出现在正常的流中
CSS3实现圆角(border-radius),阴影(box-shadow),对文字加特效(text-shadow),线性渐变(gradient),变形(transform)
如果使用import方法对CSS进行导入,会导致某些页面在Windows下的IE出现一些奇怪的现象:
以无样式显示页面内容的瞬间闪烁,这种现象称之为文档样式短暂失效(Flash of Unstyled Content),
简称为FOUC。
原理:当样式表晚于结构性html加载,当加载到此样式表时,页面将停止之前的渲染。
此样式表被下载和解析后,将重新渲染页面,也就出现了短暂的花屏现象。
解决方法:
使用LINK标签将样式表放在文档HEAD中。
BFC, 可以理解为他是运用一些渲染规则的块渲染区域,他是css世界中的结界,为何说是结界,
因为在触发了BFC 特性的容器下元素和容器外部元素完全隔离,子元素的布局不会影响外部元素,
反之亦然
BFC 元素有如下一些特征:
BFC 的块不会和浮动块重叠
计算BFC 元素的高度时,会包括浮动元素
在一个BFC下的块 margin 会发生重叠 ,不在同一个则不会
BFC元素是一个独立的容器,使得里面的元素和外部元素隔离开,互不影响
触发BFC:
float的值不为 none
overflow 的值为 auto ,scroll 和 hidden
display 的值为 table-cell , table-caption 和 inline-block
position 设置为 absolute 和 fixed
除此之外, html 元素本身默认就是一个 BFC 元素
把所有的网页元素都看成一个盒子,它具有:
content,padding,border,margin
四个属性,这就是盒子模型。
有两种, IE盒子模型、W3C盒子模型;
盒模型: 内容(content)、填充(padding)、边界(margin)、 边框(border);
区 别: IE的content部分把 border 和 padding计算了进去;
px 是绝对单位
em 相对单位,基于父节点字体大小
rem 会继承父级元素的字体大小
使用 rem 为元素设定字体大小时,仍然是相对大小,但相对的只是HTML 跟元素
重绘:当渲染树中的元素外观(如:颜色)发生改变,不影响布局时,产生重绘
回流:当渲染树中的元素的布局(如:尺寸、位置、隐藏/状态状态)发生改变时,产生重绘回流
触发BFC的条件:
作用:
1.已知宽高的情况
方法一:
position:absolute;
left:50%;top:50%;
margin-top:-高度/2
margin-left:-宽度/2
方法二:
position:absolute;
margin:auto;
top:0;
right:0;
bottom:0;
left:0;
2.未知宽高
transform:translateX(-50%) translateY(-50%)
3.父元素有高度的情况下并且只有一个div子元素
display:flex;
justify-content:center;
align-items:center
在img标签后添加空span行内标签,给控标签设置样式
span{
width:0;
height:100%
line-height
}
给img添加属性
img{
vertical-align: middle;
}
方法二:
弹性盒布局
- Promise 是异步编程的一种解决方案,从语法上讲,Promise是一个对象,可以获取异步操作的消息
- Promise 最主要的交互方式:将回调函数传入 then 方法来获得最终结果或出错原因
- Promise 代码书写上的表现:以“链式调用”代替回调函数层层嵌套(回调地狱)
更多promise 介绍请看:https://blog.csdn.net/weixin_47076989/article/details/107200004
宏任务(macro-task):整体代码script、setTimeOut、setInterval
微任务(mincro-task):promise.then、promise.nextTick(node)
更多事件循环机制、宏任务、微任务介绍:
https://blog.csdn.net/weixin_47076989/article/details/107890187
什么是同源策略?
什么是跨域?你有几中方式可以解决跨域问题?
跨域是指在浏览器上进行非同源请求的行为
1.因为浏览器处与安全考虑,有同源策略,也就是说,如果协议,域名或者端口号有一个不同就是跨域,ajax 请求会失败
2.那么是处于什么安全考虑才会引入这种机制呢,其实主要是用来防止,CSRF 攻击的, 简单点说 CSRF 攻击是利用用户的登入状态发起恶意请求也就是没有同源策略的条件下,A网站可以被任意其他来源的Ajax访问到内容,如果你当前A 网站还存在登录态, 那么对方可以通过Ajax获得你的任何信息,当然跨域并不能完全阻止CSRF
怎么解决跨域问题?
JSONP:(只限于get请求)
script可以把请求内容当做字符串读取,解析成js代码
src:不受同源策略的影响,只要返回的js代码正确就可以了
CORS :
CORS 需要浏览器和后端同时支持,IE 8 和 9 需要通过 XDomainRequest
来实现。
后端设置(服务端) Access-Control-Allow-Origin
nginx代理跨域
详细call apply bind 见CSDN网址 :https://blog.csdn.net/weixin_47076989/article/details/107200176
共同点:用于浏览器端存储的缓存数据;
不同点:
(1)、存储内容是否发送到服务器端:当设置了Cookie后,数据会发送到服务器端,造成一定的宽带浪费;
web storage,会将数据保存到本地,不会造成宽带浪费;
(2)、数据存储大小不同:Cookie数据不能超过4K,适用于会话标识;web storage数据存储可以达到5M;
(3)、数据存储的有效期限不同:cookie只在设置了Cookid过期时间之前一直有效,即使关闭窗口或者浏览器;
sessionStorage,仅在关闭浏览器之前有效;localStorage,数据存储永久有效;
(4)、作用域不同:cookie和localStorage是在同源同窗口中都是共享的;sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;
1.xss-跨站脚本攻击
XSS(Cross Site Scripting),跨站脚本攻击。XSS是常见的Web攻击技术之一.所谓的跨站脚本攻击指得是:恶意攻击者往Web页面里注入恶意Script代码,用户浏览这些网页时,就会执行其中的恶意代码,可对用户进行盗取cookie信息、会话劫持等各种攻击.
解决方案:
每个实例对象( object )都有一个私有属性(称之为 proto )指向它的构造函数的原型对象(prototype )。该原型对象也有一个自己的原型对象( proto ) ,层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节 (原型链)
闭包、原型、原型链 详情:https://blog.csdn.net/weixin_47076989/article/details/106932640
js数据类型分为基本数据类型和复杂数据类型
基本数据类型:String、Blooen、Number、undefind、null、
复杂数据类型:Array、Object
在电脑中存储js数据的地方分为栈和堆
基本数据类型是存储在栈里面的,复杂数据类型是存储在堆里面的,而暴露出来的是引用地址存在在栈中
浅拷贝:
//方法一:
var obj1={
name:"wangwu"
}
var obj2=obj1
//方法二:
var obj3={...obj1}
//方法三:
for(var key in obj1){
obj4[key]=obj1[key]
}
深拷贝:
//方法一:
var obj1={
name:"yeshuai"
}
var obj2={}
var obj2={...obj1}
//方法二:
var obj3=JSON.parse(JSON.stringify(obj1))
1. 客户端输入用户名和密码
2. 服务端来验证这个用户名和密码 如果是正确的 会签发一个token 再把这个 token 返回给客户端
3. 客户端把这个token 存储起来
4. 客户端每次像服务端请求资源的时候需要带着服务端签发的 token
5. 服务端 然后做比较 如果是验证成功 ,就会返回客户端请求的数据
基本思想是使用对象,类,继承,封装等基本概念来进行程序设计
优点:
面向对象与面向过程的区别
1、面向过程代码复用性不高,面向对象复用性高
2、面向过程是对步骤进行的操作及划分,面向对象则是以功能去划分,保证了功能的统一
typeof
是否能正确判断类型?instanceof
能正确判断对象的原理是什么?
typeof
对于原始类型来说,除了 null
都可以显示正确的类型
typeof 1 // 'number'
typeof '1' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
typeof
对于对象来说,除了函数都会显示 object
,所以说 typeof
并不能准确判断变量到底是什么类型
typeof [] // 'object'
typeof {} // 'object'
typeof console.log // 'function'
如果我们想判断一个对象的正确类型,这时候可以考虑使用 instanceof
,因为内部机制是通过原型链来判断的
const Person = function() {}
const p1 = new Person()
p1 instanceof Person // true
var str = 'hello world'
str instanceof String // false
var str1 = new String('hello world')
str1 instanceof String // true
对于原始类型来说,你想直接通过 instanceof
来判断类型是不行的
1.计算字符串的长度
str.length
,会计算空格数。2.查找字符在字符串中的位置:
Str.indexof("要找的字符")
,从前往后找,只找第一个,返回值是索引。没有找到返回值-1,兼容性很好。Str.lastIndexof("要找的字符")
,从后往前找,只找第一个,返回值是索引。没有找到返回值-1,兼容性很好。3.根据传入索引,查找该元素是什么
Str.charAt(index)
4.根据传入索引,查找该元素编码是什么
Str.charCodeAt(index)
5.根据字符编码查找该字符
String.fromCharCode()
6.字符串截取的方法
Str.slice(start,end)
作用:对字符串截取,start表示截取的开始元素,end表示截取的截止元素,包前不包后。
返回值:截取的字符串
console.log(str.slice(0,4));//0是起始索引,4是结束索引,不包含4
console.log(str.slice(4));//表示从4到结束
console.log(str.slice(-3));//表示倒数第三到最后
Str.substr(start,length)
作用:对字符串截取,start表示截取的开始元素,length表示截取的长度
返回值:截取的字符串
console.log(str.substr(0,2));//从0开始截取2个
console.log(str.substr(2));//从2开始到最后
console.log(str.substr(-3,2))//从倒数第三个,截取2个
str.substring(start,end)
7.字符串变小写
Str.toLowerCase()
8.字符串变大写
Str.toUpperCase()
9.去除前后空格
str.trim()
1.1.增
数组.unshift(item)
; 从数组前面增加一个元素
数组.push(item)
:从数组后面增加一个元素
1.2.删
数组.shift()
:删除数组中的第一个元素
数组.pop()
:删除数组中的最后一个元素
数组.splice(start,n)
:** 从数组的start位置开始删除n个元素
数组.splice(start,n,.....)
:从数组的start位置开始删除n个元素,然后再添加什么元素
1.3.截取
数组.slice(start,end)
:从数组中截取一部分
1.4.颠倒数组
数组.reverse()
:颠倒数组
1.5.连接数组
数组1.concat(数组2,数组3,......)
:
1.6.数组变字符串
1.7.查询
数组.indexof(ele,start)
作用:查找数组中某个元素的索引
返回值:如果没找到就返回-1,如果找到了就返回该元素的索引值。
参数:第一个参数ele是:要查找的那个元素
第二个参数start:从哪里开始查找,默认从零开始找
数组.lastIndexof(ele,start)
作用:查找数组中某个元素的索引
返回值:如果没找到就返回-1,如果找到了就返回该元素的索引值。
参数:第一个参数ele是:要查找的那个元素
第二个参数start:从哪里开始查找,默认从零开始找
1.8.数组排序
数组.sort(fn)
;
作用:按照指定规则进行排序
参数:如果不写参数,默认是按照字符编码的顺序进行排序,如果写参数,参数fn是表示排序 规则的函数
返回值:返回值就是拍好序的数组
注意点:直接在原数组操作
有参数:参数是表示排序规则的函数
示例“
1.for循环
for(var i=0;i<arr.length;i++){
console.log(arr[i])
}
2.for in 循环
for( var index in arr){
//固定写法,arr是要循环的数组,index是循环到的那个元素的索引
console.log("当前循环到的是第"+index+'个元素,元素的值是:'+arr[index])
}
3.forEach()循环
数组.forEach(function(value,index){
要循环执行的函数,数组里面有多少个元素,该函数就执行多少次
console.log("当前循环到的是第"+index+'个元素,元素的值是:'+value)
})
//参数:要循环执行的函数,函数有两个形参,第一个形参实循环到的那个数组元素的值,第二个形参实循环到的那个数组元素的索引
//注意点:不会改变原数组
4.map()循环
数组.map(function(value,index){
要循环执行的函数,数组里面有多少个元素,该函数就执行多少次
return value-1
})
//作用:循环数组
//参数:要循环执行的函数,函数有两个形参,第一个形参实循环到的那个数组元素的值,第二个形参实循环到的那个数组元 素的索引
//返回值:整个map的返回值是每一次循环的函数的返回值的集合
//示例:
var arr = [23,45,43,78,23,12,46,28,97];
console.log(arr)
var newArr = arr.map(function(value,index){
return value-1;
})
console.log(newArr)//newArr = [22,44,42,77,22,11,45,27,96]
5.fliter()循环
数组.fliter(function(value,index){
//要循环执行的函数,数组里面有多少个元素,该函数就执行多少次
//符合条件的返回true
//不符合条件的返回false
if(value>40){
return console.log(true);
}else{
return false;
}
})
//作用:过滤数组中符合条件的元素,返回值是新的数组
6.every()循环
数组.every(function(value,index){
//要循环执行的函数,数组里面有多少个元素,该函数就执行多少次
})
//作用:判断数组中的每一个元素是否都符合条件,符合返回值true,不符合返回值false
//示例:
var arr = [1,15,26,48,45,25,14,44]
var res = arr.every(function(value,index){
return value>30;
})
console.log(res)
7.some()循环
数组.some(function(value,index){
//要循环执行的函数,数组里面有多少个元素,该函数就执行多少次
})
//作用:判断数组中的每一个元素是否有符合条件,符合返回值true,不符合返回值false
//示例:
var arr = [1,15,26,48,45,25,14,44]
var res = arr.every(function(value,index){
return value>30;
})
console.log(res)
1.for in()
var obj = {"name":"tom","sex":"male"};
Object.defineProperty(obj, "age", {value:"18", enumerable:false});//增加不可枚举的属性age
Object.prototype.protoPer1 = function(){console.log("name is tom");};//通过原型链增加属性,为一个函数
Object.prototype.protoPer2 = 2;通过原型链增加属性,为一个整型值2
for(var key in obj){
console.log(key)//['name','sex','protoPer1','protoPer1']
}
2.Object.keys()
Object.keys主要用于遍历对象自有的可枚举属性,不包括继承自原型的属性和不可枚举的属性。
var obj = {"name":"tom","sex":"male"};
Object.defineProperty(obj, "age", {value:"18", enumerable:false});//增加不可枚举的属性age
Object.prototype.protoPer1 = function(){console.log("name is tom");};//通过原型链增加属性,为一个函数
Object.prototype.protoPer2 = 2;通过原型链增加属性,为一个整型值2
console.log("Object.keys:")
console.log(Object.keys(obj));//["name",'sex']
3.Object.getOwnPropertyNames()
Object.getOwnProperty主要用于返回对象的自有属性,包括可枚举和不可枚举的属性,不包括继承自原型的属性。
var obj = {"name":"tom","sex":"male"};
Object.defineProperty(obj, "age", {value:"18", enumerable:false});//增加不可枚举的属性age
Object.prototype.protoPer1 = function(){console.log("name is tom");};//通过原型链增加属性,为一个函数
Object.prototype.protoPer2 = 2;通过原型链增加属性,为一个整型值2
console.log("Object.getOwnPropertyNames: ");
console.log(Object.getOwnPropertyNames(obj));//["name","sex","age"]
1. 将 json 对象转化为 json 字符串,在判断该字符串是否为 {}
2. for in 循环判断
3. ES6 的 Object.keys() 方法,返回值也是对象中属性名组成的数
1.for循环嵌套,利用splice去重
function newArr(arr){
for(var i=0;i<arr.length;i++){
for(var j=i+1;j<arr.length;j++){
if(arr[i]==arr[j]){
//如果第一个等于第二个,splice方法删除第二个
arr.splice(j,1);
j--;
}
}
}
return arr;
}
let a= m.map((item,index,array)=>{
console.log(array)
})
console.log(a)
2.建新数组,利用indexOf去重
function newArr(array){
//一个新的数组
var arrs = [];
//遍历当前数组
for(var i = 0; i < array.length; i++){
//如果临时数组里没有当前数组的当前值,则把当前值push到新数组里面
if (arrs.indexOf(array[i]) == -1){
arrs.push(array[i])
};
}
return arrs;
}
3.ES6中利用Set,Array.from去重
function newArr(arr){
return Array.from(new Set(arr))
}
4.ES6中利用Set,扩展运算符去重
function newArr(array){
return arr=[new Set(array)]
}
1.事件捕获
event.stopPropagation()
2.事件冒泡
event.cancelBubble=false
低版本IE
3.阻止浏览器默认行为:火狐/谷歌
event.preventDefault()
4.阻止浏览器默认行为:低版本IE
event.returnValue=false
更全面的 ajax 知识,详细见网址 :https://blog.csdn.net/weixin_47076989/article/details/107109094
1.语义化不一样
GET倾向于从服务器获取数据
post倾向于从服务器提交数据
2.传递参数的方式
GET请求直接在地址栏后边拼接
post请求在请求体里面传递
3.参数大小限制
GET请求一般理论上不大于2KB
post请求理论上没有上线
4.缓存能力
GET会被浏览器主动缓存
POST不会被浏览器主动缓存
5.安全性能
GET请求相对安全性较低
POST请求相对安全性较高
get/post本质上都是tcp连接
cdn 加速器
路由懒加载
v-if 和 v-show 的选择使用
图片懒加载
异步组件
第三方库按需引入
浏览器缓存
特点:
由于ES5的object.definedProperty()这个方法不兼容 IE8,所以我们的vue的兼容性也是不兼容 IE8 及以下版本
MVVM分为Model、View、ViewModel三者。
Model 代表数据模型,数据和业务逻辑都在Model层中定义;
!!!需要注意的是,当我们启用 history 模式的时候,由于我们的项目是一个单页面应用,所以在路由跳转的时候,就会出现访问不到静态资源而出现 404 的情况,这时候就需要服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面
v-model:一般用在表达输入,很轻松的实现表单控件和数据的双向绑定
v-html:更新元素的innerHTML
v-show与v-if:条件渲染,注意二者区别
v-on:click:可以简写为@click,@绑定一个事件。如果事件触发了,就可以指定事件的处理函数
v-for:基于源数据多次渲染元素或模板
v-bind:当表达式的值改变时,将其产生的连带影响,响应式地作用于DOM语法
v-bind:title=”msg”简写:title="msg"
v-model:一般用在表达输入,很轻松的实现表单控件和数据的双向绑定
v-html:更新元素的innerHTML
v-show与v-if:条件渲染,注意二者区别
v-on:click:可以简写为@click,@绑定一个事件。如果事件触发了,就可以指定事件的处理函数
v-for:基于源数据多次渲染元素或模板
v-bind:当表达式的值改变时,将其产生的连带影响,响应式地作用于DOM语法
v-bind:title=”msg”简写:title="msg"
虚拟dom与diff运算:
diff运算:
减少Dom操作 提高组件复用性
diff运算:新的虚拟dom与旧的虚拟dom对比,找出**最小差异**,发送给真实的dom进行更新
beforeCreate
: vue实例的挂载元素el和数据对象data都为undefined,还未初始化。created
: vue实例的数据对象data有了,el还没有beforeMount
: vue实例的$el和data都初始化了,但还是挂载之前为虚拟的dom节点,data.message还未替换。mounted
: vue实例挂载完成,data.message成功渲染。beforeUpdate
: 数据更新前调用Update
: 数据更新后调用beforeDestroy
:适合移除事件、定时器等等,否则可能会引起内存泄露的问题。destroyed
: 进行一系列的销毁操作,如果有子组件的话,也会递归销毁子组件,所有子组件都销毁完毕后才会执行第一次页面加载会触发哪几个钩子?
简单描述每个周期具体适合哪些场景?
父组件向子组件通信
子组件通过 props 属性,绑定父组件数据,实现双方通信
子组件向父组件通信
将父组件的事件在子组件中通过 $emit 触发
非父子组件、兄弟组件之间的数据传递
路由的概念就是, 能够通过不同的请求地址来响应不同的页面或数据
视图: router-view 路由坑 路由匹配到的组件将渲染在这里
导航: router-link 路由跳转 相当于a标签 没有a标签的#号 而且还自带样式 .router-link-active 还有起到跳转作用
1. v-if 是真正的条件渲染, 默认条件为false时元素不渲染,
默认条件为true时元素渲染 条件变为false时元素会销毁,
条件变为true时元素会重新创建。
而 v-show 只是简单的去控制元素的css的display属性。
2. v-show 有更高的初始渲染开销(因为不管默认条件为真还是假,都会渲染出来)
v-if 有更高的切换开销(切换时做销毁与重建的操作) 如果需要频繁切换显示
隐藏使用v-show更好,其余情况使用v-if就好。
3. v-if 有 v-else v-else-if 去配套使用。
v-show 没有,它是孤零零的一个人
4. v-if 能配合 template 元素使用,而 v-show 不能。
优点:
良好的交互体验
良好的前后端工作分离模式
减轻服务器压力
缺点:
SEO难度较高
前进、后退管理
初次加载耗时多
keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染
keep-alive
组件包裹需要保存的组件。keep-alive
组件来说,它拥有两个独有的生命周期钩子函数,分别为 activated
和 deactivated
。用 keep-alive
包裹的组件在切换时不会进行销毁,而是缓存到内存中并执行 deactivated
钩子函数,命中缓存渲染后会执行 actived
钩子函数。数据驱动 组件系统
1.url 地址表现不同,hash模式有#号,history模式没有
2.实现原理不同
3. 兼容不同 :
1.hash模式都可以兼容
2.histyory 模式只能兼容到IE10及以上
3.history 模式会出现404 找不到页面这种问题,需要后端配置相关的处理才行,而hash 模式没有这个问题
4.history 模式时,重定向会有些问题 ,需要页面的名字叫index.html才行
使用代码分割 实现代码分割 让组件按需加载 优化项目 性能
使用 key
shouldconmpoentUpdate
组件尽可能的进行拆分
传参优化
多组件优化
相同点:
1、 数据驱动页面,提供响应式的视图组件
2、 都有 virtual DOM 组件化的开发, 通过props参数进行父子之间组件传递数据,都实现了 webComponents 规范
3、 数据流动单向,都支持服务端的渲染 SSR
4、 都有支持native的方法, react 有 react native vue有 wexx
不同点:
1. 数据绑定: Vue实现了双向的数据绑定,react 数据流动是单向的
2. 数据渲染: 大规模的数据渲染, react更快
3. 使用场景: React 配合Redux 架构适合大规模多人协作复杂项目,Vue 适合小快 的项目
4. 开发分格, react推荐做法 jsx+ inline style 把html和css都写在js了 , vue是采用 webpack +vue-loader 单文件组件格式 html,js,css同一个文件
1. 声明式设计 - React采用声明范式,可以轻松描述应用
2. 高效 - React 通过对Dom的模拟(虚拟Dom),最大限度减少与Dom的交互
3. 灵活 - React 可以与一直的库或框架很好的配合
4. JSX - JSX 是 JavaScript 的语法扩展
5. 组件 - 通过React构建组件,使得代码更加容易得到复用,能够很好的应用在大项目的开发中
6. 单项响应的数据流 - React 实现了单项响应的数据流,从而减少了重复代码,这也是它为什么比传统的绑定更简单。
1. 代码简洁,开发快速
2. 接近自然语言,易于理解
3. 更方便的代码管理
4. 易于"并发编程“
5. 代码的热升级
componentWillMount :render之前最后一次修改状态的机会
render : 只能访问this.props和 this.state,不允许修改状态和Dom 输出
componentDidMount :成功render并渲染完成真实Dom之后触发,可以修改DOM
componentWillReceiveProps :父组件修改属性触发
shouldComponentUpdate :返回false会阻止render调用
componentWillUpdate :不能修改属性和状态
render : 只能访问this.props和 this.state,不允许修改状态和Dom 输出
componentDidUpdate : 可以修改DOM
componentWillUnmount :在删除这个组件前进行清理操作
问题:
解决:
getDerivedStateFromProps
第一次的初始化组件以及后续的更新过程中(包括自身状态更新以及父传子) ,返回一个对象作为新的state,返回null则说明不需要在这里更新state
static getDerivedStateFromProps(nextProps){
if(nextProps.value!==undefined){
return{
current:nextProps.value
}
}
return null
}
getSnapshotBeforeUpdate
取代了 componetWillUpdate ,触发时间为update发生的时候,在render之后dom渲染之前返回一个值,作为componentDidUpdate的第三个参数
shouldComponentUpdate
PureComponent
real Dom
1. 更新缓慢
2. 可以直接更新 HTML
3. 如果元素更新,则创建新DOM
4. DOM 操作代价很高
5. 消耗的内存较多
Virtual DOM
1. 更新更快
2. 无法直接更新 HTML
3. 如果元素更新,则更新JSX
4. DOM 操作非常简单
5. 很少的内存消耗
React 是一个用于构建用户界面的 JAVASCRIPT 库。
React主要用于构建UI,很多人认为 React 是 MVC 中的 V(视图)。
React 起源于 Facebook 的内部项目,用来架设 Instagram 的网站,并于 2013 年 5 月开源。
React 拥有较高的性能,代码逻辑非常简单,越来越多的人已开始关注和使用它。
React 的一些主要特点是:
它提高了应用的性能
可以方便地在客户端和服务器端使用
由于JSX ,代码的可读性很好
使用 React,编写UI 测试用例变得非常容易
高阶函数就是一个纯js且没有副作用的函数。
高阶组件是一个纯函数,也是容器组件.是参数为组件,返回值为新组件的函数.
高阶组件就是一个函数,且该函数接受一个组件作为参数,并返回一个新的组件的函数。
高阶函数就是一个纯js且没有副作用的函数。
高阶组件是一个纯函数,也是容器组件.是参数为组件,返回值为新组件的函数.
高阶组件就是一个函数,且该函数接受一个组件作为参数,并返回一个新的组件的函数。
高阶函数 : 一个函数内部返回一个新的函数,内部采用闭包的写法
var add = x => {
return y => {
return x+y
}
}
高阶组件:(HOC) Higher-Order-Component
高阶组件本质上就是一个函数,内部可以接收一个组件,然后返回新的组件。
例如: React.memo() connect()
父子通信
兄弟组件通信:
对于这种情况可以通过共同的父组件来管理状态和事件函数,比如说其中一个兄弟组件调用父组件传递过来的事件函数修改父组件中的状态,然后父组件将状态给另一个兄弟组件
跨多层次组件通信:
如果你使用16.3 以上版本的话,对于这种情况可以使用 Context API
任意组件:
这种方式可以通过Redux 或者 Event Bus 解决,另外如果你不怕麻烦的话,可以使用这种方式解决上述所有的通信情况
ES5组件 React.createElement()
类组件 class User extends React.Component {}
无状态组件 function User(props) {}
高阶组件 function Hoc(Child) { }
Hocks 组件
jsx = javascript xml 语法糖
jsx 变量、对象
jsx 不是强制的,但jsx让代码更具可读性
jsx 可以嵌套
jsx 中可以使用表达式,使用方法用 单大括号进行包裹
jsx 语法更接近javascript 而不是html
React 组件的生命周期有三个不同的阶段:
1.初始化阶段
componentWillMount: rende之前最后一次修改状态的机会
render: 只能访问 this.props和 this.state,不允许修改状态和DOM 输出
componentDidMount: 成功render并渲染完成真实DOM 之后触发
可以修改DOM
2.运行中阶段
componentWillReceiveProps: 父组件修改属性触发
shouldComponentUpdata: 返回 false 会阻止render调用
componentWillUpdate: 不能修改属性和状态
render: 只能访问this.props 和this.state , 不允许修改态和DOM 输出
componentDidUpdate: :可以修改DOM
3.销毁阶段
componentWillUnmount: 再删除组件之前进行清理操作,比如计时器和事件监听器
一些最重要的生命周期方法是:
componentWillMount
创建实例前
render 渲染数据
componentDidMount
创建实例完成
componentWillUpdate
更新前
componentDidUpdate
更新完成 这个每次都会重新请求 不会判断如果是一样的就不更新
shouldcomponentUpdate(nextProps,nextState)
nextProps新的值 nextState老的值 这个可以判断是否更新 默认是true更新 就会一直更新 不应该更新就返回false 这里就是要判断应不应该更新 如果更新之后的值和之前的值是一样的话 就返回 false 不让他更新了
componentWillReceiveProps(nextProps) nextProps
更改之后的值 这个生命周期 是在 父组件属性发生改变才会触发
componentWillunmount
销毁就会触发这个
新增生命周期:==========================
初始化: getDeriveStateFromProps(nextProps,nextState
) nextState老数据 nextProps更新之后的数据 使用的时候要加 static getDerivedStateFromProps(nextProps,nextState)
更新: getDeriveStateFromProps(nextProps,nextState)
nextState老数据 nextProps更新之后的数据 这个生命周期只要是父组件调用 setState 就会走整个的更新阶段,
getDeriveStateFromProps 这个生命周期 相当于两个作用 一个是初始化的时候一个更新就的时候就是父组件属性发生属性发生改变就会触发这里
更新:getSnapshotBeforeUpdate
这个就是更新之前会触发的 ,但是的话就是先会执行render渲染 然后立马执行 getSnapshotBeforeUpdate 然后这个必须有返回值 这个返回值可以在更新完成那个生命周期的第三个参数接收到
这个相当于有个快照的感觉,就是一渲染立马会记录那个状态,这个是渲染在更新,会记录那个瞬间的值
其值由state控制的输入表单元素称为“受控组件”。
其值由真实DOM控制的输入表单元素称为“非受控组件”。
原则:
不会改变参数
相同的输入一定产生相同的输出
异步的
首先 setState 的调用并不会马上引起。 state 的改变,并且如果你一次调用了多个,
setState ,那么结果可能并不如你期待的一样
可以传第二个参数
父组件通过 props 传递给子组件
子-父 通过 自定义事件
兄弟组件通信 context
任意组件 redux event Bus
我们应该将 AJAX 请求放到 componentDidMount 函数中执行,主要原因有下:
当调用 setState 时,React会做的第一件事情是将传递给 setState 的对象合并到组件的当前状态。这将启动一个称为和解(reconciliation)的过程。和解(reconciliation)的最终目标是以最有效的方式,根据这个新的状态来更新UI。 为此,React将构建一个新的 React 元素树(您可以将其视为 UI 的对象表示)。
一旦有了这个树,为了弄清 UI 如何响应新的状态而改变,React 会将这个新树与上一个元素树相比较( diff )。
通过这样做, React 将会知道发生的确切变化,并且通过了解发生什么变化,只需在绝对必要的情况下进行更新即可最小化 UI 的占用空间。
createElement 函数式JSX 编译之后使用的创建
React Element 的函数 , 而cloneElement 则是用于复制某个元素并传入新的Props
redux-logger : 提供日志输出
redux-thunk : 处理异步操作
redux-promise : 处理异步操作,actionCreator的返回值是 promise
1. web 应用是一个状态机, 视图与状态是 -- 对应的
2. 所有的状态,保存在一个对象里面(唯一数据源)
是一个应用数据流框架,集中式管理
**怎么用:**view调用 store 的 dispath 接收 action 传入 store ,reducer 进行 state 操作, view 通过 store 提供的 getState 获取最新的数据
缺点: state必须由父组件传过来,子组件相关数据更新,父组件会强制渲染
1.一个组件所需要的数据,必须由父组件传过来, 而不能像 flux 中直接从 store取
2.当一个组件相关数据更新时,即使父组件不需要用到这个组件,父组件还是会重新 render,
可能会有效率影响,或者需要些复杂的 shouldComponentUpdate 进行判断
唯一数据源:
整个应用的state都被存储到一个状态树里面,并且这个状态树,只存在于唯一的store中
state 保持只读状态:
state是只读的,唯一改变state的方法就是触发action,action是一个用于描述以发生时间的普通对象
数据改变只能通过纯函数来执行:
使用纯函数来执行修改,为了描述action如何改变state的,你需要编写reducers
Redux 由以下组件组成:
**store:用来存储数据**
**reducer:真正的来管理数据**
**actionCreators:创建action,交由reducer处理**
**view: 用来使用数据,在这里,一般用react组件来充当**
1.很多非父子通信需要管理
2.缓存后端数据,减少重复的后端请求,减轻服务器压力,提高用户体验
减少Dom操作 提高组件复用性
安装 : $ cnpm install react-redux -S
核心组件:
**Provider 提供者 属性上通过store将数据派给容器组件**
**connect 用于连接容器组件与UI组件**
`connect() 返回一个函数,函数参数接收UI组件,返回容器组件`
connect(mapStateToProps,mapDispatchToProps)(ui组件)
容器组件内部帮你做了 store.subscribe() 的方法订阅
状态变化 ==> 容器组件监听状态改变了 ==> 通过属性的方式传给UI组件
把`store.getState()`的状态转化为展示组件的`props`使用
虚拟dom相当于在js和真实dom中间加了一个缓存,利用dom diff算法避免了没有必要的dom操作,从而提高性能:
具体实现步骤如下:
用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,插到文档当中
当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,记录两棵树差异
把2所记录的差异应用到步骤1所构建的真正的DOM树上,视图就更新
把树形结构按照层级分解,只比较同级元素。
给列表结构的每个单元添加唯一的key属性,方便比较。
React 只会匹配相同 class 的 component(这里面的class指的是组件的名字)
合并操作,调用 component 的 setState 方法的时候, React 将其标记为 - dirty.到每一个事件循环结束, React 检查所有标记 dirty的 component重新绘制.
选择性子树渲染。开发人员可以重写shouldComponentUpdate提高diff的性能
Flux 的最大特点,就是数据的"单向流动"。
Flux 是一种强制单向数据流的架构模式。它控制派生数据,并使用具有所有数据权限的中心 store 实现多个组件之间的通信。整个应用中的数据更新必须只能在此处进行。 Flux 为应用提供稳定性并减少运行时的错误。
用户访问 View
View发出用户的 Action
Dispatcher 收到Action,要求 Store 进行相应的更新
Store 更新后,发出一个"change"事件
View 收到"change"事件后,更新页面
hooks 他是一组函数api
解决问题: 类组件 (无状态组件)
hooks 让类组件可以拥有 state, 生命周期等特性
先简要概述浏览器渲染的步骤:
1.处理HTML标记并构建DOM树
2.处理CSS标记并构建CSSOM树
3.将DOM与CSSOM合并成一个渲染树
4.根据渲染树来布局,计算每个节点的布局信息
5.将各个节点绘制到屏幕上
响应式设计与自适应设计的区别:
1、文件合并(目的是减少http请求)
2、文件压缩(目的是直接减少文件下载的体积)
3、使用cdn托管资源
4、使用缓存
5、gizp压缩你的js和css文件
6、meta标签优化(title,description,keywords)、heading标签的优化、alt优化
7、反向链接,网站外链接优化
web标准简单来说可以分为结构、表现和行为。其中结构主要是有HTML标签组成。或许通俗点说,在页面body里面我们写入的标签都是为了页面的结构。表现即指css样式表,通过css可以是页面的结构标签更具美感。行为是指页面和用户具有一定的交互,同时页面结构或者表现发生变化,主要是有js组成。
web标准一般是将该三部分独立分开,使其更具有模块化。但一般产生行为时,就会有结构或者表现的变化,也使这三者的界限并不那么清晰。
W3C对web标准提出了规范化的要求,也就是在实际编程中的一些代码规范:
1.对于结构要求:(标签规范可以提高搜索引擎对页面的抓取效率,对SEO很有帮助)
2.对于css和js来说
HTTP协议是一个广泛应用的Internet协议。在其中有8个不同的请求方法:
GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT
GET:向特定的资源发出请求。
POST:向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的创建和/或已有资源的修改。
缓存策略的分类:
对于强缓存,浏览器在第一次请求的时候,会直接下载资源,然后缓存在本地,第二次请求的时候,直接使用缓存。
对于协商缓存,第一次请求缓存且保存缓存标识与时间,重复请求向服务器发送缓存标识和最后缓存时间,服务端进行校验,如果失效则使用缓存
1XX:信息状态码
100 Continue 继续,一般在发送post请求时,已发送了http header之后服务端将返回此信息,
表示确认,之后发送具体参数信息
2XX:成功状态码
200 OK 正常返回信息
201 Created 请求成功并且服务器创建了新的资源
202 Accepted 服务器已接受请求,但尚未处理
3XX:重定向
301 Moved Permanently 请求的网页已永久移动到新位置。
302 Found 临时性重定向。
303 See Other 临时性重定向,且总是使用 GET 请求新的 URI。
304 Not Modified 自从上次请求后,请求的网页未修改过。
4XX:客户端错误
400 Bad Request 服务器无法理解请求的格式,客户端不应当尝试再次使用相同的内容发起请求。
401 Unauthorized 请求未授权。
403 Forbidden 禁止访问。
404 Not Found 找不到如何与 URI 相匹配的资源。
5XX: 服务器错误
500 Internal Server Error 最常见的服务器端错误。
503 Service Unavailable 服务器端暂时无法处理请求(可能是过载或维护)
浏览器根据请求的URL 交给 DNS 域名解析,找到真实IP, 向服务器发起请求;
服务器交给后台处理完成后返回数,浏览器接受文件(HTML.JS,CSS 图像等)
浏览器对加载到的资源(HTML、JS、CSS等)进行语法解析,建立相应的内部数据结构(如HTML的DOM);
载入解析到的资源文件,渲染页面,完成。
-----------------------------------------------
1、浏览器的地址栏输入URL并按下回车。
2、浏览器查找当前URL的DNS缓存记录。
3、DNS解析URL对应的IP。
4、根据IP建立TCP连接(三次握手)。
5、HTTP发起请求。
6、服务器处理请求,浏览器接收HTTP响应。
7、渲染页面,构建DOM树。
8、关闭TCP连接(四次挥手)
为了数据传输的安全, HTTPS 在HTTP 的基础上加入SSL协议,SSL 依靠证书来验证服务器的身份,
并未浏览器和服务器之间的通信加密
http 是超文本传输协议,信息是明文传输,
https 则是具有安全性的 ssl 加密传输协议
http 的连接很简单, 是无状态的;
https 协议是由 SSL+HTTP 协议构建的可进行加密传输,身份认证的网络协议, 比 http 协议安全
就是该内存空间使用了 但是没有回收 所以导致了泄漏
以下会造成内存泄漏:
(1)意外的全局变量引起的内存泄露。
(2)闭包引起的内存泄露。
(3)没有清理的DOM元素引用。
(4)被遗忘的定时器或者回调
(5)子元素存在引起的内存泄露
(1)模拟手机调试
(2)真机调试之android手机+Chrome
(3)真机调试之 iphone+ safari ⑷UC浏览器
(1)微信内置浏览器调试
(2)debuggap
(3)抓包
可能的原因:
(1)后端原因:后端接口,后端服务器
(2)域名、IP和路径问题
(3)网络环境问题
(4)线上库、框架、工具的版本和本地不—致问题
(5)线上和本地数据资源不—致问题
(6)程序bug
1. 前端是最贴近用户的程序员,前端的能力就是能让产品从 90分进化到 100 分,甚至更好
2. 参与项目,快速高质量完成实现效果图,精确到1px;
3. 与团队成员,UI设计,产品经理的沟通;
4. 做好的页面结构,页面重构和用户体验;
5. 处理hack,兼容、写出优美的代码格式;
6. 针对服务器的优化、拥抱最新前端技术。
第一次握手,由浏览器发起,告诉服务器,我要发起请求了,
第二次握手,由服务器发起,告诉浏览器我准备接受了,你发送吧
第三次握手,由浏览器发送,告诉服务器,我马上发送了准备接受吧
第一次挥手, 浏览器发起,发送给服务器 ,我东西发送完了,你准备关闭吧
第二次挥手,服务器发送,告诉浏览器,我东西接收完了(请求报文) 我准备关闭了 你也准备吧
第三个挥手, 服务器发起,告诉浏览器,我东西发送完了,(响应报文) 我准备关闭了 你也准备吧
第四次挥手, 浏览器发起,告诉浏览器,我东西接受完了,我准备关闭,你也准备吧
/* 把上、左、右三条边隐藏掉(颜色设为 transparent) */
#demo {
width: 0;
height: 0;
border-width: 20px;
border-style: solid;
border-color: transparent transparent red transparent;
}
// 给其他三个边框都设为 透明
div {
width: 0 ;
height: 0 ;
border: 100px solid red;
border-right-color: transparent;
border-bottom-color: transparent;
border-left-color: transparent;
}