廢話少說(shuō),本文分四個(gè)部分,css、js、知識(shí)點(diǎn)一、知識(shí)點(diǎn)二、React(部分問(wèn)題沒(méi)有給出答案,后續(xù)更新)
css面試問(wèn)題
一、垂直居中問(wèn)題
https://www.cnblogs.com/clj2017/p/9293363.html
1、設(shè)置行高
2、彈性布局(父元素設(shè)置display:flex;子元素設(shè)置align-slef:center)
3、偽元素
父元素設(shè)置:before
content:“”;
display:inline-block;
vertical-align:middle;
height:100%;
4:父元素設(shè)置display:table
子元素設(shè)置display:table-cell;
vertical-align:middle;
二、彈性布局
http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html
容器屬性、項(xiàng)目屬性
1、容器屬性
flex-direction:row | row-reverse | column? | column-reverse
決定項(xiàng)目的排列順序
flex-wrap:wrap | nowrap | wrap-reverse
是否換行
flex-flow:<flex-direction> | <flex-wrap>
flex-direction和flex-wrap簡(jiǎn)寫(xiě)形式
justify-content:flex-start | flex-end | center | space-between | space-around
項(xiàng)目在主軸上的對(duì)齊方式
align-items:flex-start | flex-end | center | baseline | stretch
項(xiàng)目在交叉軸的對(duì)齊方式
align-content:flex-start | flex-end | center | stretch | space-between | space-around
定義了多跟軸線的對(duì)齊方式 ,如果項(xiàng)目只有一根軸線,該屬性不起作用。
2、項(xiàng)目屬性
order
定義項(xiàng)目的排列順序,值越小排列越靠前,默認(rèn)為0.
flex-grow
定義項(xiàng)目的放大比例,默認(rèn)為0,即如果存在剩余空間也不放大
如果所有項(xiàng)目的flex-grow都為1,等分剩余空間。如果一個(gè)項(xiàng)目的flex-grow為2,其他項(xiàng)目的flex-grow都為1,前者占用的剩余空間將比其他項(xiàng)多一倍。
flex-shrink
定義項(xiàng)目的縮小比例,默認(rèn)為1,即如果空間不足,該項(xiàng)目將縮小
flex-basis
分配多余空間之前項(xiàng)目占據(jù)的主軸空間
flex
flex-grow | flex-shrink | flex-basis的簡(jiǎn)寫(xiě)。
align-self:auto | flex-start | flex-end | center | baseline | stretch
單個(gè)項(xiàng)目在交叉的對(duì)齊方式,可與其他項(xiàng)目不一樣
三、BFC
https://blog.csdn.net/sinat_36422236/article/details/88763187
1、定義:塊級(jí)格式化上下文
2、觸發(fā)BFC的條件
⑴浮動(dòng)
⑵position:absolute fixed
⑶display:inline-block | table-cell | flex |
⑷overflow:hidden | scroll | auto
3、BFC解決的問(wèn)題
(1)避免margin重疊
(2)解決浮動(dòng)重疊
(3)解決高度塌陷問(wèn)題
四、清除浮動(dòng)的方式
清除浮動(dòng)主要是為了解決父級(jí)元素因?yàn)樽蛹?jí)浮動(dòng)引起的內(nèi)部高度為0的問(wèn)題。
1、額外標(biāo)簽
在父元素下寫(xiě)一個(gè)標(biāo)簽:用clear:both
2、overflow:hidden;觸發(fā)bfc
3、偽元素:after{clear:both;content:"";display:block;}
js
一、解決浮點(diǎn)數(shù)計(jì)算問(wèn)題
const floatAdd = (arg1, arg2) => {
? var r1, r2, m;
? r1 = arg1.toString().split(".")[1].length;
? r2 = arg2.toString().split(".")[1].length;
? m = Math.pow(10, Math.max(r1, r2));
? var rs = (arg1 * m + arg2 * m) / m;
? console.log(rs);
? return rs;
};
二、數(shù)組扁平化
1、遞歸
2、轉(zhuǎn)化為字符串
var rs = [1, 2, 3, [4, 5, [8, 78], 6]]
? .toString()
? .split(",")
? .map(item => {
? ? return Number(item);
? });
console.log(rs);
三、兩個(gè)數(shù)組求交集
function intersection(arr1,arr2){
return arr1.filter(item=>{
if(arr2.indexOf(item)>-1){
return item
}
})
}
四、數(shù)組去重
var arr2 = [2, 1, 3, 1];
var arr3 = [];
arr2.map(item => {
? if (arr3.indexOf(item) == -1) {
? ? arr3.push(item);
? }
});
console.log(arr3);
五、深拷貝和淺拷貝
淺拷貝方法
1、展開(kāi)運(yùn)算符 ...
2、Object.assign({},對(duì)象)
深拷貝方法
1、JSON.parse(JSON.stringify(對(duì)象))
該方法有局限性
會(huì)忽略u(píng)ndefined
會(huì)忽略symbol
不能序列化函數(shù)
不能解決循環(huán)引用的對(duì)象
2、遞歸
function deepClone(obj) {
? //判斷是否為引用類型
? function isobj(o) {
? ? return (typeof o == "object" || typeof o == "function") && o !== null;
? }
? if (!isobj(obj)) {
? ? throw new Error("非對(duì)象");
? }
? //判斷是否為數(shù)組,是的話解構(gòu)數(shù)組否則結(jié)構(gòu)對(duì)象
? let isArray = Array.isArray(obj);
? let newobj = isArray ? [...obj] : { ...obj };
? Object.keys(newobj).forEach(item => {
? ? newobj[item] = isobj(newobj[item]) ? deepClone(newobj[item]) : newobj[item];
? });
? return newobj;
}
六、繼承
1、原型繼承(通過(guò)prototype)
function Parent(name, age) {
? this.name = "小頭爸爸";
? this.age = 40;
}
function Child() {}
Child.prototype = new Parent();
var child = new Child();
console.log(child.name);
2、構(gòu)造函數(shù)繼承()
function Parent(name) {
? this.name = name;
? this.age = 40;
}
function Child(name) {
? Parent.call(this, name);
}
var child = new Child("大頭兒子");
console.log(child.name);
console.log(child.age);
3、組合繼承
function Box(age) {
this.name = ['Lee', 'Jack', 'Hello']
this.age = age;
}
Box.prototype.run = function () {
return this.name + this.age;
};
function Desk(age) {
Box.call(this, age); //對(duì)象冒充
}
Desk.prototype = new Box(); //原型鏈繼承
var desk = new Desk(100);
alert(desk.run());
4、class繼承
class Parent {
? constructor(value) {
? ? this.value = value;
? }
? getvalue() {
? ? console.log(this.value);
? }
}
class Child extends Parent {
? constructor(value) {
? ? super(value);
? ? this.value = value;
? }
}
let child = new Child(1);
child.getvalue();
組合繼承優(yōu)點(diǎn)是可以用構(gòu)造函數(shù)傳參,可以復(fù)用父類的函數(shù),不會(huì)與父類引用屬性共享,
缺點(diǎn)是子類原型上多了不需要的父類屬性
七、手寫(xiě)call、apply、bind
//手寫(xiě)call、apply、bind
//?Function.prototype.mycall?=?function(context)?{
//???if?(typeof?this?!==?"function")?{
//?????throw?new?TypeError("Error");
//???}
//???context?=?context?||?window;
//???context.fn?=?this;
//???let?args?=?[...arguments].slice(1);
//???let?result?=?context.fn(...args);
//???delete?context.fn;
//???return?result;
//?};
//?function?demo(num1,?num2)?{
//???let?rs?=?num1?+?num2;
//???console.log(rs);
//???return?rs;
//?}
//?demo.mycall(this,?1,?2);
//手寫(xiě)apply
//?Function.prototype.myapply?=?function(context)?{
//???if?(typeof?this?!==?"function")?{
//?????throw?new?Error("Error");
//???}
//???context?=?context?||?window;
//???context.fn?=?this;
//???let?result;
//???if?(arguments[1])?{
//?????result?=?context.fn(...arguments[1]);
//???}?else?{
//?????result?=?context.fn();
//???}
//???delete?context.fn;
//???return?result;
//?};
//?function?demo(num1,?num2)?{
//???let?rs?=?num1?+?num2;
//???console.log(rs);
//???return?rs;
//?}
//?demo.myapply(this,?[1,?2]);
//手寫(xiě)bind
Function.prototype.mybind?=?function(context)?{
??if?(typeof?this?!==?"function")?{
????throw?new?Error("Error");
??}
??console.log(arguments?instanceof?Object);
??let?args?=?[...arguments].slice(1);
??let?self?=?this;
??return?function?F()?{
????if?(this?instanceof?F)?{
??????return?new?self(...args,?...arguments);
????}?else?{
??????return?self.apply(context,?args.concat(...arguments));
????}
??};
};
function?demo(num1,?num2)?{
??let?rs?=?num1?+?num2;
??console.log(rs);
??return?rs;
}
demo.mybind(this,?1)(3,?6);
八、一個(gè)按鈕掛載兩個(gè)onclick事件
1、寫(xiě)兩個(gè).addEventListener(click,fn1 )
addEventListener(click,fn2)
2、寫(xiě)onclick=“fn1();n2()”
知識(shí)點(diǎn)1
一、http緩存
二、git常用命令
三、axios? 攔截器作用 底層原理
axios是什么
axios是基于promise機(jī)制實(shí)現(xiàn)的異步鏈?zhǔn)秸?qǐng)求框架,體積小。
底層原理:promise+ajax
基本api
axios.get()get請(qǐng)求 獲取數(shù)據(jù)
axios.post()post請(qǐng)求 提交數(shù)據(jù)
axios.put()put請(qǐng)求 更新數(shù)據(jù)
axios.delete() 刪除數(shù)據(jù)
用法
對(duì)象使用:axios.get('url',params).then(response=>{
console.log(response)
})
函數(shù)使用:axios({
url:"url",
method:"method",
headers:?{'X-Requested-With':?'XMLHttpRequest'},
}).then((res)=>{console.log(err)}).catch((err)=>{console.log(err)})
axios.defaults.baseURL?=?'https://api.example.com';(設(shè)置基礎(chǔ)路徑)
axios.interceptors.request.use()請(qǐng)求攔截器
axios.interceptors.response.use()響應(yīng)攔截器
用法:
axios.interceptors.request.use((config)=>{
return config
},(error)=>{
return promise.reject(error)
})//兩種攔截器用法一樣。
token怎么從后端獲取
四、優(yōu)化
1、圖片優(yōu)化
⑴很多裝飾類的用css去完成。
⑵雪碧圖
⑶小圖使用base64格式
⑷選擇正確的格式
能使用webp就使用webp(webp兼容性不好,很多瀏覽器不支持)
小圖使用PNG,大部分圖標(biāo)可以用SVG代替
照片使用JPEG
2、DNS預(yù)解析
DNS解析也是需要時(shí)間的,可以通過(guò)預(yù)解析的方式來(lái)預(yù)先獲得域名
<link rel="dns-prefetch" href="http://域名">
3、節(jié)流
如果滾動(dòng)事件會(huì)發(fā)起網(wǎng)絡(luò)請(qǐng)求,我們不希望用戶在滾動(dòng)中一直發(fā)送網(wǎng)絡(luò)請(qǐng)求,而是而一段時(shí)間發(fā)送一次,對(duì)于這種情況我們可以使用節(jié)流
實(shí)現(xiàn)的主要思路:就是將當(dāng)前時(shí)間和上一次執(zhí)行時(shí)間作對(duì)比,如果差值大于設(shè)置的等待時(shí)間就執(zhí)行函數(shù)。
4、防抖
點(diǎn)擊按鈕會(huì)觸發(fā)網(wǎng)絡(luò)請(qǐng)求,我們不希望每次點(diǎn)擊都會(huì)觸發(fā)網(wǎng)絡(luò)請(qǐng)求,而是用戶點(diǎn)擊按鈕一段時(shí)間后沒(méi)有再次點(diǎn)擊的情況才去發(fā)起網(wǎng)絡(luò)請(qǐng)求,對(duì)于這種情況我們可以使用防抖。
// func是用戶傳入需要防抖的函數(shù)// wait是等待時(shí)間const debounce = (func, wait = 50) => {
? // 緩存一個(gè)定時(shí)器id? let timer = 0? // 這里返回的函數(shù)是每次用戶實(shí)際調(diào)用的防抖函數(shù)? // 如果已經(jīng)設(shè)定過(guò)定時(shí)器了就清空上一次的定時(shí)器? // 開(kāi)始一個(gè)新的定時(shí)器,延遲執(zhí)行用戶傳入的方法? return function(...args) {
? ? if (timer) clearTimeout(timer)
? ? timer = setTimeout(() => {
? ? ? func.apply(this, args)
? ? }, wait)
? }
}
5、預(yù)加載
有些資源不需要馬上用到,但是需要盡早獲取,這時(shí)候可以用到預(yù)加載
預(yù)加載其實(shí)是聲明式的fetch,強(qiáng)制瀏覽器請(qǐng)求資源,并且不會(huì)阻塞onload事件,可以使用以下代碼實(shí)現(xiàn)預(yù)加載
<link rel="preload" href="資源">
優(yōu)點(diǎn):降低首屏加載時(shí)間,缺點(diǎn)是兼容性不好
6、預(yù)渲染
可以通過(guò)預(yù)渲染將下載的文件在后臺(tái)渲染
實(shí)現(xiàn):<link rel="prerender" href="資源">
預(yù)渲染雖然可以提高頁(yè)面的加載速度,但是要確保該頁(yè)面大概率會(huì)被用戶在之后打開(kāi),否則就是白白浪費(fèi)資源去渲染。
7、懶執(zhí)行
將某些邏輯使用時(shí)在計(jì)算。該技術(shù)可以用于首屏優(yōu)化,一般可以通過(guò)定時(shí)器或者事件調(diào)用來(lái)喚醒
8、懶加載
將不關(guān)鍵的資源延后加載
原理是只加載可視區(qū)域
五、當(dāng)瀏覽器輸入url之后
https://www.cnblogs.com/confach/p/10050013.html
DNS查詢
TCP連接
發(fā)送HTTP請(qǐng)求
Server處理HTTP請(qǐng)求并返回HTTP報(bào)文
瀏覽器解析并render頁(yè)面
HTTP連接斷開(kāi)
六、forEach和map的區(qū)別
1、返回值不一樣,forEach返回值是undefined,map返回值是一個(gè)新的數(shù)組
2、forEach不可中斷,除非拋出異常。
七、this指向問(wèn)題
1、定時(shí)器的this指向問(wèn)題
setTimeout(function(){
console.log(this.name)
},1000)
一般情況下如果在定時(shí)器內(nèi)部使用普通函數(shù),this指向window
改變this指向的方法
⑴that綁定this
⑵使用bind,bind方法返回一個(gè)新函數(shù),call和apply立即執(zhí)行函數(shù),所以只能使用bind方法,否則就失去了定時(shí)器的作用
⑶使用箭頭函數(shù),箭頭函數(shù)沒(méi)有this指向,它的this是繼承外部的作用域。
2、如果直接調(diào)用函數(shù),函數(shù)不管放在哪個(gè)地方,this指向都是window
3、如果對(duì)象調(diào)用函數(shù),this指向被調(diào)用的對(duì)象
4、對(duì)于new的方式,this永遠(yuǎn)綁定在實(shí)例化對(duì)象上,不可改變。
5、箭頭函數(shù)沒(méi)有this指向,它的this是繼承外部的作用域。
八、webpack相關(guān)內(nèi)容
webpack相關(guān)內(nèi)容https://www.runoob.com/w3cnote/es6-setup.html
webpack功能:
1將sass/less 等預(yù)編譯的css語(yǔ)言轉(zhuǎn)換成瀏覽器識(shí)別的css文件
2能夠?qū)⒍鄠€(gè)預(yù)編譯文件打包成一個(gè)文件
3 打包image/styles/assets/scrips/等前端常用的文件
4 搭建開(kāi)發(fā)環(huán)境開(kāi)啟服務(wù)器
5 監(jiān)視文件改動(dòng),熱部署。
webpack構(gòu)建過(guò)程
從entry里配置的module開(kāi)始遞歸解析entry依賴的所有module
每找到一個(gè)module,就會(huì)根據(jù)配置的loader去找對(duì)應(yīng)的轉(zhuǎn)換規(guī)則
對(duì)module進(jìn)行轉(zhuǎn)換后,再解析出當(dāng)前module依賴的module
這些模塊會(huì)以entry為單位分組,一個(gè)entry和其所有依賴的module被分到一個(gè)組Chunk
最后webpack會(huì)把所有Chunk轉(zhuǎn)換成文件輸出
在整個(gè)流程中webpack會(huì)在恰當(dāng)?shù)臅r(shí)機(jī)執(zhí)行plugin里定義的邏輯
webpack打包原理
將所有依賴打包成一個(gè)bundle.js,通過(guò)代碼分割成單元片段按需加載
什么是entry,output?
entry 入口,告訴webpack要使用哪個(gè)模塊作為構(gòu)建項(xiàng)目的起點(diǎn),默認(rèn)為./src/index.js
output 出口,告訴webpack在哪里輸出它打包好的代碼以及如何命名,默認(rèn)為./dist
什么是loader,plugins?
loader是用來(lái)告訴webpack如何轉(zhuǎn)換某一類型的文件,并且引入到打包出的文件中。
plugins(插件)作用更大,可以打包優(yōu)化,資源管理和注入環(huán)境變量
什么是bundle,chunk,module?
bundle是webpack打包出來(lái)的文件,chunk是webpack在進(jìn)行模塊的依賴分析的時(shí)候,代碼分割出來(lái)的代碼塊。module是開(kāi)發(fā)中的單個(gè)模塊
如何利用webpack來(lái)優(yōu)化前端性能
1. 壓縮代碼。uglifyJsPlugin 壓縮js代碼, mini-css-extract-plugin 壓縮css代碼
2. 利用CDN加速,將引用的靜態(tài)資源修改為CDN上對(duì)應(yīng)的路徑,可以利用webpack對(duì)于output參數(shù)和loader的publicpath參數(shù)來(lái)修改資源路徑
3. 刪除死代碼(tree shaking),css需要使用Purify-CSS
4. 提取公共代碼。webpack4移除了CommonsChunkPlugin (提取公共代碼),用optimization.splitChunks和optimization.runtimeChunk來(lái)代替
補(bǔ)充CDN
CDN(Content Delivery Network)是指內(nèi)容分發(fā)網(wǎng)絡(luò),也稱為內(nèi)容傳送網(wǎng)絡(luò),在現(xiàn)有互聯(lián)網(wǎng)基礎(chǔ)上建立一個(gè)內(nèi)容分發(fā)平臺(tái)專門(mén)為網(wǎng)站提供服務(wù),是為加快網(wǎng)絡(luò)訪問(wèn)速度而被優(yōu)化的網(wǎng)絡(luò)覆蓋層,
原理
CDN的基本原理是廣泛采用各種緩存服務(wù)器,將這些緩存服務(wù)器分布到用戶訪問(wèn)相對(duì)集中的地區(qū)或網(wǎng)絡(luò)中,在用戶訪問(wèn)網(wǎng)站時(shí),利用全局負(fù)載技術(shù)將用戶的訪問(wèn)指向距離最近的工作正常的緩存服務(wù)器上,由緩存服務(wù)器直接響應(yīng)用戶請(qǐng)求
知識(shí)點(diǎn)2
一、websocket介紹:https://www.liaoxuefeng.com/wiki/1022910821149312/1103303693824096
websocket簡(jiǎn)單介紹
http://www.itdecent.cn/p/970dcfd174dc
二、koa
Koa 是一個(gè)新的 web 框架,由 Express 幕后的原班人馬打造, 致力于成為 web 應(yīng)用和 API 開(kāi)發(fā)領(lǐng)域中的一個(gè)更小、更富有表現(xiàn)力、更健壯的基石。 通過(guò)利用 async 函數(shù),Koa 幫你丟棄回調(diào)函數(shù),并有力地增強(qiáng)錯(cuò)誤處理。 Koa 并沒(méi)有捆綁任何中間件, 而是提供了一套優(yōu)雅的方法,幫助您快速而愉快地編寫(xiě)服務(wù)端應(yīng)用程序。
三、express
基于nodejs的web開(kāi)發(fā)框架
四、nginx
Nginx?(engine x) 是一個(gè)高性能的HTTP和反向代理web服務(wù)器,特點(diǎn)是占有內(nèi)存少,并發(fā)能力強(qiáng),事實(shí)上nginx的并發(fā)能力在同類型的網(wǎng)頁(yè)服務(wù)器中表現(xiàn)較好,中國(guó)大陸使用nginx網(wǎng)站用戶有:百度、京東、新浪、網(wǎng)易、騰訊、淘寶等。
功能:
Nginx是一個(gè)HTTP服務(wù)器,可以將服務(wù)器上的靜態(tài)文件(如HTML、圖片)通過(guò)HTTP協(xié)議展現(xiàn)給客戶端
可以實(shí)現(xiàn)負(fù)載均衡、虛擬主機(jī)
什么是負(fù)載均衡
當(dāng)網(wǎng)站訪問(wèn)量非常大,網(wǎng)站站長(zhǎng)開(kāi)心賺錢(qián)的同時(shí),也攤上事兒了。因?yàn)榫W(wǎng)站越來(lái)越慢,一臺(tái)服務(wù)器已經(jīng)不夠用了。于是將同一個(gè)應(yīng)用部署在多臺(tái)服務(wù)器上,將大量用戶的請(qǐng)求分配給多臺(tái)機(jī)器處理。同時(shí)帶來(lái)的好處是,其中一臺(tái)服務(wù)器萬(wàn)一掛了,只要還有其他服務(wù)器正常運(yùn)行,就不會(huì)影響用戶使用。
Nginx可以通過(guò)反向代理來(lái)實(shí)現(xiàn)負(fù)載均衡。
虛擬主機(jī)
有的網(wǎng)站訪問(wèn)量大,需要負(fù)載均衡。然而并不是所有網(wǎng)站都如此出色,有的網(wǎng)站,由于訪問(wèn)量太小,需要節(jié)省成本,將多個(gè)網(wǎng)站部署在同一臺(tái)服務(wù)器上。
例如將www.aaa.com和www.bbb.com兩個(gè)網(wǎng)站部署在同一臺(tái)服務(wù)器上,兩個(gè)域名解析到同一個(gè)IP地址,但是用戶通過(guò)兩個(gè)域名卻可以打開(kāi)兩個(gè)完全不同的網(wǎng)站,互相不影響,就像訪問(wèn)兩個(gè)服務(wù)器一樣,所以叫兩個(gè)虛擬主機(jī)。
五、nodejs
Node.js 是一個(gè)基于 Chrome V8 引擎的?JavaScript?運(yùn)行環(huán)境。 Node.js 使用了一個(gè)事件驅(qū)動(dòng)、非阻塞式 I/O 的模型。?[1]?
Node 是一個(gè)讓 JavaScript 運(yùn)行在服務(wù)端的開(kāi)發(fā)平臺(tái),它讓 JavaScript 成為與PHP、Python、Perl、Ruby?等服務(wù)端語(yǔ)言平起平坐的腳本語(yǔ)言。
特點(diǎn):
單線程
Node可以在不新增額外線程的情況下,依然可以對(duì)任務(wù)進(jìn)行并發(fā)處理 —— Node.js是單線程的。它通過(guò)事件循環(huán)(event loop)來(lái)實(shí)現(xiàn)并發(fā)操作,對(duì)此,我們應(yīng)該要充分利用這一點(diǎn) —— 盡可能的避免阻塞操作,取而代之,多使用非阻塞操作。
非阻塞IO
V8虛擬機(jī)
事件驅(qū)動(dòng)
六、事件驅(qū)動(dòng)
所謂事件驅(qū)動(dòng),簡(jiǎn)單地說(shuō)就是你點(diǎn)什么按鈕(即產(chǎn)生什么事件),電腦執(zhí)行什么操作(即調(diào)用什么函數(shù)).當(dāng)然事件不僅限于用戶的操作. 事件驅(qū)動(dòng)的核心自然是事件。從事件角度說(shuō),事件驅(qū)動(dòng)程序的基本結(jié)構(gòu)是由一個(gè)事件收集器、一個(gè)事件發(fā)送器和一個(gè)事件處理器組成。事件收集器專門(mén)負(fù)責(zé)收集所有事件,包括來(lái)自用戶的(如鼠標(biāo)、鍵盤(pán)事件等)、來(lái)自硬件的(如時(shí)鐘事件等)和來(lái)自軟件的(如操作系統(tǒng)、應(yīng)用程序本身等)。事件發(fā)送器負(fù)責(zé)將收集器收集到的事件分發(fā)到目標(biāo)對(duì)象中。事件處理器做具體的事件響應(yīng)工作,它往往要到實(shí)現(xiàn)階段才完全確定,因而需要運(yùn)用虛函數(shù)機(jī)制(函數(shù)名往往取為類似于HandleMsg的一個(gè)名字)。對(duì)于框架的使用者來(lái)說(shuō),他們唯一能夠看到的是事件處理器。這也是他們所關(guān)心的內(nèi)容
七、非阻塞i/o
非阻塞I/O是指以異步來(lái)執(zhí)行函數(shù),先執(zhí)行同步任務(wù),耗時(shí)任務(wù)放在事件隊(duì)列中,以此輪詢執(zhí)行。
八、webpack和gulp
二者比較
gulp它是基于流的自動(dòng)化構(gòu)建工具。有task處理機(jī)制,入口是src,通過(guò)管道pipe打包文件。配置文件是gulpfile.js
webpack的兩大特點(diǎn):1模塊化 2打包。Webpack實(shí)現(xiàn)了模塊化開(kāi)發(fā)和文件處理。它能夠?qū)⒏鱾€(gè)模塊進(jìn)行按需加載,不會(huì)導(dǎo)致加載了無(wú)用或冗余的代碼。配置文件webpack.config.js
功能:
1將sass/less 等預(yù)編譯的css語(yǔ)言轉(zhuǎn)換成瀏覽器識(shí)別的css文件
2能夠?qū)⒍鄠€(gè)預(yù)編譯文件打包成一個(gè)文件
3 打包image/styles/assets/scrips/等前端常用的文件
4 搭建開(kāi)發(fā)環(huán)境開(kāi)啟服務(wù)器
5 監(jiān)視文件改動(dòng),熱部署。
九、模塊化
模塊化的優(yōu)點(diǎn)
解決命名沖突
提供復(fù)用性
提高代碼可維護(hù)性
實(shí)現(xiàn):
CommonJs
隨著Javasript應(yīng)用進(jìn)軍服務(wù)器端,業(yè)界急需一種標(biāo)準(zhǔn)的模塊化解決方案,于是,CommonJS(www.commonjs.org)應(yīng)運(yùn)而生。它最初是由Kevin Dangoor在他的這篇博文中首次提出。
這是一種被廣泛使用的Javascript模塊化規(guī)范,大家最熟悉的Node.js應(yīng)用中就是采用這個(gè)規(guī)范。在Node.js中,內(nèi)置了module對(duì)象用來(lái)定義模塊, require函數(shù)用來(lái)加載模塊文件,代碼如下:
// utils.js 模塊定義var add = function(a, b) {
? ? return a + b;
};
module.exports = {
? ? add: add
};// 加載模塊var utils = require('./utils');console.log(utils.add(1, 2));
此種模塊化方案特點(diǎn)就是:同步阻塞式加載,無(wú)法實(shí)現(xiàn)按需異步加載。另外,如果想要在瀏覽器中使用CommonJS模塊就需要使用Browserify進(jìn)行解析:
npm install browserify -g
browserify utils.js > bundle.js
當(dāng)然,你也可以使用gulp, webpack等工具進(jìn)行解析打包后引入到瀏覽器頁(yè)面中去。
ES6 Modules
對(duì)于ES6來(lái)說(shuō),不必再使用閉包和封裝函數(shù)等方式進(jìn)行模塊化支持了。在ES6中,從語(yǔ)法層面就提供了模塊化的功能。然而受限于瀏覽器的實(shí)現(xiàn)程度,如果想要在瀏覽器中運(yùn)行,還是需要通過(guò)Babel等轉(zhuǎn)譯工具進(jìn)行編譯。ES6提供了import和export命令,分別對(duì)應(yīng)模塊的導(dǎo)入和導(dǎo)出功能。具體實(shí)例如下:
// demo-export.js 模塊定義var name = "scq000"var sayHello = (name) => {
? console.log("Hi," + name);
}export {name, sayHello};// demo-import.js 使用模塊import {sayHello} from "./demo-export";
sayHello("scq000");
對(duì)于具體的語(yǔ)法細(xì)節(jié),想必大家在日常使用過(guò)程中都已經(jīng)輕車(chē)熟路了。但對(duì)于ES6模塊化來(lái)說(shuō),有以下幾點(diǎn)特性是需要記住的:
ES6使用的是基于文件的模塊。所以必須一個(gè)文件一個(gè)模塊,不能將多個(gè)模塊合并到單個(gè)文件中去。
ES6模塊API是靜態(tài)的,一旦導(dǎo)入模塊后,無(wú)法再在程序運(yùn)行過(guò)程中增添方法。
ES6模塊采用引用綁定(可以理解為指針)。這點(diǎn)和CommonJS中的值綁定不同,如果你的模塊在運(yùn)行過(guò)程中修改了導(dǎo)出的變量值,就會(huì)反映到使用模塊的代碼中去。所以,不推薦在模塊中修改導(dǎo)出值,導(dǎo)出的變量應(yīng)該是靜態(tài)的。
ES6模塊采用的是單例模式,每次對(duì)同一個(gè)模塊的導(dǎo)入其實(shí)都指向同一個(gè)實(shí)例
Webpack中的模塊化方案
作為現(xiàn)代化的前端構(gòu)建工具,Webpack還提供了豐富的功能能夠使我們更加輕易地實(shí)現(xiàn)模塊化。利用Webpack,你不僅可以將Javascript文件進(jìn)行模塊化,同時(shí)還能針對(duì)圖片,css等靜態(tài)資源進(jìn)行模塊化。你可以在代碼里使用CommonJS, ES6等模塊化語(yǔ)法,打包的時(shí)候你也可以根據(jù)需求選擇打包類型,如UMD, AMD等:
module.exports = {
? //...
? output: {
? ? library: 'librayName',
? ? libraryTarget: 'umd', // 配置輸出格式
? ? filename: 'bundle.js'
? }
};
另外,ES6模塊好處很多,但是并不支持按需加載的功能, 而按需加載又是Web性能優(yōu)化中重要的一個(gè)環(huán)節(jié)。好在我們可以借助Webpack來(lái)彌補(bǔ)這一缺陷。Webpack v1版本提供了require.ensureAPI, 而2.x之后使用了import()函數(shù)來(lái)實(shí)現(xiàn)異步加載。具體的代碼示例可以查看我之前所寫(xiě)的前端性能優(yōu)化之加載技術(shù)?這篇文章。
十、mvvm mvc
PS:MVVM(Model-View-ViewModel), 源自于經(jīng)典的 Model–View–Controller(MVC)模式。MVVM 的出現(xiàn)促進(jìn)了 GUI 前端開(kāi)發(fā)與后端業(yè)務(wù)邏輯的分離,極大地提高了前端開(kāi)發(fā)效率。MVVM 的核心是 ViewModel 層,它就像是一個(gè)中轉(zhuǎn)站(value converter),負(fù)責(zé)轉(zhuǎn)換 Model 中的數(shù)據(jù)對(duì)象來(lái)讓數(shù)據(jù)變得更容易管理和使用,該層向上與視圖層進(jìn)行雙向數(shù)據(jù)綁定,向下與 Model 層通過(guò)接口請(qǐng)求進(jìn)行數(shù)據(jù)交互,起呈上啟下作用。View 層展現(xiàn)的不是 Model 層的數(shù)據(jù),而是 ViewModel 的數(shù)據(jù),由 ViewModel 負(fù)責(zé)與 Model 層交互,這就完全解耦了 View 層和 Model 層,這個(gè)解耦是至關(guān)重要的,它是前后端分離方案實(shí)施的最重要一環(huán)。
十一、ajax 、axios、fetch
Ajax
傳統(tǒng) Ajax 指的是 XMLHttpRequest(XHR), 最早出現(xiàn)的發(fā)送后端請(qǐng)求技術(shù),隸屬于原始js中,核心使用XMLHttpRequest對(duì)象,多個(gè)請(qǐng)求之間如果有先后關(guān)系的話,就會(huì)出現(xiàn)回調(diào)地獄。
JQuery ajax 是對(duì)原生XHR的封裝,除此以外還增添了對(duì)JSONP的支持。經(jīng)過(guò)多年的更新維護(hù),真的已經(jīng)是非常的方便了,;如果是硬要舉出幾個(gè)缺點(diǎn),那可能只有:
1.本身是針對(duì)MVC的編程,不符合現(xiàn)在前端MVVM的浪潮
2.基于原生的XHR開(kāi)發(fā),XHR本身的架構(gòu)不清晰。
3.JQuery整個(gè)項(xiàng)目太大,單純使用ajax卻要引入整個(gè)JQuery非常的不合理(采取個(gè)性化打包的方案又不能享受CDN服務(wù))
4.不符合關(guān)注分離(Separation of Concerns)的原則
5.配置和調(diào)用方式非?;靵y,而且基于事件的異步模型不友好。
PS:MVVM(Model-View-ViewModel), 源自于經(jīng)典的 Model–View–Controller(MVC)模式。MVVM 的出現(xiàn)促進(jìn)了 GUI 前端開(kāi)發(fā)與后端業(yè)務(wù)邏輯的分離,極大地提高了前端開(kāi)發(fā)效率。MVVM 的核心是 ViewModel 層,它就像是一個(gè)中轉(zhuǎn)站(value converter),負(fù)責(zé)轉(zhuǎn)換 Model 中的數(shù)據(jù)對(duì)象來(lái)讓數(shù)據(jù)變得更容易管理和使用,該層向上與視圖層進(jìn)行雙向數(shù)據(jù)綁定,向下與 Model 層通過(guò)接口請(qǐng)求進(jìn)行數(shù)據(jù)交互,起呈上啟下作用。View 層展現(xiàn)的不是 Model 層的數(shù)據(jù),而是 ViewModel 的數(shù)據(jù),由 ViewModel 負(fù)責(zé)與 Model 層交互,這就完全解耦了 View 層和 Model 層,這個(gè)解耦是至關(guān)重要的,它是前后端分離方案實(shí)施的最重要一環(huán)。
axios
axios 是一個(gè)基于Promise 用于瀏覽器和 nodejs 的 HTTP 客戶端,本質(zhì)上也是對(duì)原生XHR的封裝,只不過(guò)它是Promise的實(shí)現(xiàn)版本,符合最新的ES規(guī)范,它本身具有以下特征:
注:
1、從瀏覽器創(chuàng)建XMLHttpRequest
2、node.js發(fā)送http請(qǐng)求
3、支持promiseAPI
4、攔截請(qǐng)求和響應(yīng)
5、轉(zhuǎn)換請(qǐng)求和響應(yīng)
6、取消請(qǐng)求
7、JSON數(shù)據(jù)的自動(dòng)轉(zhuǎn)換
8、客戶端對(duì)防止XSRF的支持
PS:防止CSRF:就是讓你的每個(gè)請(qǐng)求都帶一個(gè)從cookie中拿到的key, 根據(jù)瀏覽器同源策略,假冒的網(wǎng)站是拿不到你cookie中得key的,這樣,后臺(tái)就可以輕松辨別出這個(gè)請(qǐng)求是否是用戶在假冒網(wǎng)站上的誤導(dǎo)輸入,從而采取正確的策略。
axios既提供了并發(fā)的封裝,而且體積也較小,當(dāng)之無(wú)愧現(xiàn)在最應(yīng)該選用的請(qǐng)求的方式。
fetch
fetch號(hào)稱是AJAX的替代品,是在ES6出現(xiàn)的,使用了ES6中的promise對(duì)象。Fetch是基于promise設(shè)計(jì)的。Fetch的代碼結(jié)構(gòu)比起ajax簡(jiǎn)單多了,參數(shù)有點(diǎn)像jQuery ajax。但是,一定記住fetch不是ajax的進(jìn)一步封裝,而是原生js,沒(méi)有使用XMLHttpRequest對(duì)象。
fetch的優(yōu)點(diǎn):
1.符合關(guān)注分離,沒(méi)有將輸入、輸出和用事件來(lái)跟蹤的狀態(tài)混雜在一個(gè)對(duì)象里
2.更好更方便的寫(xiě)法
坦白說(shuō),上面的理由對(duì)我來(lái)說(shuō)完全沒(méi)有什么說(shuō)服力,因?yàn)椴还苁荍query還是Axios都已經(jīng)幫我們把xhr封裝的足夠好,使用起來(lái)也足夠方便,為什么我們還要花費(fèi)大力氣去學(xué)習(xí)fetch?
我認(rèn)為fetch的優(yōu)勢(shì)主要優(yōu)勢(shì)就是:
1.? 語(yǔ)法簡(jiǎn)潔,更加語(yǔ)義化
2.? 基于標(biāo)準(zhǔn) Promise 實(shí)現(xiàn),支持 async/await
3.? 同構(gòu)方便,使用 [isomorphic-fetch](https://github.com/matthew-andrews/isomorphic-fetch)
4.更加底層,提供的API豐富(request, response)
5.脫離了XHR,是ES規(guī)范里新的實(shí)現(xiàn)方式
十二、有關(guān)于異步的問(wèn)題
promise
是異步編程的一種解決方案。
從語(yǔ)法上說(shuō),Promise 是一個(gè)對(duì)象,從它可以獲取異步操作的消息。
Promise 狀態(tài)以及狀態(tài)的特點(diǎn)
Promise 異步操作有三種狀態(tài):pending(進(jìn)行中)、fulfilled(已成功)和 rejected(已失敗)。除了異步操作的結(jié)果,任何其他操作都無(wú)法改變這個(gè)狀態(tài)。
Promise 對(duì)象只有:從 pending 變?yōu)?fulfilled 和從 pending 變?yōu)?rejected 的狀態(tài)改變。只要處于 fulfilled 和 rejected ,狀態(tài)就不會(huì)再變了即 resolved(已定型)。
狀態(tài)的缺點(diǎn)
無(wú)法取消 Promise ,一旦新建它就會(huì)立即執(zhí)行,無(wú)法中途取消。
如果不設(shè)置回調(diào)函數(shù),Promise 內(nèi)部拋出的錯(cuò)誤,不會(huì)反應(yīng)到外部。
當(dāng)處于 pending 狀態(tài)時(shí),無(wú)法得知目前進(jìn)展到哪一個(gè)階段(剛剛開(kāi)始還是即將完成)。、
then 方法接收兩個(gè)函數(shù)作為參數(shù),第一個(gè)參數(shù)是 Promise 執(zhí)行成功時(shí)的回調(diào),第二個(gè)參數(shù)是 Promise 執(zhí)行失敗時(shí)的回調(diào),兩個(gè)函數(shù)只會(huì)有一個(gè)被調(diào)用。
generator
yield是ES6的新關(guān)鍵字,使生成器函數(shù)執(zhí)行暫停,yield關(guān)鍵字后面的表達(dá)式的值返回給生成器的調(diào)用者。它可以被認(rèn)為是一個(gè)基于生成器的版本的return關(guān)鍵字。
yield關(guān)鍵字實(shí)際返回一個(gè)IteratorResult(迭代器)對(duì)象,它有兩個(gè)屬性,value和done,分別代表返回值和是否完成。
yield無(wú)法單獨(dú)工作,需要配合generator(生成器)的其他函數(shù),如next,懶漢式操作,展現(xiàn)強(qiáng)大的主動(dòng)控制特性。
function *gen() {
? ? yield 'hello';
? ? yield 'world';
? ? return true;
}
以上代碼定義了一個(gè)簡(jiǎn)單的 generator,看起來(lái)就像一個(gè)普通的函數(shù),區(qū)別是function關(guān)鍵字后面有個(gè)*號(hào),函數(shù)體內(nèi)可以使用yield語(yǔ)句進(jìn)行流程控制。
?var iter?=?gen();
?var a?= iter.next();
?console.log(a);?// {value:'hello', done:false}
?var b?= iter.next();
?console.log(b);?// {value:'world', done:false}
?var c?= iter.next();
?console.log(c);?// {value:true, done:true}
當(dāng)執(zhí)行g(shù)en()的時(shí)候,并不執(zhí)行 generator 函數(shù)體,而是返回一個(gè)迭代器。迭代器具有next()方法,每次調(diào)用 next() 方法,函數(shù)就執(zhí)行到y(tǒng)ield語(yǔ)句的地方。next() 方法返回一個(gè)對(duì)象,其中value屬性表示 yield 關(guān)鍵詞后面表達(dá)式的值,done 屬性表示是否遍歷結(jié)束。generator 生成器通過(guò)next和yield的配合實(shí)現(xiàn)流程控制,上面的代碼執(zhí)行了三次 next() ,generator 函數(shù)體才執(zhí)行完畢。
async
async 函數(shù)返回一個(gè) Promise 對(duì)象
function testAwait(){? return new Promise((resolve) => {? ? ? setTimeout(function(){? ? ? ? ? console.log("testAwait");
? ? ? ? ? resolve();
? ? ? }, 1000);
? });} async function helloAsync(){? await testAwait();
? console.log("helloAsync");
}helloAsync();// testAwait// helloAsync
await針對(duì)所跟不同表達(dá)式的處理方式:
Promise 對(duì)象:await 會(huì)暫停執(zhí)行,等待?Promise 對(duì)象 resolve,然后恢復(fù) async 函數(shù)的執(zhí)行并返回解析值。
非 Promise 對(duì)象:直接返回對(duì)應(yīng)的值。
十三、Object.keys()和Reflect.ownKeys()區(qū)別
Object.keys()返回屬性key,但不包括不可枚舉的屬性
Reflect.ownKeys()返回所有屬性key
他們兩個(gè)都不能遍歷原型上的屬性
擴(kuò)展
for in
for in一般用于遍歷對(duì)象的屬性;
作用于數(shù)組的for in除了會(huì)遍歷數(shù)組元素外,還會(huì)遍歷自定義可枚舉的屬性,以及原型鏈上可枚舉的屬性;
作用于數(shù)組的for in的遍歷結(jié)果是數(shù)組的索引,且都為字符串型,不能用于運(yùn)算;
某些情況下,可能按照隨機(jī)順序遍歷數(shù)組元素;
for of
ES6中添加的循環(huán)語(yǔ)法;
for of支持遍歷數(shù)組、類對(duì)象(例如DOM NodeList對(duì)象)、字符串、Map對(duì)象、Set對(duì)象;
for of不支持遍歷普通對(duì)象,可通過(guò)與Object.keys()搭配使用遍歷;
for of遍歷后的輸出結(jié)果為數(shù)組元素的值;
十四、頁(yè)面卡頓的原因
1、js運(yùn)行時(shí)間太長(zhǎng)
2、head加載js時(shí)一直沒(méi)加載出來(lái)
3、dom過(guò)多
4、首屏加載資源過(guò)大(解決:默認(rèn)資源站位)
十五、瀏覽器存儲(chǔ)(cookie 、webstorage)
https://www.cnblogs.com/qiujianmei/p/10824682.html
React
一、子組件向父組件傳值
父子組件通信不僅可以傳值,還可以傳遞方法,父組件將更新數(shù)據(jù)的方法拿給子組件使用,子組件將自身的數(shù)據(jù)傳入這個(gè)方法并調(diào)用,以此來(lái)改變父組件的數(shù)據(jù)。
就是父組件給子組件傳遞一個(gè)方法,子組件將自己的數(shù)據(jù)傳入這個(gè)方法并調(diào)用,就能改變父組件數(shù)據(jù)
二、父組件調(diào)用子組件的方法
先向子組件傳方法,子組件通過(guò)父組件傳遞的方法向父組件傳遞方法,父組件獲取到子組件的方法直接調(diào)用。
三、state和prop的區(qū)別
2-1.prop用于定義外部接口,state用于記錄內(nèi)部狀態(tài)
2-2,prop 的賦值在外部世界使用組件時(shí),state的賦值在組件內(nèi)部,
2-3,組件不應(yīng)該改變prop的值,而state存在的目的就是讓組件來(lái)改變的
四、修改數(shù)據(jù)應(yīng)該在哪個(gè)生命周期里面
didMount、didUpdate()
五、虛擬dom
1、瀏覽器資源對(duì)dom節(jié)點(diǎn)開(kāi)銷很大,而且頻繁改變dom結(jié)點(diǎn),會(huì)引發(fā)重繪和回流,非常影響性能。
2、虛擬dom存在的意義就是為了減少對(duì)實(shí)際dom的操作,js運(yùn)行速度很快,通過(guò)對(duì)比新舊dom,有針對(duì)性的把差異部分渲染到頁(yè)面上
3、虛擬dom原理:
⑴用js模擬dom樹(shù),并渲染dom樹(shù)
⑵比較新老dom樹(shù),得到比較的差異對(duì)象
⑶把差異對(duì)象應(yīng)用到渲染的dom樹(shù)
4、js創(chuàng)建虛擬dom
5、diff算法
作用:是用來(lái)計(jì)算出 Virtual DOM 中被改變的部分,然后針對(duì)該部分進(jìn)行原生DOM操作。
createElement(tag,props,children)
策略:策略一(tree diff):
Web UI中DOM節(jié)點(diǎn)跨層級(jí)的移動(dòng)操作特別少,可以忽略不計(jì)。
? 策略二(component diff):
擁有相同類的兩個(gè)組件 生成相似的樹(shù)形結(jié)構(gòu),
擁有不同類的兩個(gè)組件 生成不同的樹(shù)形結(jié)構(gòu)。
? 策略三(element diff):
對(duì)于同一層級(jí)的一組子節(jié)點(diǎn),通過(guò)唯一id區(qū)分。
六、react生命周期
https://www.cnblogs.com/kdcg/p/9182393.html
1、construtor():構(gòu)造函數(shù)
組建加載前最先調(diào)用一次,僅調(diào)用一次
作用:定義狀態(tài)機(jī)變量
2、componentWillMount
組件初始渲染(render()被調(diào)用)前調(diào)用,僅調(diào)用一次。
如果這個(gè)函數(shù)調(diào)用的setState改變了組件的某些狀態(tài),react會(huì)等待setState完成后再渲染組件
注意子組件也有componentWillMount函數(shù),在父組件的該函數(shù)調(diào)用后在調(diào)用。
3、render()
執(zhí)行:componentWillMount調(diào)用之后,componentDidMount調(diào)用之前
作用:渲染掛載組件。
觸發(fā):⑴初始化加載頁(yè)面,⑵狀態(tài)機(jī)改變setState,⑶接受新的props(父組件更新)
注意:這是組件必要參數(shù),不能在該函數(shù)內(nèi)使用setState改變狀態(tài)機(jī)
4、componentDidMount()
執(zhí)行:render()之后被調(diào)用,僅調(diào)用一次。
作用:渲染掛載組件
注意:子組件也有該函數(shù),在父組件調(diào)用前調(diào)用,如果該函數(shù)有setState改變狀態(tài)機(jī),將重新渲染組件,如果需要在頁(yè)面初始化之后才改變狀態(tài)機(jī)的,可以將網(wǎng)絡(luò)請(qǐng)求放在該函數(shù)內(nèi)。
5、componentWillReceiveProps()
執(zhí)行:組件渲染后,當(dāng)組件接收新的參數(shù)時(shí)被調(diào)用,
6、shouldComponentUpDate(nextProps,nextState)
執(zhí)行:組件執(zhí)行render()函數(shù)之后,接收新的props或state時(shí)被調(diào)用,即每次執(zhí)行setState都會(huì)執(zhí)行該函數(shù),來(lái)判斷是否重新渲染組件,默認(rèn)返回true,接收兩個(gè)參數(shù)。
作用:如果有些變化不需要執(zhí)行渲染組件,可在該函數(shù)內(nèi)阻止,
注意:不能在該函數(shù)內(nèi)使用setState來(lái)改變狀態(tài)機(jī)。
7、componentDidUpdate()
執(zhí)行:組件重新渲染后調(diào)用,初始化渲染的時(shí)候該方法不會(huì)被調(diào)用。
作用:使用該方法可以在組件更新后操作dom元素
8、componentWillUnmount()
執(zhí)行:組件卸載之前被調(diào)用
作用:在該方法中執(zhí)行必要的清理,比如無(wú)效的定時(shí)器
注意:當(dāng)一個(gè)頁(yè)面中存在父子組件的時(shí)候,要特別注意componentDidMount的使用,因?yàn)樽咏M件componentDidMount會(huì)比父組件先調(diào)用,從而引起父子組件傳參錯(cuò)誤
七、Component與PureComponent的區(qū)別
https://www.cnblogs.com/ly0612/p/11954414.html
PureComponent簡(jiǎn)單實(shí)現(xiàn)了shouldComponentUpdate()的功能。當(dāng)然數(shù)據(jù)結(jié)構(gòu)比較復(fù)雜就不行了。
PureComponent缺點(diǎn)
可能會(huì)因深層的數(shù)據(jù)不一致而產(chǎn)生錯(cuò)誤的否定判斷,從而shouldComponentUpdate結(jié)果返回false,界面得不到更新。
八、怎么寫(xiě)一個(gè)組件
https://blog.csdn.net/donspeng/article/details/83421136
組件目的是為了提高代碼復(fù)用性,另外,組件必須功能單一,復(fù)用性高。如果想實(shí)現(xiàn)復(fù)用性強(qiáng)的特點(diǎn)的話,可以用高階組件的思想,傳參數(shù)通過(guò)props
九、connect()參數(shù)有幾個(gè)
函數(shù)將被調(diào)用兩次。第一次是設(shè)置參數(shù),第二次是組件與 Redux store 連接:connect(mapStateToProps, mapDispatchToProps, mergeProps)(MyComponent)。
十、路由
十一、react優(yōu)化
十二、服務(wù)器渲染
十三、react hooks方法有哪些方法
1、基礎(chǔ) Hook
useState
useEffect
useContext
2、額外的 Hook
useReducer
useCallback
useMemo
useRef
useImperativeHandle
useLayoutEffect
useDebugValue
十四、setState
什么時(shí)候setState是同步的
1、React通過(guò)addEventListener直接添加事件處理函數(shù),
2、通過(guò)setTimeout/setInterval產(chǎn)生異步調(diào)用
原理解析:
在React的setState函數(shù)實(shí)現(xiàn)中,會(huì)根據(jù)一個(gè)變量 isBatchingUpdate 來(lái)判斷是直接同步更新this.state還是放到隊(duì)列中異步更新 。這個(gè)變量默認(rèn)為false即同步執(zhí)行,而當(dāng) React 在調(diào)用事件處理函數(shù)之前就會(huì)調(diào)用這個(gè) batchedUpdates,這個(gè)函數(shù)會(huì)把isBatchingUpdate變?yōu)閠rue,然后異步執(zhí)行setState。
React使用了事務(wù)的機(jī)制,React的每個(gè)生命周期和合成事件都處在一個(gè)大的事務(wù)當(dāng)中。在事務(wù)的前置鉤子中調(diào)用batchedUpdates方法修改isBatchingUpdates變量為true,在后置鉤子中將變量置為false。原生綁定事件和setTimeout異步的函數(shù)沒(méi)有進(jìn)入到React的事務(wù)當(dāng)中,或者當(dāng)他們執(zhí)行時(shí),剛剛的事務(wù)已近結(jié)束了,后置鉤子觸發(fā)了,所以此時(shí)的setState會(huì)直接進(jìn)入非批量更新模式,表現(xiàn)在我們看來(lái)成為了同步SetState
十五、淺談redux
最外層是Provider(react-redux解構(gòu)出來(lái))<Provider store={store}>
然后是store, store里面是reducer
reducer傳兩個(gè)參數(shù)(state,action)返回新的state
頁(yè)面用connect(mapstate,dispatchstate,組件)或者使用裝飾器
為什么reducer是純函數(shù)
因?yàn)椴荒芨淖冚斎胫祍tate,說(shuō)白了就是reducer傳state和action返回新的state
為什么這樣設(shè)計(jì)
因?yàn)轫?yè)面渲染需要比較新舊state,react比較state比較的是地址(也就是淺比較,如果深比較耗費(fèi)性能)所以必須返回新的state,否則頁(yè)面不更新
首先得先知道什么是純函數(shù)
1、相同的輸入永遠(yuǎn)返回相同的輸出
2、不能修改輸入值
3、不依賴外部環(huán)境
4、無(wú)任何副作用
十六、React組件有那些
可分為函數(shù)組件,class組件、渲染組件、組合組件、有狀態(tài)組件、無(wú)狀態(tài)組件、高階組件、自定義組件