前端部份学问总结

乱序 不间断更新

绝大多数写的比较浅易 看个乐子

display:none 和visibility:hidden的区分

display:none
完整消逝
将会隐蔽它以及一切的子女元素
占有的空间消逝,阅读器不会剖析该元素
页面发作回流+重绘

visibility:hidden
视觉消逝可以明白为透明度为0
占有的空间仍存在,阅读器仍然会剖析该元素
页面发作重绘
visibility具有继承性,父元素设置visibility:hidden,子元素也会继承该属性,当子元素从新设置visibility:visible,元素又会从新显现,而display:none不会

页面的显现流程&回流&重绘

页面的显现流程

  1. 阅读器将读取的一切html代码剖析,天生一个Dom树 ->dom tree
  2. 阅读器将一切款式剖析成款式构造体 ->style rules
  3. Dom数和款式构造体连系天生构建显现树 render tree ->attachment
  4. 阅读器依据render tree 绘制页面

some tips

  • 在剖析款式构造体的历程当中阅读器会去除不能辨认的款式(IE去掉-moz开首的款式,firefox去除_开首的款式)
  • render tree与dom tree区分很大,render tree可以辨认款式,且不会包含隐蔽的节点(display:none),visibility:hidden仍会包含在render tree内。在render tree中,每一个节点被称为box

回流&重绘

回流:render tree中部份(悉数)元素的范围尺寸规划等转变而须要从新构建页面。
重绘:render tree中一些元素须要更新属性,但这些属性只影响元素的表面、作风而不引发规划的转变

在剖析款式构造体的历程当中阅读器会去除不能辨认的款式
回流势必引发重绘,重绘不肯定引发回流
参考文档:关于显现、回流、重绘

get请乞降post要求

get:经由历程查询字符串的体式格局来举行通报

用于猎取少许信息(单次运输量不大于64k),运用url通报参数->很不平安

post:经由历程表单的体式格局通报

用于修正服务器的资本,无信息量限定,采纳要求体承载的体式格局,不轻易暴露
    

本质上同根同源
get&post 都是http协定中用于发送要求的要领,而http是基于tcp/ip的关于数据如安在万维网通信的协定
怎样明白?
TCP->汽车 HTTP->交通规则 阅读器->运输公司
get->将货色放在车顶上(url) ,只发作一个数据包
post->将货色放在车箱里 , 发作header+body两个数据包

post发作两个数据包,先发送header确认后再发送body,然则并非一切阅读器都在post中发两次包,如firefox就只发一次

域名的构成

http://    www.baidu.com    :8080    /dir/other.html
协定        主机名            端口     文件途径 参数 文件片断



transition和transform

transform
对元素举行挪动、缩放、迁移转变、拉长或拉伸
要领:
translate():元素从当前位置挪动依据给定的top left 坐标挪动

transform:tanslate(50px,30px)    

rotate():元素顺时针扭转给定的角度,负值->逆时针扭转

transform:rotata(20deg)

scale():依据给定的XY轴参数、元素的尺寸会增添或削减(拉伸、压缩)

transform:scale(1.2,0.8)

skew():翻转

transform:skew(20deg, 20deg);
//缭绕 X 轴把元素翻转20度,缭绕 Y 轴翻转20度

transition过渡
元素从一种款式逐步变成另一种款式,属于一种简朴的动画属性
四个属性:
transition-property: 过渡属性的款式(默许值为all)
transition-duration: 过渡持续时刻(默许值为0s)必需值
transiton-timing-function: 过渡函数(默许值为ease函数)
transition-delay: 过渡耽误时刻(默许值为0s)

div{
width:100px;
transition: width 1s;
//时长为一秒的宽度变化效果
}
div:hover{
width:500px;
}

参考:深切明白trasition
参考:transition和transform

假造DOM

为什么用假造dom?
天生页面时,阅读器从构建DOM树最先从到到尾实行一遍流程。比方在一次操纵时,须要更新10个DOM节点,抱负状况是一次性构建完DOM树,再实行后续操纵。然则阅读器并不会这么做,收到第一个更新DOM要求后会立时实行流程,因而须要实行10次。频仍的操纵会引发页面卡顿。实在的DOM节点,哪怕最简朴的一个div也会包含很多属性

假造DOM干什么?
如一次操纵有10个更新DOM的行动,假造DOM不会马上操纵DOM,而是将10次更新的diff内容保存到一个当地的js对象中,最终将js对象一次行attach到DOM树上,防止了大批的无谓盘算量

假造的DOM的中心头脑:对庞杂的文档DOM构造,供应一种轻易的东西,举行最小化地DOM操纵

React的生命周期

《前端部份学问总结》

三个状况:装配 更新 卸载

初始化衬着:
constructor()构造函数

componentWillMount组件将要加载(17版本弃用,在这里要求异步数据,render能够不会衬着到,因为componentWillMount实行后,render立马实行)
全部生命周期只挪用一次(组件更新不再挪用)

render()衬着要领

componentDidMount 组件已加载
全部生命周期只挪用一次(组件更新不再挪用)
↑在这里可以异步要求数据,在这里设置状况会触发从新衬着,然则不引荐运用setstate函数,会触发分外一次衬着,且在阅读器革新屏幕之前实行,会致使机能题目

更新:
共有五个环节(差异的状况有差异的实行步骤)

1.componentWillReceiveProps(nextprops猎取更新状况以及相应的组件状况,组件将要吸收参数

2.shouldComponentUpdate(nextprops,nextstate)依据下一个props和state决议组件是不是应当更新
↑immutable data在此运用immutable是一旦建立,就不能再被变动的数据

3.componentWillUpdate()组件将要更新 做准备事情(定时、收集要求等)
在这里可以变动state 然则不能运用setState函数 会引发函数挪用componentshouldupdate从而进入死轮回
4.render()衬着

getSnapshotBeforeUpdate(nextprops,nextstate)在更新前截图//不会用

5.componentDidUpdate() 组件已更新终了
可以在这里猎取DOM

卸载
只需一个步骤,因为卸载后将落空掌握才
componentWillUnmount()组件将要卸载
在这里消灭一些不须要的监听和计时器

三种情势下的实行步骤:

  1. 父组件动员子组件更新 -> 12345
  2. setState() 跳过componentWillReceiveProps() ->2345
  3. forceUpdate()强迫更新 跳过shouldComponentUpdate()无需判读->345

defaultProps()
设定默许props 在组件没有被传入时见效,防止报错
propTypes 范例搜检

import PropTypes from 'prop-types'.//连系第三方prop-types库
static propTypes = {
    title:PropTypes.string
}

原型&原型链

原型是JavaScript中继承的基本,JavaScript的继承就是基于原型的继承

什么是原型?
我们建立的每一个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,这个对象可以包含由特定范例的一实在例同享的属性和要领。而prototype就是经由历程挪用构造函数建立的对象实例的原型对象

原型所指的就是一个对象,实例继承对象的属性。在原型上定义的属性,经由历程继承,实例也具有了这个属性
实例经由历程_proto_这个属性直接接见到原型

function Person(){
Person.prototype.type   = 'object named Person';
person = new Person();
person._proto_ === Person.prototype;//二者等价

}

构造函数->prototype->接见原型
原型->constructor->接见构造函数

运用原型的长处:
可以让对象的实例同享它所包含的属性和要领,没必要在构造函数中增加定义对象信息,而是可以将这些信息增加到原型中(假如运用构造函数就要让每一个要领都在实例中建立一遍)

《前端部份学问总结》

constructor是原型的一个属性,Constructor是真正的构造函数

什么是原型链?
_proto_是实例指向原型对象的一个指针,是任何对象都有的属性,js万物皆对象,所以就构成了一条由_proto_连起来的链条,递归接见到头,终值为null

在读取一个实例的属性时,假如该属性在当前实例没有找到,那末就会循着_proto_指定的原型继承向上找,假如还找不到,则寻觅原型的原型,假如一向没有找到,则直到搜刮到null为止

原型继承

Son.prototype = new Father();//Son继承了Father,经由历程原型,构成链条

参考文章:原型
参考文章:原型链

函数提拔与变量提拔的优先级

变量提拔
ES6之前没有块级作用域,只需全局作用域和部分作用域,变量提拔就是将变量声明提拔到它地点作用域的最最先的部份

函数提拔
建立函数有两种情势:函数声明和函数字面量,只需函数声明有变量提拔

console.log(a)  // f a() { console.log(a) }
console.log(b) //undefined,不存在函数提拔
    
function a() {
        console.log(a) 
}

var b = function(){
        console.log(b)
}

函数提拔与变量提拔的优先级
函数提拔要比变量提拔的优先级要高一些,且不会被变量声明掩盖,然则会被变量赋值今后掩盖。

console.log(a);    // f a() {console.log(10)}
console.log(a());    //  undefined
var a = 3;

function a() {
        console.log(10) //10
}
console.log(a)   //3
a = 6;
console.log(a());  //a is not a function;

平常的实行递次

 var a = funtion () {
        console.log(10)
    }
    var a;
    console.log(a);    // f a() {console.log(10)}
    console.log(a());  //  undefined

    a = 3;
    console.log(a)   //3
    a = 6;
    console.log(a());   //a() is not a function;

参考文章

JS处置惩罚异步的几种体式格局

  1. 事宜监听
    onclick要领、addEventlistener、attachEvent(不支撑ie,实行递次3-2-1)
  1. setTimeout超时挪用
    setInterval间歇挪用,根据指定的时刻间隔重复实行使命代码
  2. generator 可以屡次返回的“函数”
    每实行一次后就停息,返回的值就是yield的返回值,每次返回一个值,直到done为true,这个generate对象已悉数实行终了
  3. promise
    三种状况:守候(pengding) 胜利(resolved) 失利(rejected)
  4. async/await
    一种特别的语法,可以更温馨地与promise协同事情
    async安排在一个函数前面,使函数老是返回一个promise,纵然个中包含非promise(会自动将返回值包装成promise的resolved值)
    await只能运用在async内,可以使JavaScript守候,直到promise处置惩罚完毕
    1.假如它是一个毛病,异常就发作了,就像在那个处所挪用了throw error一样。
    2.不然,它会返回一个效果,我们可以将它分配给一个值

    参考

  5. 观察者情势
    publish()/subscribe
    又称为宣布、定阅情势
    某个使命实行终了,则向信号中心宣布一个信号,其他使命可以向信号中心定阅该信号,从而晓得什么时刻实行本身的使命
//f2()
 jQuery.subscribe("done", f2);
//f1()
function f1(){

    setTimeout(function () {

      // f1的使命代码

      jQuery.publish("done");

    }, 1000);

  }

//f2实行终了后可以作废定阅
  jQuery.unsubscribe("done", f2);

该要领优于事宜监听,可以经由历程检察音讯中心相识如今有若干信号、定阅者,从而监控顺序的实行状况
参考文档

回调函数的好坏

长处:轻易明白和布置
瑕玷:不利于代码阅读、保护,各个部份耦合性很高,流程杂沓,且每一个使命只能指定一个回调函数

跨域及跨域的体式格局

什么是跨域:
阅读器不能实行其他网站的剧本,由阅读器的同源战略形成,是阅读器对JavaScript施加的平安限定
判读是同域:
雷同域名,端口雷同,协定雷同

Jsonp:
Json with Padding,为相识决跨域要求资本而发作的处理方案,是一种依托开发人员创造出的一种非官方跨域数据交互协定。

Jsonp的发作:
ajax直接要求平常文件存在跨域无权限接见的题目,而web页面挪用js时不受跨域影响,通常带有src属性标签的都具有跨域才->在长途服务器上把数据装进js花样的文件里,可以完成跨域接见
JSON的纯字符数据花样可以简约的形貌庞杂的顺序,JSON还被原生js支撑
所以,web客户端挪用跨域服务器天生的js文件(JSON),便获得了本身想要的数据

Jsonp道理
运用script标签没有跨域限定的“破绽”到达和第三方通信的目的
首先在客户端注册一个回调函数,然后把回调函数的名字传给服务器,这时刻服务器天生json数据,以JavaScript的体式格局天生function,将jasonp以入参的体式格局放到function里,天生JavaScript文档,返回给客户端,阅读器剖析这个script,实行JavaScript文档,此时数据作为参数传入了客户端之前定义的回调函数里。

jsonp是要求今后背景包装好一段json,而且把数据放在一个callback函数,返回一个js文件,动态引入这个文件,下载完成js今后,会去挪用这个callback,经由历程如许接见数据
json 是一种数据花样,jsonp 是一种数据挪用的体式格局,带callback的json就是jsonp

跨域的几种要领

  1. Jsonp
    长处:不受同源战略限定,兼容性好,低版本的阅读器也可以运转,在要求终了后可以经由历程挪用callback的体式格局回传效果。
    瑕玷:只支撑get要求不支撑post要求,只支撑跨域HTTP要求这类状况,不能处理差异域的两个页面之间怎样举行JavaScript挪用的题目。
  2. document.domain跨域
    前提条件:
    这两个域名必需属于统一个基本域名!而且所用的协定,端口都要一致,不然没法运用document.domain举行跨域.
    要领:
    须要在a.html里与b.html里都到场:document.domain = “xxx.com”;
  3. HTML5的postMessage要领跨域
    高等阅读器Internet Explorer 8+, chrome,Firefox , Opera 和 Safari 都将支撑这个功用。这个功用重要包含接收信息的”message”事宜和发送音讯的”postMessage”要领。
    比方damonare.cn域的A页面经由历程iframe嵌入了一个google.com域的B页面,可以经由历程以下要领完成A和B的通信
  4. CORS跨域
    基本头脑就是运用自定义的HTTP头部让阅读器与服务器举行沟通,从而决议要求或相应是应当胜利照样失利。
    全部CORS通信历程,都是阅读器自动完成,不须要用户介入。
    关于开发者来讲,CORS通信与同源的AJAX通信没有差异,代码完整一样。阅读器一旦发明AJAX要求跨源,就会自动增加一些附加的头信息,偶然还会多出一次附加的要求,但用户不会有觉得。
    更适用于当代阅读器

参考文档

函数柯里化

把可以接收多个参数的函数变换成接收一个单一参数的函数,而且返回接收余下参数而且返回效果的函数手艺

柯里化是指如许一个函数(假定叫做createCurry),他吸收函数A作为参数,运转后可以返回一个新的函数。而且这个新的函数可以处置惩罚函数A的盈余参数。

函数柯里化(function currying)又称部份求值。一个currying的函数首先会接收一些参数,接收了这些参数后,该函数并不会马上求值,而是继承返回别的一个函数,适才传入的参数在函数构成的闭包里被保存起来。待到函数真正须要求值的时刻,之前传入的参数都邑被一次性用于求值。

Q:函数经由createCurry转化为一个柯里化函数,末了实行的效果,不是恰好相当于实行函数本身吗?柯里化是不是是把简朴的题目庞杂化了?

长处:
1.参数复用
2.提早返回
3.延时实行

参考文档
参考文档,高阶

模块化、CommonJs

对模块化的明白
功用封装,针对Javascript代码,断绝、构造复制的javascript代码,将它封装成一个个具有特定功用的的模块。
模块可以经由历程通报参数的差异修正这个功用的的相干设置,每一个模块都是一个零丁的作用域,依据须要挪用。
模块化就是为了削减体系耦合度,进步内聚性,削减资本轮回依靠,加强体系框架设想。
CommonJs
它的终极目的是供应一个相似Python,Ruby和Java范例库。如许的话,开发者可以运用CommonJS API编写运用顺序,然后这些运用可以运转在差异的JavaScript诠释器和差异的主机环境中。
CommonJs的特性:

  1. 一切代码都运转在模块作用域,不会污染全局作用域。
  2. 模块可以屡次加载,然则只会在第一次加载时运转一次,然后运转效果就被缓存了,今后再加载,就直接读取缓存效果。要想让模块再次运转,必需消灭缓存。
  3. 模块加载的递次,根据其在代码中涌现的递次。

AMD范例和commonJS范例
1.雷同点:都是为了模块化。
2.差异点:AMD范例则是非同步加载模块,许可指定回调函数。CommonJS范例加载模块是同步的,也就是说,只需加载完成,才实行背面的操纵。
参考文档

情形题,加载图片

  • 懒加载

    运用jQuery完成图片懒加载的道理。它的基本头脑是:在输出HTML的时刻,不要直接输出<img src=”xxx”,而是输出以下的img标签:

<img src="/static/loading.gif" data-src="http://真正的图片地点/xxx.jpg">
监听scroll事宜,挪用目的元素(绿色方块)的getBoundingClientRect()要领,获得它对应于视口左上角的坐标,再推断是不是在视口以内。这类要领的瑕玷是,因为scroll事宜麋集发作,盘算量很大,轻易形成机能题目。

参考:JQuery完成

运用IntersectionObserve(callback,option) api监听图片素到视口的间隔推断是不是加载图片,完成懒加载
callback平常会触发两次。一次是目的元素方才进入视口(最先可见),另一次是完整脱离视口(最先不可见)。
参考

有些事宜(resize Mousemove scroll)几乎是不间断触发的,假如存在庞杂的函数要领,异常影响机能,所以须要函数撙节

  • 函数撙节

    函数撙节的基本头脑是设置一个定时器,在指定时刻间隔内运转代码时消灭上一次的定时器,并设置另一个定时器,直到函数要求住手并凌驾时刻间隔才会实行。
    一个函数实行一次后,只需大于设定的实行周期后才会实行第二次

  • 防抖
    函数挪用n秒后才会实行,假如函数在n秒内被挪用的话则函数不实行,从新盘算实行时刻

函数的撙节和函数的去抖都是经由历程削减现实逻辑处置惩罚历程的实行来进步事宜处置惩罚函数运转机能的手腕,并没有实质上削减事宜的触发次数。

撙节和防抖的区分
函数撙节是指肯定时刻内js要领只跑一次。
比方人的眨眼睛,就是肯定时刻内眨一次。这是函数撙节最抽象的诠释。
函数防抖是指频仍触发的状况下,只需充足的余暇时刻,才实行代码一次。
比方生涯中的坐公交,就是肯定时刻内,假如有人连续刷卡上车,司机就不会开车。只需他人没刷卡了,司机才开车。

代码完成
撙节
声明一个变量为标志位,当这个变量为true的时刻,代表如今的转动处置惩罚事宜是余暇的,可以运用。直接return并将变量设为false如许,其他要求实行转动事宜的要领,就被挡回去了。然后用settimeout划定时刻间隔,再实行定时函数内的代码,实行终了将变量从新设为true
防抖
也须要一个settimeout辅佐,耽误实行须要跑的代码
假如要领屡次触发,则把上次纪录的耽误实行代码用clearTimeout清掉,从新最先。
假如计时终了,没有要领进来接见触发,则实行代码。
 函数防抖的完成重点,就是巧用setTimeout做缓存池,而且可以轻易地消灭待实行的代码。clearTimeout(timer)
参考

react父组件更新,子组件更新题目

只需父组件的render了,那末默许状况下就会触发子组件的render历程,子组件的render历程又会触发它的子组件的render历程,一向到React元素(即jsx中的<div>如许的元素)。当render历程到了恭弘=叶 恭弘子节点,即React元素的时刻,diff历程便最先了,这时刻候diff算法会决议是不是实在更新DOM元素。
React不能检测到你是不是给子组件传了属性,所以它必需举行这个重衬着历程(术语叫做reconciliation)
链接形貌

let&const

let、const、var的区分
var:可以跨块级作用域接见,不能跨函数作用域接见
let:只能在块级作用域接见,不能跨函数运用
const:定义常量,必需初始化且不能修正,只能在块级作用域内运用
关于变量提拔:var不管声明在那边都邑莫默许提拔到函数/全局最顶部,然则let和const不会举行变量提拔

promise.all()和promise.race() 的区分

《前端部份学问总结》

async await完成sleep

function sleep(ms){
  return new Promise((resolve)=>setTimeout(resolve,ms));
}
async function test(){
  var temple=await sleep(1000);
  console.log(1111)
  return temple
}
test();
//耽误1000ms输出了1111

async/await相干于promise的上风

  1. 代码越发简约,可以更好的处置惩罚then链
    没必要编写.then,没必要建立一个匿名函数来处置惩罚相应,不势必定名数据通报给我们不须要运用的变量。我们也防止了嵌套代码。
  2. 更好的处置惩罚中心值
    比方说time1 time2 time3 ,promise通报参数很贫苦,而用async/await就不须要过剩的中心值
  3. 更易于调试

promise因为没有代码块,所以不能在一个返回的箭头函数中设置断点。假如你在一个 .then 代码块中运用调试器的步进(step-over)功用,调试器并不会进入后续的 .then 代码块,因为调试器只能跟踪同步代码的每一步。
运用 async/await,你就没必要再运用箭头函数。你可以对 await 语句实行步进操纵

参考

diff算法

传统算法就是对每一个节点逐一对照,轮回遍历一切的子节点,然后推断子节点的更新状况,分别为remove、add、change。假如before的子节点仍有子节点照旧依次实行。

《前端部份学问总结》

《前端部份学问总结》

参考
参考

flex弹性规划

重要头脑是赋予容器掌握内部元素高度和宽度的才

《前端部份学问总结》

主轴main axis 纵轴 cross axis
1点:

        display: flex;
        justify-content: center;
        align-items:center;

2点:竖列规划且在主轴方向采纳justify-content的两头对齐规划,如许两个圆点会在左侧显现,然后采纳align-items让其居中

        display: flex;
        flex-direction: column;//垂直显现
        justify-content: space-between;
        align-items:center;

3点:用到align-self属性让第二个和第三个圆点有本身的属性设置,分别在纵轴方向上居中和低端对齐

    .item:nth-child(2){
        align-self:center;
    }
    .item:nth-child(3){
        align-self:flex-end;
    }

五点规划
思绪:先竖着放两行圆点,每行圆点里横着放两个圆点,所以最外层父元素设置align,内里的父元素设置justify-content构成4点
让圆点(即子元素)在横轴上居中在竖轴上居中,分别用justify-content和align-items构成1点

        display: flex;
        flex-wrap:wrap;//必要时拆行显现
        align-content:space-between;//各行在弹性盒容器中平均散布
    .column{
        flex-basis:100%;
        display:flex;
        justify-content: space-between;
    }

6点:
跟四点的一样,先竖放三行在每行横放两个圆点

完成骰子规划

雪碧图

一个网页能够有很多的小图标,接见时会发送许屡次的要求,形成资本糟蹋、接见速率变慢。可以运用一张图片来替代小图标,按肯定的间隔排开
前提条件
须要一个宽和高设置好的容器
须要设置background-position的值(默许为(0,0),也就是图片的左上角),即挪动图片到本身想要的图标位置。

用css Gaga 自动天生雪碧图

css代码为:background-position:-xpx -ypx;

前端攻防

1.XSS进击:
跨站剧本进击指的是歹意进击者往Web页面里插进去歹意html代码,当用户阅读该页之时,嵌入的歹意html代码会被实行,对受益用户能够采用Cookie材料盗取、会话挟制、垂纶诳骗等种种进击。
防备要领:

  • 设想xss Filter,剖析用户提交的输入,并消弭潜伏的跨站剧本进击、歹意的HTML等。在须要html输入的处所对html标签及一些特别字符( ”
    < > & 等等 )做过滤,将其转化为不被阅读器诠释实行的字符。
  • 前端防备组件:js-xss

2.CSRF跨站点捏造要求
进击者经由历程种种要领捏造一个要求,模拟用户提交表单的行动,从而到达修正用户的数据,或许实行特定使命的目的。
处理要领:

  • 采纳POST要求,增添进击的难度.用户点击一个链接就可以提议GET范例的要求。而POST要求相对照较难,进击者每每须要借助javascript才完成。
  • 对要求举行认证,确保该要求确实是用户本人填写表单并提交的,而不是局外人捏造的.详细可以在会话中增添token,确保看到信息和提交信息的是统一个人。(验证码)

3.Http Heads进击
HTTP协定在Response header和content之间,有一个空行,即两组CRLF(0x0D 0A)字符。这个空行标志着headers的完毕和content的最先。“智慧”的进击者可以运用这一点。只需进击者有方法将恣意字符“注入”到headers中,这类进击就可以发作。

处理方法:
服务器平常会限定request headers的大小。比方Apache server默许限定request header为8K。假如凌驾8K,Aapche Server将会返回400 Bad Request相应。
关于大多数状况,8K是充足大的。假定运用顺序把用户输入的某内容保存在cookie中,就有能够凌驾8K.进击者把凌驾8k的header链接发给受益者,就会被服务器谢绝接见.处理方法就是搜检cookie的大小,限定新cookie的总大写,削减因header过大而发作的谢绝接见进击
参考

闭包
垂直居中完成

redux道理

Javascript全局函数

《前端部份学问总结》

JS的内置对象

《前端部份学问总结》

    原文作者:李默
    原文地址: https://segmentfault.com/a/1190000018944902
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞