文章目錄
- 面-什么是SEO
- 面 - cookie / localstorage / sessionstorage的區別
- 面 - promise面試題
- 面 - 柯里化函數
- 面 - 函數節流
- 面 - 函數防抖
- HTML / CSS 知識點
- 1、講講盒模型(螞蟻金服 2019.03 招行信用卡 2019.04 美團 作業幫)
- 2、根據盒模型解釋邊距重疊(螞蟻金服 2019.03 圖森未來)
- 3、 寬高比4:3自適應 (螞蟻金服 2019.03 )
- 4、css選擇器的優先級( 百度前端 搜狐 美團 拼多多 VIVO)
- 5、css水平居中 (螞蟻金服、百度前端、字節跳動)
- 6、CSS3 的 flexbox(彈性盒布局模型)以及適用場景 (猿輔導)
- 7、如何畫一個三角形 (星環科技)
- 8、讓一個圖片無限旋轉(螞蟻金服 2019.03)
- 9、display 有哪些值?說明他們的作用?
- 10、position 的值?
- 11、為什么要初始化 CSS 樣式
- 12、簡要介紹一下CSS3的新特性
- 13、元素的顯示與隱藏
- 14、`display: none`與`visibility: hidden`的區別
- 15.如何讓一個不設寬高的div,垂直水平居中
- 16.什么是BFC
- 17.css reset 瀏覽器樣式重置
- 18.常用的幾種開發布局方式
- 19-兼容問題,漸進增強和優雅降級
- 20-設置p標簽屬性,ie6以下為黑。ie7以下為紅
- 20-html/xhtml/xml
- 21-對比一下div+css和table布局
- 22-console
- 23-為什么利用多個域名來提供網站資源會更有效
- 24-談談以前端角度出發做好 SEO 需要考慮什么?
- 25-rgba()和 opacity 的透明效果有什么不同?
- 26 - sass和less
- 27-css3動畫和js動畫區別
- 28-css3和html5新特性
- **1、CSS3 新特性有哪些?**
- 2.**html5 有哪些新特性、移除了那些元素?如何處理 HTML5 新標簽的瀏覽器兼容問題?**
- 支持 HTML5 新標簽:
- 29-image 和 canvas 在處理圖片的時候有什么區別?
- 30-HTML5中的本地存儲介紹一下
- 31- margin塌陷解決方式
- 32- 清浮動方法
- 33- flex
- 34- 常見的布局方式
- 35-css中的1px問題
- 36- CSS實現水平垂直居中
- 37- 層疊上下文和層疊等級
- 38- 移動端的1px
- js知識點
- 面 - js對象隱形轉成原始數據類型
- 面 - 基礎類型使用方法
- 1.數據類型和方法
- 1-1 操作數組方法
- 2- string對象
- 2.操作符
- 5.類和實例和繼承
- 原型和原型鏈
- 7. ES高級
- 8- DOM
- 面 - onload 和 onDomContentLoaded的區別
- 1- 元素查找
- 2- 事件流
- 3- 事件對象
- 9- BOM
- Location對象
- History對象
- Navigation對象
- window對象
- 移動端dom
- 10- js的執行機制
- 10-1 編譯過程
- 10-2 代碼執行過程
- 10-3 詞法作用域/函數作用域/塊作用域和閉包
- 10-4 預解析
- 10-5 this
- 面 - 手寫new
- 面 - 手寫call()
- get和post 的區別
- 面試題
- 3.防抖和節流的區別是什么?怎么實現?
- 4.深拷貝和淺拷貝有什么區別?你能實現一個深拷貝嗎?
- 淺拷貝實現 , 只拷貝當前基本屬性的值,不會拷貝復雜屬性的值 ,俗稱:只拷貝地址,不拷貝內容
- 深拷貝實現 拷貝當前的值,復雜屬性也一并拿來,拷貝全部屬性值,換個地址而已
- 8.實現一個new函數
- 9.箭頭函數和普通函數的區別是什么?
- 10.實現一個promise
- 11.promise、async/await、setTimeout的區別是什么?
- vue知識點
- 面- 介紹一下什么是SSR
- 面-vue的跨平臺是如何做到的
- 面 - 文件上傳的幾種方式,聊聊大文件上傳
- 面 - 組件設計和狀態設計
- 1-vue的使用
- 1-1 插值表達式
- 1-2 指令
- 1-3計算屬性 和 過濾器 和 監聽屬性
- **計算屬性** - 多個數據影響一個數據
- 監聽屬性 - 一個數據影響多個數據
- 每個的使用場景
- 1-4 生命周期
- 1-5 事件監聽器
- 1-6 內置組件
- 2-vue高級特性
- 2-1 .$nextTick
- 2-2 組件的name屬性 - 遞歸組件
- 2-3 組件通信
- 面--父傳子的生命周期
- 面--父組件監聽子組件的生命周期
- 2-3 slot插槽
- 面- 如何在vue中提取可復用的組件
- 2-4 動態組件
- 2-5 異步組件
- 2-6 緩存組件 keep - alive
- 2-7 mixin
- 2-8 自定義指令
- 3-vue底層原理
- 3-1組件化(vue核心)
- 面--說說組件化工程化和模塊化
- 3-2響應式(
- 3-3 vdom 和 diff
- 面- 為何要加上key
- 3-4 模板編譯
- 3-5 組件更新 和 渲染過程
- 3-6 前端路由原理
- 面- 如何實現vue-router切換頁面后,保持在頁面頂部/保持原先位置不變
- 4-相關插件
- 4-1 axios工具包
- 面--axios如何解決跨域問題?
- 4-2 vuex
- 核心
- 面-- 頁面刷新的時候數據丟失
- 面 - vuex實現雙向綁定
- 4-3 vue-router
- 1-使用步驟
- 2- 編程式導航
- 3-路由元信息
- 4-導航跳轉流程
- 5- 獲取路由跳轉的信息
- 面 - 如何監聽路由參數的變化
- 面 - 使用動態路由切換時候,組件沒有變化,不會觸發生命周期函數
- 面 - 實現路由解耦
- 4-4 vue-loader
- 5- vue的性能優化
- 5-1 代碼層面的優化
- 5-2 Webpack 層面的優化
- 5-3 **基礎的** Web 技術的優化
- 面- vue如何優化首屏加載速度
- React 知識點
- 1- react的使用
- 1-1 創建react元素的方式
- 1-2 jsx{ }嵌入式表達式
- 1-3 條件渲染
- 1-4列表渲染
- 1-5 組件
- 1-6 事件
- 1-7 組件通信
- 1-8 生命周期
- 1-9 setState()
- 2- React 高級特性
- 2-1高階組件(公共邏輯代碼的抽離,minin已經棄用)
- 2-2 render - props (公共邏輯代碼的抽離,mixin已經棄用)
- 2-3 Portals 傳送門
- 2-4 異步組件
- 2-5 性能優化
- **代碼層面優化**
- Webpack 層面的優化
- Web 技術的優化
- 2-6 組件懶加載
- 3- React 核心原理
- 3-1函數式編程
- 3-2 JSX編譯
- 3-3 組件渲染過程 和 更新過程
- 3-4 合成事件機制
- 3-5 setState 和 batchUpdate機制
- 面 - React和vue對比
- webpack知識點
- 1. 什么是webpack,webpack的運行原理,如何打包 (字節跳動)
- 2.什么是bundle,什么是chunk,什么是module?
- 3.什么是Loader?什么是Plugin?
- 4. 有哪些常見的Loader?他們是解決什么問題的?
- 5. 有哪些常見的Plugin?
- 6.webpack的構建流程是什么?從讀取配置到輸出文件這個過程盡量說全
- 7.如何利用webpack來優化前端性能?
- 8. 如何提高webpack的打包速度?
- 9. 介紹模塊化發展歷程
- 10.webpack 熱更新原理
- 11-介紹一下babel
- NODEJS知識點
- 1.模塊分類
- 2.node模塊類型
- 3-中間件
- 4-node事件循環機制 和 瀏覽器的事件循環機制
- 4-1 瀏覽器的事件循環機制
- 小程序
- 面 - 小程序開發和vue開發的區別#$
- 1-文件架構
- 2- 雙線程模型
- 3- 小程序執行流程
- 瀏覽器輸入url后發生了什么(網絡 / 瀏覽器)
- 基本流程
- 1.DNS地址查詢
- 2.TCP連接
- 3.發送HTTP請求
- 4.服務器處理請求,以及響應
- 5.瀏覽器根據響應渲染頁面
- 6.tcp連接結束
- 1-DNS地址查詢
- 1.1什么是DNS
- 1-2 DNS查詢
- 1-3 DNS中的安全問題
- 1-4 DNS中的網絡性能優化
- 2-TCP連接
- 2-1什么是tcp
- 2-2 三次握手和四次揮手
- 1.**三次握手**
- 2.為什么要三次握手?
- 3.四次握手
- 4.為什么要四次揮手
- 5超時和重傳
- 6-tcp的可靠性如何保證
- 3-發送HTTP請求
- 3-1.什么是HTTP協議
- 3-2.HTTP連接方式
- 3-3.HTTP報文
- 1-報文格式
- 2-請求方式
- 3-常見的狀態碼
- 3-4-HTTP版本
- 3-5-HTTPS
- 1.**什么是HTTPS**
- **2- HTTPS功能實現**
- 1.內容被竊聽問題 - 加密
- 2.報文被篡改 - 數字簽名
- 3-通信方身份偽裝 - 數字證書
- 3-4-帶寬和延遲
- 4- 瀏覽器渲染頁面
- 4-1瀏覽器組成
- 4-2 瀏覽器如何解析資源渲染頁面
- 1.渲染引擎將html和css文檔解析成語法樹
- 2.渲染引擎將css語法樹和html語法樹結合成渲染樹
- 3.渲染引擎和js引擎
- 4.觸發瀏覽器的paint事件,根據渲染樹計算元素位置,繪制
- 5.回流和重繪
- **瀏覽器緩存
- ajax請求和跨域問題
- 1- get 請求和get 請求的區別
- 2- 網絡傳輸常用的數據格式
- xml
- json
- 3- formdata 對象
- 4- 跨域 / 同源
- 解決跨域
- v8引擎的內存控制
- 垃圾回收機制
- service worker
- 性能優化
- WEB安全
- 1.xss攻擊
- 1-1 xss介紹
- 1-2 惡意代碼注入方式
- 1-3 XSS攻擊分類
- 1-4XSS攻擊預防
- 2.CSRF攻擊
- 2-1 CSRF介紹
- 2-2 攻擊類型
- 2-3 CSRF攻擊特點
- 2-4 防護策略
- 同源檢測防護
- 雙重Cookie驗證
- Token防護
- Samesite Cookie屬性
- 2-5 CSRF 測試
- 3.點擊劫持攻擊
- 4.后端一些攻擊漏洞:命令行注入和DDos攻擊
- 面 - 開發中的數據安全問題
- 開發項目知識點
- yarn
- GIT
- 抓包工具
- linux基本指令
- 開發流程
- 短信驗證碼和圖片驗證碼
- 移動端的兼容(安卓和iOS手機)
- 2.CSRF攻擊
- 2-1 CSRF介紹
- 2-2 攻擊類型
- 2-3 CSRF攻擊特點
- 2-4 防護策略
- 同源檢測防護
- 雙重Cookie驗證
- Token防護
- Samesite Cookie屬性
- 2-5 CSRF 測試
- 3.點擊劫持攻擊
- 4.后端一些攻擊漏洞:命令行注入和DDos攻擊
- 面 - 開發中的數據安全問題
- 開發項目知識點
- yarn
- GIT
- 抓包工具
- linux基本指令
- 開發流程
- 短信驗證碼和圖片驗證碼
- 移動端的兼容(安卓和iOS手機)
-
vue知識點 -
react知識點(完善90%)
等上了redux再繼續完善
面試視頻redux沒看,react面試題沒準備
-
webpack知識點 -
html/css知識點 -
瀏覽器知識點 -
網絡知識點 -
安全問題 -
js知識點執行上下文/作用域/閉包 (概念和刷題)this/call/apply/bind (手寫)原型/繼承 (概念)Promise (看一下)深淺拷貝事件機制函數式編程es常用方法webworker防抖節流- 柯里化函數
-
typescript -
git代碼管理 -
小程序 -
性能優化(閑暇看)
- 打包優化
- 網絡優化
- 代碼優化
-
node -
設計模式
-
數據結構和算
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-a7F4lihL-1598189226388)(C:\Users\ADMINI~1\AppData\Local\Temp\1591770445912.png)]
面-什么是SEO
seo
搜索機器人的搜索網頁的模式:根據網頁類型來進行廣度和深度搜索。
搜索機器人在搜索到一個網頁時候,會優先看meta標簽的元信息。所以meta內容是增加seo的一個手段。
搜索機器人在爬網頁的時候,會對網絡的內容進行一個過濾,然后根據內容相關度,比如文本相關度進行排行。而爬網頁的過程中,如果能讓搜索機器人更理解更快更好的處理數據,也會增加seo比如標簽語義化。
還有一個很重要的seo就是外鏈。這是前端能做的增強seo最有效的一個方法。搜索機器人會根據外鏈的數量,和自己和對方外置的權重來進行一個計算,得出本網站的權重值。
- 合理的 title、description、keywords:搜索對著三項的權重逐個減小,title 值強調重點即可,重要關鍵詞出現不要超過 2 次,而且要靠前,不同頁面 title 要有所不同;description 把頁面內容高度概括,長度合適,不可過分堆砌關鍵詞,不同頁面 description 有所不同;keywords 列舉出重要關鍵詞即可
- 重要內容 HTML 代碼放在最前:搜索引擎抓取 HTML 順序是從上到下,有的搜索引擎對抓取長度有限制,保證重要內容一定會被抓取
- 重要內容不要用 js 輸出:爬蟲不會執行 js 獲取內容
- 少用 iframe(搜索引擎不會抓取 iframe 中的內容)
- 非裝飾性圖片必須加 alt
- 提高網站速度(網站速度是搜索引擎排序的一個重要指標)
面 - cookie / localstorage / sessionstorage的區別
-
cookie:一開始只是用來和服務器通信的,后來用于存儲一些本地數據,大小只有4kb,發送ajax時,自動添加cookie。操作cookie的api簡陋
-
localStorage(5M) / sessionStorage(20M)
大容量,loacalstorage永久存在瀏覽器中。sessionstorage只存在當前窗口,關閉則清除
cookie: cookie機制 客戶端瀏覽器會把Cookie保存起來。當瀏覽器再請求該網站時,瀏覽器把請求的網址連同該Cookie一同提交給服務器。
cookie 做什么? 一般用來存儲數據 比如 用戶的登錄狀態 不過現在經常用token 和localStorage了
HTTP協議本身是無狀態的。什么是無狀態呢,即服務器無法判斷用戶身份。Cookie實際上是一小段的文本信息(key-value格式)。客戶端向服務器發起請求,如果服務器需要記錄該用戶狀態,就使用response向客戶端瀏覽器頒發一個Cookie。客戶端瀏覽器會把Cookie保存起來。當瀏覽器再請求該網站時,瀏覽器把請求的網址連同該Cookie一同提交給服務器。服務器檢查該Cookie,以此來辨認用戶等狀態。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-0SGRNVSD-1598189226390)(C:\Users\ADMINI~1\AppData\Local\Temp\1592384871210.png)]
面 - promise面試題
//題目1
const promise = new Promise((resolve, reject) => {console.log(1)resolve()//此處不會阻塞console.log(2)
})
promise.then(() => {console.log(3)
})
console.log(4) //1243//題目2
const promise = new Promise((resolve, reject) => {setTimeout(() => {console.log('once')resolve('success')}, 1000)
})const start = Date.now()
promise.then((res) => {console.log(res, Date.now() - start)
})
//只要promise狀態確定了,then函數可以一直調用
promise.then((res) => {console.log(res, Date.now() - start)
})//題目三
Promise.resolve(1).then(2).then(Promise.resolve(3)).then(console.log)
// .then 或者 .catch 的參數期望是函數,傳入非函數則會發生值穿透。
面 - 柯里化函數
柯里化函數是指一個函數在內部定義了一個函數處理參數,并將其返回, 運行后可以得到新的函數,并且該函數能夠處理接下來的參數。
面 - 函數節流
限制函數一段時間內,只執行一次。防抖和節流都是js性能優化的方式,都用于檢測鼠標,滾輪,輸入框輸入等事件
var throttle = function(func, delay) {var prev = Date.now();return function() {var context = this;var args = arguments;var now = Date.now();if (now - prev >= delay) {func.apply(context, args);prev = Date.now();}}
}
function handle() {console.log(Math.random());
}
window.addEventListener('scroll', throttle(handle, 1000));
面 - 函數防抖
沒有防抖前,函數持續觸發。浪費性能,最典型的場景是輸入框觸發input事件時。這時候可以利用閉包實現函數防抖,達到事件出發后一段時間內再執行回調,若期間事件還被觸發,則重新計時。
function debounce(fn, wait) {var timeout = null;return function() {if(timeout !== null) clearTimeout(timeout);timeout = setTimeout(fn, wait);}
}
// 處理函數
function handle() {console.log(Math.random());
}
// 滾動事件
window.addEventListener('scroll', debounce(handle, 1000));
HTML / CSS 知識點
1、講講盒模型(螞蟻金服 2019.03 招行信用卡 2019.04 美團 作業幫)
盒子模型就是 元素在網頁中的實際占位,有兩種:標準盒子模型和IE盒子模型
標準(W3C)盒子模型:內容content+填充padding+邊框border+邊界margin寬高指的是 content 的寬高
低版本IE盒子模型:內容(content+padding+border)+ 邊界margin,寬高指的是content+padding+border 部分的寬高
/* 標準模型 */
box-sizing:content-box;/*IE模型*/
box-sizing:border-box;
復制代碼
2、根據盒模型解釋邊距重疊(螞蟻金服 2019.03 圖森未來)
父子元素、兄弟元素,當有外邊距時,會取其中一個邊距的最大值,作為實際的邊距。 空元素的有上下邊距時,也會取其中更大的一個邊距值,作為實際的邊距。 這就是邊距重疊。
BFC: 概念:塊級格式化上下文 原理:
- 在BFC這個元素垂直方向的邊距會發生重疊
- BFC的區域不會與浮動元素的box重疊
- BFC在頁面上是一個獨立的容器,其里外的元素不會互相影響
- 計算BFC高度時,浮動元素也會參與計算
3、 寬高比4:3自適應 (螞蟻金服 2019.03 )
垂直方向的padding: 在css中,padding-top或padding-bottom的百分比值是根據容器的width來計算的。
.wrap{position: relative;height: 0; //容器的height設置為0width: 100%;padding-top: 75%; //100%*3/4
}
.wrap > *{position: absolute;//容器的內容的所有元素absolute,然子元素內容都將被padding擠出容器left: 0;top: 0;width: 100%;height: 100%;
}
復制代碼
+ **padding & calc()**: 跟第一種方法原理相同
?```css
padding-top: calc(100%*9/16);
復制代碼
- padding & 偽元素
- 視窗單位: 瀏覽器100vw表示瀏覽器的視窗寬度
width:100vw;
height:calc(100vw*3/4)
復制代碼
4、css選擇器的優先級( 百度前端 搜狐 美團 拼多多 VIVO)
優先級就近原則,同權重情況下樣式定義最近者為準
!important>id >class>tag
important比內聯優先級高
元素選擇符的權值:元素標簽(派生選擇器):1,class選擇符:10,id選擇符:100,內聯樣式權值最大,為1000
- !important聲明的樣式優先級最高,如果沖突再進行計算。
- 如果優先級相同,則選擇最后出現的樣式。
- 繼承得到的樣式的優先級最低。
5、css水平居中 (螞蟻金服、百度前端、字節跳動)
一、對于行內元素:
text-align:center;
復制代碼
二、對于確定寬度的塊級元素:
(1)margin和width實現水平居中
常用(前提:已設置width值):margin-left:auto; margin-right:auto;
(2)絕對定位和margin-left: -(寬度值/2)實現水平居中
固定寬度塊級元素水平居中,通過使用絕對定位,以及設置元素margin-left為其寬度的一半
.content{width: 200px;position: absolute;left: 50%;margin-left: -100px; // 該元素寬度的一半,即100pxbackground-color: aqua;}
復制代碼
(3)position:absolute + (left=0+top=0+right=0+bottom=0) + margin:auto
.content{position: absolute;width: 200px;top: 0;right: 0;bottom: 0;left: 0;margin: auto;}
復制代碼
三、對于未知寬度的塊級元素:
(1)table標簽配合margin左右auto實現水平居中
使用table標簽(或直接將塊級元素設值為display:table),再通過給該標簽添加左右margin為auto
(2)inline-block實現水平居中方法
display:inline-block;(或display:inline)和text-align:center;實現水平居中
復制代碼
存在問題:需額外處理inline-block的瀏覽器兼容性(解決inline-block元素的空白間距)
(3)絕對定位實現水平居中
絕對定位+transform,translateX可以移動本省元素的50%
.content{position: absolute;left: 50%;transform: translateX(-50%); /* 移動元素本身50% */background: aqua;}
復制代碼
(4)相對定位實現水平居中
用float或者display把父元素變成行內塊狀元素
.contentParent{display: inline-block; /* 把父元素轉化為行內塊狀元素 *//*float: left; 把父元素轉化為行內塊狀元素 */position: relative;left: 50%;}/*目標元素*/.content{position: relative;right: 50%;background-color:aqua;}
復制代碼
(5)CSS3的flex實現水平居中方法,法一
.contentParent{display: flex;flex-direction: column;}.content{align-self:center;}
復制代碼
(6)CSS3的flex實現水平居中方法,法二
.contentParent{display: flex;}.content{margin: auto;}
復制代碼
(7)CSS3的fit-content配合左右margin為auto實現水平居中方法
.content{width: fit-content;margin-left: auto;margin-right: auto;}
復制代碼
參考鏈接 blog.csdn.net/dengdongxia…
6、CSS3 的 flexbox(彈性盒布局模型)以及適用場景 (猿輔導)
該布局模型的目的是提供一種更加高效的方式來對容器中的條目進行布局、對齊和分配空間。在傳統的布局方式中,block 布局是把塊在垂直方向從上到下依次排列的;而 inline 布局則是在水平方向來排列。彈性盒布局并沒有這樣內在的方向限制,可以由開發人員自由操作。flexbox設置父元素的display
屬性為flex
,則子元素都變成flex item
,通過自己內部的格式化規則。可以控制子元素的排列方式、尺寸、間距等; 試用場景:彈性布局適合于移動前端開發,在Android和ios上也完美支持。
7、如何畫一個三角形 (星環科技)
左右邊框設置為透明,長度為底部邊框的一半。左右邊框長度必須設置,不設置則只有底部一條邊框,是不能展示的。
{width: 0; height: 0; border-top: 40px solid transparent; border-left: 40px solid transparent; border-right: 40px solid transparent; border-bottom: 40px solid #ff0000;}
復制代碼
8、讓一個圖片無限旋轉(螞蟻金服 2019.03)
<img class="circle" src="001.jpg" width="400" height="400"/>//infinite 表示動畫無限次播放 linear表示動畫從頭到尾的速度是相同的.circle{animation: myRotation 5s linear infinite;}
@keyframes myRotation {from {transform: rotate(0deg);}to {transform: rotate(360deg);}
}
復制代碼
9、display 有哪些值?說明他們的作用?
inline默認。此元素會被顯示為內聯元素,元素前后沒有換行符。
block此元素將顯示為塊級元素,此元素前后會帶有換行符。
none此元素不會被顯示(隱藏)。
inline-block行內塊元素。(CSS2.1 新增的值)
list-item此元素會作為列表顯示。
table此元素會作為塊級表格來顯示(類似table),表格前后帶有換行符
10、position 的值?
absolute
生成絕對定位的元素,相對于 static 定位以外的第一個父元素進行定位。
元素的位置通過 “left”, “top”, “right” 以及 “bottom” 屬性進行規定。
fixed
生成固定定位的元素,相對于瀏覽器窗口進行定位。(老IE不支持)
元素的位置通過 “left”, “top”, “right” 以及 “bottom” 屬性進行規定。
relative
生成相對定位的元素,相對于其正常位置進行定位,不脫離文檔流。
因此,“left:20” 會向元素的 LEFT 位置添加 20 像素。
static默認值。
沒有定位,元素出現在正常的文檔流中(忽略 top, bottom, left, right 或者 z-index 聲明)。inherit規定應該從父元素繼承 position 屬性的值。
11、為什么要初始化 CSS 樣式
因為瀏覽器的兼容問題,不同瀏覽器對有些標簽的默認值是不同的,如果沒對CSS初始化往往會出現瀏覽器之間的頁面顯示差異。
12、簡要介紹一下CSS3的新特性
-
在布局方面新增了flex布局;
-
在選擇器方面新增了例如:first-of-type,nth-child等選擇器;
-
在盒模型方面添加了box-sizing來改變盒模型,
-
在動畫方面增加了animation、2d變換、3d變換等。在顏色方面添加透明、rgba等,
-
在字體方面允許嵌入字體和設置字體陰影,同時當然也有盒子的陰影,
-
媒體查詢。為不同設備基于它們的能力定義不同的樣式。
@media screen and (min-width:960px) and (max-width:1200px){body{background:yellow;} } 復制代碼
13、元素的顯示與隱藏
元素的顯示隱藏方法很多,不同方法的在不同的場景下頁面效果不一,對頁面的性能也有不同的影響。
元素隱藏方法總結:
-
如果希望元素不可見、不占據空間、資源會加載、DOM 可訪問:
display: none
; -
如果希望元素不可見、不能點擊、但占據空間、資源會加載,可以使用:
visibility: hidden
; -
如果希望元素不可見、不占據空間、顯隱時可以又
transition
淡入淡出效果div{ position: absolute;visibility: hidden;opacity: 0;transition: opacity .5s linear;background: cyan; }div.active{visibility: visible;opacity: 1; } 復制代碼
這里使用visibility: hidden
而不是display: none
,是因為display: none
會影響css3的transition
過渡效果。 但是display: none
并不會影響cssanimation
動畫的效果。
- 如果希望元素不可見、可以點擊、占據空間,可以使用:
opacity: 0
; - 如果希望元素不可見、可以點擊、不占據空間,可以使用:
opacity: 0; position: absolute;
; - 如果希望元素不可見、不能點擊、占據空間,可以使用:
position: relative; z-index: -1;
; - 如果希望元素不可見、不能點擊、不占據空間,可以使用:
position: absolute ; z-index: -1;
display: none
與visibility: hidden
的區別
14、display: none
的元素不占據任何空間,visibility: hidden
的元素空間保留;display: none
會影響css3的transition
過渡效果,visibility: hidden
不會;display: none
隱藏產生重繪 ( repaint ) 和回流 ( relfow ),visibility: hidden
只會觸發重繪;- 株連性:
display: none
的節點和子孫節點元素全都不可見,visibility: hidden
的節點的子孫節點元素可以設置visibility: visible
顯示。visibility: hidden
屬性值具有繼承性,所以子孫元素默認繼承了hidden
而隱藏,但是當子孫元素重置為visibility: visible
就不會被隱藏。
15.如何讓一個不設寬高的div,垂直水平居中
? 方法一:使用css3方法的transfrom.
11 方法二:給父盒子設置display:table-ceil,這樣子盒子就相當于表格內的元素和,可以通過text-align和vertical-align對齊
16.什么是BFC
BFC叫做塊級格式化上下文。它制造了一個獨立的渲染區域,有著自己特殊的布局方式,和外部不同。
內部布局規則有:
- 塊級元素按垂直方向一個個放置
- box的垂直方向距離由margin控制
- bfc不會和浮動元素重疊
- bfc內容高度,包括浮動元素
觸發方式:
- 根元素(html)
- float屬性不為none
- position為absolute或者fixed
- display為inline-block,table-caption
- overflow不為visible
17.css reset 瀏覽器樣式重置
每個瀏覽器對頁面樣式的處理方式不一樣。所以有時候寫樣式的時候,會把這些瀏覽器差異化的樣式統一清除后,編寫樣式。但是實際上樣式初始化會對seo有一定的影響。所以我們要在保持最小損失的情況下達到相對大的效果。
18.常用的幾種開發布局方式
流式布局/百分比布局
設置盒子的寬度的時候,采用百分比取值,使之能夠小范圍內根據,屏幕寬度調整元素距離。但是和設計圖會有偏差。
fflex布局
rem布局
媒體查詢,通過查詢screen寬度來設置根元素字體大小,然后標簽屬性的尺寸單位設置成rem。
超小<768px
小屏:768-992
中屏:992-1200
大屏:>1200
通常使用響應式框架來開發網頁,比如boostrap
19-兼容問題,漸進增強和優雅降級
漸進增強是優先針對低版本的瀏覽器進行構建頁面,保證最基本的功能,然后針對高級瀏覽器進行效果交互功能的進一步優化。
優雅降級是一開始就是構建一個完整的功能,然后再對低版本瀏覽器進行一個向下兼容的處理,甚至是閹割。比如css3h5的一些特型,低版本處理不了
20-設置p標簽屬性,ie6以下為黑。ie7以下為紅
這是css hack
p{color: green,//可以理解為特定瀏覽器下的私有屬性*color:red,_color:black
}
20-html/xhtml/xml
html是網頁設計的語言,
xhtml是xml的過度語言,和html類似,只是規則上有些差異,比如Xhtml必須有閉合標識。必須有根元素
xml是可拓展標記語言,和html語法規則類似,但是xml它用于傳遞數據,且xml標簽完全自定義
21-對比一下div+css和table布局
table布局其實我基本沒用過。只是自己練習的時候操作了一下。所以也只能簡單的對比一下兩者的差異
div+css:能夠提高seo,相對于table來說很大程度上提高了網頁的瀏覽速度。而且容易維護和改版
table:局部麻煩,代碼量大,不容易維護,seo差
22-console
console.info(“這是info”);
console.log(“這是log”);
console.debug(“這是debug”);
console.warn(“這是warn”);
console.error(“這是error”);
? console.dir(‘這是dir’)
? console.group(“第一組信息”);
console.log(“第一組第一條”);
console.log(“第一組第二條”);
console.groupEnd();
23-為什么利用多個域名來提供網站資源會更有效
- 突破瀏覽器的并發限制 現階段各大瀏覽器的同一域名最大的并發請求數量在6個或以上,低版本的IE6、7是2個。
- 節約cookie帶寬 在訪問服務器時,cookie也會占用一定的帶寬,使用多個域名進行分流。
- CDN緩存更方便 多個域名可以更快速的給客戶端分配最優下載服務器,傳輸數據更快。
- 防止不必要的安全問題,例如cookie的隔離 客戶端對服務器進行請求時,發送數據到達的地址會用一個第三方的域名。防止上傳惡意數據對cookie進行竊取。
- 節約主機域名連接數,優化頁面響應速度 這個很顯然,每個域名所響應的客戶端請求越少,反應時間也就越短,客戶端頁面可以更快下載數據。
24-談談以前端角度出發做好 SEO 需要考慮什么?
搜索機器人的搜索網頁的模式:根據網頁類型來進行廣度和深度搜索。
搜索機器人在搜索到一個網頁時候,會優先看meta標簽的元信息。所以meta內容是增加seo的一個手段。
搜索機器人在爬網頁的時候,會對網絡的內容進行一個過濾,然后根據內容相關度,比如文本相關度進行排行。而爬網頁的過程中,如果能讓搜索機器人更理解更快更好的處理數據,也會增加seo比如標簽語義化。
還有一個很重要的seo就是外鏈。這是前端能做的增強seo最有效的一個方法。搜索機器人會根據外鏈的數量,和自己和對方外置的權重來進行一個計算,得出本網站的權重值。
-
合理的 title、description、keywords:搜索對著三項的權重逐個減小,title 值強調重點即可,重要關鍵詞出現不要超過 2 次,而且要靠前,不同頁面 title 要有所不同;description 把頁面內容高度概括,長度合適,不可過分堆砌關鍵詞,不同頁面 description 有所不同;keywords 列舉出重要關鍵詞即可
-
重要內容 HTML 代碼放在最前:搜索引擎抓取 HTML 順序是從上到下,有的搜索引擎對抓取長度有限制,保證重要內容一定會被抓取
-
重要內容不要用 js 輸出:爬蟲不會執行 js 獲取內容
-
少用 iframe(搜索引擎不會抓取 iframe 中的內容)
-
非裝飾性圖片必須加 alt
-
提高網站速度(網站速度是搜索引擎排序的一個重要指標)
25-rgba()和 opacity 的透明效果有什么不同?
rgba()和 opacity 都能實現透明效果,但最大的不同是 opacity 作用于元素,以及元素內的所有
內容的透明度,
而 rgba()只作用于元素的顏色或其背景色。(設置 rgba 透明的元素的子元素不會繼承透明效果!)
26 - sass和less
? sass和less都屬于css的預處理器,是專門用一種語言來為css增加一點編程的特性,最終輸出css文件。
至于為什么使用這些css預處理器。因為css本身的語法有很多不足,比如不能嵌套書寫,沒有變量和合理的樣式復用機制。難以維護。
less對比sass的優點:
- less使用環境更簡單,只要能運行js,就能處理less文件。而cass需要安裝ruby環境
- less使用上手簡單,十分貼合css,只是增加一個些變量等復用性強的語法規則
-sass優勢:
- 有變量作用域,函數,進程控制,繼承,數據結構等
27-css3動畫和js動畫區別
js動畫功能更加強大,兼容性更好
- js對于動畫的控制粒度更細,css只能通過@keyframs來控制。
- css動畫被支持的時間函數很少,不靈活
- 現階段而言,css動畫很難做到多個狀態的轉化
- 只要支持js的客戶端都能展示出來
css優勢:性能好
- css是樣式制作的動畫,性能消耗比較少
- css3屬性,有很大的兼容問題
- 對于幀速表現不太好的瀏覽器,css可以自然降級
28-css3和html5新特性
1、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、radial-gradient
\7. 過渡:transition,可實現動畫
\8. 自定義動畫 animate @keyfrom
\9. 在 CSS3 中唯一引入的偽元素是 ::selection.
\10. 媒體查詢,多欄布局 @media screen and (width:800px){ … }
\11. border-image
12.2D 轉換:transform:translate(x,y) rotate(x,y) skew(x,y) scale(x,y)
\13. 3D 轉換
14 字體圖標 font-face
15 彈性布局 flex
2、CSS3 選擇器有哪些?
答:屬性選擇器、偽類選擇器、偽元素選擇器。
屬性選擇器 例如:[href=“a.mp4”] {color: green;}
偽類選擇器 例如:li:nth-child(3) {color: red;} span:empty h2:target li:not(.special) li:nth-last
child(3) {color: blue;}
偽元素選擇器 例如:p::selection p::first-line li::first-letter ::after ::bofer
2.html5 有哪些新特性、移除了那些元素?如何處理 HTML5 新標簽的瀏覽器兼容問題?
新特性:
\1. 拖拽釋放(Drag and drop) API ondrop
自定義屬性 data-id 獲取 li.getAttribute(‘data-id’)或者 li.dataset.type = ‘guoji’
\2. 語義化更好的內容標簽(header,nav,footer,aside,article,section)
\3. 音頻、視頻 API(audio,video) 如果瀏覽器不支持自動播放怎么辦?
\4. 畫布(Canvas) API 熱 canvas 和 image 的區別?
\5. 地理(Geolocation) API
\6. 本地離線存儲 localStorage 長期存儲數據,瀏覽器關閉后數據不丟失;
\7. sessionStorage 的數據在瀏覽器關閉后自動刪除
\8. 表單控件,calendar、date、time、email、url、search 、tel、file、number
\9. 新的技術 webworker, websocket, Geolocation
10文件讀取
移除的元素-純表現的元素:basefont,big,center,font, s,strike,tt,u;
支持 HTML5 新標簽:
* IE8/IE7/IE6 支持通過 document.createElement 方法產生的標簽,
可以利用這一特性讓這些瀏覽器支持 HTML5 新標簽,
瀏覽器支持新標簽后,還需要添加標簽默認的樣式:
* 當然最好的方式是直接使用成熟的框架、使用最多的是 html5shim 框架
<!--[if lt IE 9]> <script> src="http://html5shim.googlecode.com/svn/trunk/html5.js"</script> <![endif]-->
29-image 和 canvas 在處理圖片的時候有什么區別?
答:image 是通過對象的形式描述圖片的;canvas 通過專門的 API 將圖片繪制在畫布上。
30-HTML5中的本地存儲介紹一下
標簽之間的通信和購物車都會用到本地存儲
以前我們在存儲本地得到時候都會存儲在cookie里面,但是cookie存儲大小只有4k,而且解析復雜。而且cookie數據,在發送請求的時候,會自動發送給瀏覽器。造成更大的問題
存儲空間html5 localstorage(20m)和sessionStorage(5m)提供了一個新的本地存儲方式,存儲空間更大,操作更簡易。
生命周期:sessionStorage。在瀏覽器窗口關閉時清除。local storage需要手動清除。cookie在過期之前一直有效。
作用域: sessionStorage要想數據共享,必須在同一個瀏覽器內。localstorage和cookie在所有的同源窗口中共享
31- margin塌陷解決方式
-
給父元素設定一個border-top / padding-top限定子元素的margin
-
給父元素設定overflow:hidden 觸發BFC
-
給父元素設定浮動
-
將父元素轉成行內塊元素
32- 清浮動方法
-
額外標簽法
給父元素后添加塊元素,添加屬性clear:both
-
偽元素清楚法
原理和額外標簽清除一樣,只不過換成了為元素
-
給父元素設定overflow:hidden
-
給父元素設定一個高度
33- flex
單行內:
-
水平方向
justify-content : space-between
-
垂直方向
align- center
是否換行:
- flex-wrap:wrap
多行側軸:
- align-content : space - around
flex - basic 元素初始大小,優先級比width高
34- 常見的布局方式
- 流式布局(百分比布局)
- flex布局(彈性布局)
- 響應式布局
- grid布局
35-css中的1px問題
12 - 哪些操作會導致回流
- 調整窗口大小(Resizing the window)
- 改變字體(Changing the font)
- 增加或者移除樣式表(Adding or removing a stylesheet)
- 內容變化,比如用戶在input框中輸入文字(Content changes, such as a user typing text in
an input box) - 激活 CSS 偽類,比如 :hover (IE 中為兄弟結點偽類的激活)(Activation of CSS pseudo classes such as :hover (in IE the activation of the pseudo class of a sibling))
- 操作 class 屬性(Manipulating the class attribute)
- 腳本操作 DOM(A script manipulating the DOM)
- 計算 offsetWidth 和 offsetHeight 屬性(Calculating offsetWidth and offsetHeight)
- 設置 style 屬性的值 (Setting a property of the style attribute)
36- CSS實現水平垂直居中
劃重點,這是一道面試必考題,很多面試官都喜歡問這個問題,我就被問過好幾次了
要實現上圖的效果看似很簡單,實則暗藏玄機,本文總結了一下CSS實現水平垂直居中的方式大概有下面這些,本文將逐一介紹一下,我將本文整理成了一個github倉庫,歡迎大家star
僅居中元素定寬高適用
- absolute + 負margin
- absolute + margin auto
- absolute + calc
居中元素不定寬高
- absolute + transform
- lineheight
- writing-mode
- table
- css-table
- flex
- grid
absolute + 負margin
為了實現上面的效果先來做些準備工作,假設HTML代碼如下,總共兩個元素,父元素和子元素
<div class="wp"><div class="box size">123123</div>
</div>
復制代碼
wp是父元素的類名,box是子元素的類名,因為有定寬和不定寬的區別,size用來表示指定寬度,下面是所有效果都要用到的公共代碼,主要是設置顏色和寬高
注意:后面不在重復這段公共代碼,只會給出相應提示
/* 公共代碼 */
.wp {border: 1px solid red;width: 300px;height: 300px;
}.box {background: green;
}.box.size{width: 100px;height: 100px;
}
/* 公共代碼 */
復制代碼
絕對定位的百分比是相對于父元素的寬高,通過這個特性可以讓子元素的居中顯示,但絕對定位是基于子元素的左上角,期望的效果是子元素的中心居中顯示
為了修正這個問題,可以借助外邊距的負值,負的外邊距可以讓元素向相反方向定位,通過指定子元素的外邊距為子元素寬度一半的負值,就可以讓子元素居中了,css代碼如下
/* 此處引用上面的公共代碼 */
/* 此處引用上面的公共代碼 *//* 定位代碼 */
.wp {position: relative;
}
.box {position: absolute;;top: 50%;left: 50%;margin-left: -50px;margin-top: -50px;
}
復制代碼
這是我比較常用的方式,這種方式比較好理解,兼容性也很好,缺點是需要知道子元素的寬高
點擊查看完整DEMO
absolute + margin auto
這種方式也要求居中元素的寬高必須固定,HTML代碼如下
<div class="wp"><div class="box size">123123</div>
</div>
復制代碼
這種方式通過設置各個方向的距離都是0,此時再講margin設為auto,就可以在各個方向上居中了
/* 此處引用上面的公共代碼 */
/* 此處引用上面的公共代碼 *//* 定位代碼 */
.wp {position: relative;
}
.box {position: absolute;;top: 0;left: 0;right: 0;bottom: 0;margin: auto;
}
復制代碼
這種方法兼容性也很好,缺點是需要知道子元素的寬高
點擊查看完整DEMO
absolute + calc
這種方式也要求居中元素的寬高必須固定,所以我們為box增加size類,HTML代碼如下
<div class="wp"><div class="box size">123123</div>
</div>
復制代碼
感謝css3帶來了計算屬性,既然top的百分比是基于元素的左上角,那么在減去寬度的一半就好了,代碼如下
/* 此處引用上面的公共代碼 */
/* 此處引用上面的公共代碼 *//* 定位代碼 */
.wp {position: relative;
}
.box {position: absolute;;top: calc(50% - 50px);left: calc(50% - 50px);
}
復制代碼
這種方法兼容性依賴calc的兼容性,缺點是需要知道子元素的寬高
點擊查看完整DEMO
absolute + transform
還是絕對定位,但這個方法不需要子元素固定寬高,所以不再需要size類了,HTML代碼如下
<div class="wp"><div class="box">123123</div>
</div>
復制代碼
修復絕對定位的問題,還可以使用css3新增的transform,transform的translate屬性也可以設置百分比,其是相對于自身的寬和高,所以可以講translate設置為-50%,就可以做到居中了,代碼如下
/* 此處引用上面的公共代碼 */
/* 此處引用上面的公共代碼 *//* 定位代碼 */
.wp {position: relative;
}
.box {position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);
}
復制代碼
這種方法兼容性依賴translate2d的兼容性
點擊查看完整DEMO
lineheight
利用行內元素居中屬性也可以做到水平垂直居中,HTML代碼如下
<div class="wp"><div class="box">123123</div>
</div>
復制代碼
把box設置為行內元素,通過text-align
就可以做到水平居中,但很多同學可能不知道通過通過vertical-align
也可以在垂直方向做到居中,代碼如下
/* 此處引用上面的公共代碼 */
/* 此處引用上面的公共代碼 *//* 定位代碼 */
.wp {line-height: 300px;text-align: center;font-size: 0px;
}
.box {font-size: 16px;display: inline-block;vertical-align: middle;line-height: initial;text-align: left; /* 修正文字 */
}
復制代碼
這種方法需要在子元素中將文字顯示重置為想要的效果
點擊查看完整DEMO
writing-mode
很多同學一定和我一樣不知道writing-mode
屬性,感謝@張鑫旭老師的反饋,簡單來說writing-mode可以改變文字的顯示方向,比如可以通過writing-mode讓文字的顯示變為垂直方向
<div class="div1">水平方向</div>
<div class="div2">垂直方向</div>
復制代碼
.div2 {writing-mode: vertical-lr;
}
復制代碼
顯示效果如下:
水平方向
垂
直
方
向
復制代碼
更神奇的是所有水平方向上的css屬性,都會變為垂直方向上的屬性,比如text-align
,通過writing-mode
和text-align
就可以做到水平和垂直方向的居中了,只不過要稍微麻煩一點
<div class="wp"><div class="wp-inner"><div class="box">123123</div></div>
</div>
復制代碼
/* 此處引用上面的公共代碼 */
/* 此處引用上面的公共代碼 *//* 定位代碼 */
.wp {writing-mode: vertical-lr;text-align: center;
}
.wp-inner {writing-mode: horizontal-tb;display: inline-block;text-align: center;width: 100%;
}
.box {display: inline-block;margin: auto;text-align: left;
}
復制代碼
這種方法實現起來和理解起來都稍微有些復雜
點擊查看完整DEMO
table
曾經table被用來做頁面布局,現在沒人這么做了,但table也能夠實現水平垂直居中,但是會增加很多冗余代碼
<table><tbody><tr><td class="wp"><div class="box">123123</div></td></tr></tbody>
</table>
復制代碼
tabel單元格中的內容天然就是垂直居中的,只要添加一個水平居中屬性就好了
.wp {text-align: center;
}
.box {display: inline-block;
}
復制代碼
這種方法就是代碼太冗余,而且也不是table的正確用法
點擊查看完整DEMO
css-table
css新增的table屬性,可以讓我們把普通元素,變為table元素的現實效果,通過這個特性也可以實現水平垂直居中
<div class="wp"><div class="box">123123</div>
</div>
復制代碼
下面通過css屬性,可以讓div顯示的和table一樣
.wp {display: table-cell;text-align: center;vertical-align: middle;
}
.box {display: inline-block;
}
復制代碼
這種方法和table一樣的原理,但卻沒有那么多冗余代碼,兼容性也還不錯
點擊查看完整DEMO
flex
flex作為現代的布局方案,顛覆了過去的經驗,只需幾行代碼就可以優雅的做到水平垂直居中
<div class="wp"><div class="box">123123</div>
</div>
復制代碼
.wp {display: flex;justify-content: center;align-items: center;
}
復制代碼
目前在移動端已經完全可以使用flex了,PC端需要看自己業務的兼容性情況
點擊查看完整DEMO
grid
感謝@一絲姐 反饋的這個方案,css新出的網格布局,由于兼容性不太好,一直沒太關注,通過grid也可以實現水平垂直居中
<div class="wp"><div class="box">123123</div>
</div>
復制代碼
.wp {display: grid;
}
.box {align-self: center;justify-self: center;
}
復制代碼
37- 層疊上下文和層疊等級
-
層疊上下文
如果一個元素內部發生了元素層疊,則稱這個元素為層疊上下文元素。
-
在同一個層疊上下文中,層疊等級越高的,越在z軸高出顯示
-
不同層疊上下文層疊等級的比較,要先比較層疊上下文疊層等級
38- 移動端的1px
- 根據設備型號,比如375設備和750設計稿,將0.5px轉成rem
- 使用邊框圖邊
- 設置meta元屬性的視口,以方便適配手機端
39 - input寬度
并不是給所有元素設定display:block,該元素就會填充父元素寬度。input的就不會,input寬度只由size決定
js知識點
面 - js對象隱形轉成原始數據類型
- 如果對象存的是原始數據類型,那就不需要轉換了。
- 調用x.valueOf(),入股轉換成基礎數據類型,返回對應的值,
- 調用.toString(),如果轉成基礎類型,返回
- 如果都沒有返回,報錯
面 - 基礎類型使用方法
基礎類型當在調用方法的時候,瀏覽器內部會將他轉成對象,然后調用原型鏈上的方法。
調用完后,銷毀對象,轉成初始值
1.數據類型和方法
- number
- string
- boolean
- undefine
- null
- Object
- function
- Array
1-1 操作數組方法
.join() 將數組轉成字符串,用自定義的字符串分割
.push() 將數據放在最后一項,返回一個長度
.pop() 將數組最后一項移除,返回移除的值
.shift() 刪除數組第一項,返回該項
.unshift()在數組第一項加上一項/多項,返回長度
.sort() 對數組進行排序
.reverse() 反向排序數組
.concat() 合并數組
.slice( index1,index2) 數組截取,返回截取的新數組
.splice() 刪除數組項,添加數組項
indexof( ) / lastindexof()查找已知數據,返回第一次/最后一次出現的下標,沒有則返回-1
es5
.forEach() 遍歷數組,將每項交給回調處理
.map()遍歷數組,將每項交給回調處理,返回一個新函數
.filter() 返回一個數組,包含滿足回調函數條件的元素
.some() 判斷是否有元素滿足條件
.every() 判斷是否全符合條件
.find() 找到第一個滿足條件的元素
2- string對象
簡單的數據類型本身是沒有操作數據的方法的,他們只有數據,若簡單數據類型使用了屬性和方法,瀏覽器底層會將其包裝成復雜數據類型,操作結束后,又會基本包裝類型
.trim()去除字符串首位空格
.touppercase()轉大寫字母
.slice()字符串切割
.replace()字符串替換
es6
.startsWith() 是否以指定字符串開頭
.endsWith() 是否以指定字符串結尾
.includes()
2.操作符
-
typeof - typeof str 返回數據類型
檢測數據類型,基本數據類型都能識別,復雜數據類型都是object。null由于二進制的前三位和對象是一樣的,所以也被識別為object
-
instanceof
A instanceof B - 判斷B是否在A原型鏈上,返回布爾值
Object.getPrototypeOf(obj)
-
邏輯運算符
A && B 返回遇到的第一個falsely值,都是ture,返回B
A || B 返回第一個truely值
-
比較運算符
== 類型不同會隱形轉換,盡量讓他們相等
除非 == null ,其他一律用 ===
-
in 操作符
檢查該屬性是不是在原型鏈上
Object.hasOwnProperty()檢查屬性是不是在該實例上
Object.create(B) 將B添加為對象的原型
Object.keys(obj) 遍歷對象,提取key放入數組
Object.assign(target,… sources) 淺復制
-
for … of …
迭代這個對象
5.類和實例和繼承
類:是將數據和它相關的行為打包起來就稱之為類。在其他語言中,子類和父類,類和實例,都是完全不同的對象,子類將父類的成員復制過來加以處理,形成自己的屬性和方法。
原型/構造函數:這兩個概念是js里面獨有的,在js中用這兩者來模擬類的概念。構造函數中有一個屬性指向原型,原型有一個默認屬性指向構造函數,當構造函數實例化后,new強行構建了一個對象稱之為實例。實例上有構造函數執行時獲得的方法,當調用自己沒有的方法時,實例的內部[[get]]屬性會自動向對象的__proto_
屬性指向的對象中查找,這個對象就是實例。若該原型的身上也沒有該方法,【【get】】內部屬性會繼續通過–proto–找原型的原型,就這樣[[get]]持續查找的過程,直到查找到null,這中間通過–propto–屬性鏈接起來的鏈式結構,稱之為原型鏈。一些插件就是在原型上添加了相關的接口而已。
繼承:是面向對象編程的三大特征之一。就是將有著共同成員的類的成員提取出來單獨定義成一個類,若需要定義多個子類的時候,已經在父類定義好了的成員就不用重新定義了。由于js中的原型和構造函數的特殊性,有很多種繼承方式。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-XuYLpOGh-1598189226398)(C:\Users\ADMINI~1\AppData\Local\Temp\1592389657228.png)]
封裝:面向對象編程的三大特征之一。對象內部 可以定義外部訪問不到的私有屬性
多態:對象在實例化的時候,對類的方法重新賦值。就造成了一個函數名的兩種使用方式。
原型和原型鏈
- 原型:每個函數都有 prototype 屬性,該屬性指向原型對象;使用原型對象的好處是所有對象實例共享它所包含的屬性和方法。
- 原型鏈:主要解決了繼承的問題;每個對象都擁有一個原型對象,通過__proto__ 指針指向其原型對象,并從中繼承方法和屬性,同時原型對象也可能擁有原型,這樣一層一層,最終指向 null。
7. ES高級
-
解構賦值
-
計算變量
-
模板字符串
-
展開運算符
-
set對象去重
-
箭頭函數
- 箭頭函數沒有內部屬性this,只能在詞法作用域找外部的this。
- 沒有內部屬性arguments
- 沒有propertype屬性
- this無法用call等改變
-
模塊的導出和導入
es6的模塊導入是靜態導入,在導入前會先進行編譯。所以配合webpack能實現一些代碼優化。
-
promise()
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-HdAfj7bZ-1598189226399)(C:\Users\ADMINI~1\AppData\Local\Temp\1592389471451.png)]
解決異步中的回調函數問題,回調地獄。閱讀性差
promise對象內部有一個狀態機,當調用reject或者resole函數時候,狀態機的值就會改變,執行then或者catch函數。
實質上是對Generator (生成器)函數的包裝
-
async 和 await 關鍵字
async 修飾一個函數,標識這個函數異步執行。
await 會阻塞async函數的執行,直到內部 定義的一個promise對象得到成功的結果。只接收成功的結果,若防止失敗。用try/catch包裹整個await代碼
-
let/const
聲明關鍵字,會定義一個塊作用域,每次聲明都會創建一個塊作用域。
for(let i = 0 ,i < 10, i++){console.log(i) } //等同于 { let i = 0 ,log(i) } { let i = 1 ,log(i) } { let i = 2 ,log(i) } { let i = 3 ,log(i) } { let i = 4 ,log(i) } ?```
代碼執行到一塊作用域的時候,編譯器會創建詞法作用域環境,此時聲明提升。
- 編譯器遇到var關鍵字的時候,會查找該變量有沒有聲明,如果聲明了,就直接不再創建變量標識符,若沒有則創建,并自動賦值為undifine。v
- 當編譯器遇到let關鍵詞時,創建和查找過程和var一樣,和var不同的是let的詞法環境是塊作用域內。
- const關鍵詞和let差不多,只是const關鍵詞聲明的變量的內部屬性的[[write]]屬性值為false。
在let/const聲明變量后,到js引擎給變量賦值的過程,變量里面沒有保存任何數據,連undfine都沒有,這段過程稱為暫時性死區。
let/const的變量提升,最多只能提升到script作用域變量
-
迭代器
iterator是一個接口,為不同的數據提供一個訪問機制,完成遍歷操作。
數組的很多高級方法,內部都是調用了迭代里來遍歷數組,執行流程如下
- 被遍歷的對象會調用[Symbol.iterator]方法,
- 該方法返回一個迭代器對象,對象指針指向1
- 該對象可以調用next()方法,該會返回包含1號項信息的value和done屬性的對象。指針指向2
- 一直調用next()
- 直到done變成true
迭代器在es6中使用的場景很多:
- 解構賦值
- 擴展運算符
- 數組/偽數組的方法
- set對象去重
-
es6 moudle
靜態導入,編譯后才會導入數據。自動采用嚴格模式。導出的都是值的引用
import()導入會返回一個promise對象,可以通過這個進行懶加載
import(“”).then()
-
Proxy
是一個構造函數,可以生成一個攔截對象實例,訪問任何該對象的行為,都要先經過攔截對象。
我們回想一下vue 2+對數組的攔截方式,只能通過在實例和對象之間增加一個攔截原型來監聽幾個數組方法。而proxy對象是在訪問該對象之間建立了一個對象。
宏任務:主代碼。i/o,ui render
8- DOM
面 - onload 和 onDomContentLoaded的區別
1- 元素查找
找到的dom元素偽數組
2- 事件流
注冊事件
-
事件源.on事件名 = 函數
-
事件源.addEventListener( “事件名”,事件處理函數,布爾值 )
有兼容性,通過布爾值控制事件處理函數的觸發時機,true在捕獲階段執行
移除事件
- 事件源.on事件名 = null
- 事件源.removeEventListener( “事件名”,事件處理函數 )
3- 事件對象
在事件觸發后,會創建一個事件對象,存入事件相關信息。
瀏覽器自動將事件對象,存入事件處理函數中,只要在事件處理函數接收就好了
event.target 注冊和綁定事件的對象
event.currentTarget 觸發點擊的對象
event.perventDefault()阻止對象默認行為
event.stopPropagation()阻止事件流傳遞
9- BOM
Location對象
包含了網站的url信息和操作
History對象
存儲瀏覽器的歷史記錄
Navigation對象
存儲了客戶端的信息
window對象
offsetWIdth : 當前元素信息
clientwidth:當前元素可視區信息
scroll 滾動條信息
移動端dom
touch相關事件。click事件會有300ms延遲
事件對象:
e.touches: 屏幕上所有觸點
10- js的執行機制
10-1 編譯過程
-
階段一:詞法分析階段
將代碼拆分成token詞法單元塊
-
階段二: 語法分析
將token轉成AST(抽象語法樹)
-
階段三:代碼生成
AST 轉譯成機器碼
作用域就是收集和維護所有聲明標識符的超集
10-2 代碼執行過程
-
編譯器聲明代碼,在詞法作用域內查找是否有變量標記符,若沒有,則在該作用域創建該標識符
聲明提升,預解析過程
- 聲明多個函數,后面覆蓋前面的
- 聲明同名函數和變量,函數生效
-
js引擎執行代碼的時候,會在當前詞法作用域查找有沒有a,若有直接操作數據,沒有繼續向上查找
LHS查詢被賦值的變量,RHS查詢查找變量
10-3 詞法作用域/函數作用域/塊作用域和閉包
作用域:就是一個變量的合法使用范圍。在這個范圍內,RHS能查詢到該變量
詞法作用域是詞法分析過程就定下來了作用域,而閉包就是指函數在執行的時候,能夠訪問聲明時候所在的詞法作用域,此時就產生了閉包。
閉包可以用來保護數據,模塊導入,防抖節流
10-4 預解析
10-5 this
this指向函數調用的 執行環境對象,所以this的綁定決定于函數的調用方式,可以通過函數調用棧查找
-
函數自調用
this指向全局對象
-
對象調用
this指向該對象
-
call()/apply()/bind()直接綁定
-
new綁定
-
特殊調用
- 定時器中的函數屬于函數自調用
函數發生賦值傳遞時候,原this指向會丟失
面 - 手寫new
- 創建一個新對象,繼承構造函數的原型
- 考慮參數
- 綁定this指向
function newOperator(ctor){if(typeof ctor !== 'function'){throw 'newOperator function the first param must be a function';}// ES6 new.target 是指向構造函數newOperator.target = ctor;// 1.創建一個全新的對象,// 2.并且執行[[Prototype]]鏈接// 4.通過`new`創建的每個對象將最終被`[[Prototype]]`鏈接到這個函數的`prototype`對象上。var newObj = Object.create(ctor.prototype);// ES5 arguments轉成數組 當然也可以用ES6 [...arguments], Aarry.from(arguments);// 除去ctor構造函數的其余參數var argsArr = [].slice.call(arguments, 1);// 3.生成的新對象會綁定到函數調用的`this`。// 獲取到ctor函數返回結果var ctorReturnResult = ctor.apply(newObj, argsArr);// 小結4 中這些類型中合并起來只有Object和Function兩種類型 typeof null 也是'object'所以要不等于null,排除nullvar isObject = typeof ctorReturnResult === 'object' && ctorReturnResult !== null;var isFunction = typeof ctorReturnResult === 'function';if(isObject || isFunction){return ctorReturnResult;}// 5.如果函數沒有返回對象類型`Object`(包含`Functoin`, `Array`, `Date`, `RegExg`, `Error`),那么`new`表達式中的函數調用會自動返回這個新的對象。return newObj;
}
面 - 手寫call()
//手寫一個call Object.prototype.myCall = function (obj, str) {obj.xxx = this // this是指向函數obj.xxx(str)}dog.say.myCall(cat, '我是')
get和post 的區別
GET比POST更不安全,因為參數直接暴露在URL上,所以不能用來傳遞敏感信息。
GET參數通過URL傳遞,POST放在Request body中。
GET請求參數會被完整保留在瀏覽器歷史記錄里,而POST中的參數不會被保留
GET 請求可被收藏為書簽 ,POST 不能被收藏為書簽
GET請求只能進行url編碼,而POST支持多種編碼方式。
GET 請求可被緩存 POST 請求不會被緩存
GET 請求有長度限制,POST 請求對數據長度沒有要求
面試題
3.防抖和節流的區別是什么?怎么實現?
- 防抖:觸發事件的n秒后執行對應函數,若n秒內事件再次被觸發,那么時間將重新計算。
function debounce(fn, time) {let timer = null; // 定時器IDreturn function() {clearTimeout(timer); // 觸發事件時將上一次的定時器清除掉timer = setTimeout(() => { // 創建一個新的定時器,只有在一定時間后會執行fn.apply(this, arguments);}, time);}}
復制代碼
- 節流:觸發事件后,會先判斷n秒內是否執行了函數,未執行時才會去執行。
function throttle(fn, time) {let isRun = false; // 定義一個當前事件內是否執行了函數的變量return function () {if (isRun) return; // 如果當前時間內函數執行了,則直接returnisRun = true; // 沒執行,則將其設置為truesetTimeout(() => { // 創建一個定時器在n秒后執行函數,并把isRun賦值為falsefn.apply(this, arguments);isRun = false;}, time);}}
復制代碼
4.深拷貝和淺拷貝有什么區別?你能實現一個深拷貝嗎?
- 淺拷貝只能復制對象的第一層,當對象的屬性還是引用類型的時候,則只會復制其引用地址,當值被修改以后所有的引用的值都會改變。
- 賦值拷貝
- Object.assign
- 擴展運算符
- 深拷貝則是解決淺拷貝存在的無法深入拷貝復雜類型
- JSON對象的parse和stringify
- 可以滿足基本的深拷貝需求,能夠處理所有能用json格式標識的所有數據類型。但是對于正則表達式和函數類型無法進行深拷貝,會丟失很多信息。也會拋棄對象的chonstructor
- 遞歸函數
- JSON對象的parse和stringify
淺拷貝實現 , 只拷貝當前基本屬性的值,不會拷貝復雜屬性的值 ,俗稱:只拷貝地址,不拷貝內容
var a = function(obj) {// 只拷貝對象if (typeof obj !== 'object') return;// 根據obj的類型判斷是新建一個數組還是對象var newObj = obj instanceof Array ? [] : {};// 遍歷obj,并且判斷是obj的屬性才拷貝for (var key in obj) {//查找當前對象是否有這個屬性if (obj.hasOwnProperty(key)) {newObj[key] = obj[key];}}return newObj;}
深拷貝實現 拷貝當前的值,復雜屬性也一并拿來,拷貝全部屬性值,換個地址而已
var c = {name:'wangyu',yu:{age: 18}}function a(obj) {var newobj = null;if(typeof obj == 'object' && obj !== null){newobj = obj instanceof Array ? [] : {};for(var key in obj){newobj[key] = a(obj[key]) }return newobj;}else{return newobj = obj}}var qwe = a(c)qwe.ewq = 20;console.log(qwe);console.log(c);
7.在ES5中比較常見的繼承方式有哪些?
8.實現一個new函數
function _new(Fn,...arg) {// 必須為一個函數且不能為箭頭函數if(typeof Fn !== "function" || !Fn.prototype) throw Error(`Fn is not a constructor`);// 將新對象的隱式原型賦值為構造函數的prototype,obj.__proto__ = Fn.prototypeconst obj = Object.create(Fn.prototype);// 改變Fn的執行作用域,并傳入相應的參數const isRet = Fn.call(obj, ...arg);// 判斷構造函數本身是否返回一個objectreturn isRet instanceof Object ? isRet : obj;}
復制代碼
9.箭頭函數和普通函數的區別是什么?
- 自身無this,其this繼承上一級,所以無法使用call、apply、bind綁定this
- 自身無 arguments 對象,會通過作用域鏈向上查找
- 不能用作 Generator 函數。
- 沒有prototype屬性,所以無法用new關鍵字調用
10.實現一個promise
我當時實現的是非常低配的promise,代碼就不貼了,推薦坤坤大佬的promise實現
11.promise、async/await、setTimeout的區別是什么?
首先,js的事件循環分為宏任務和微任務,而當前執行棧的執行順序為同步代碼 -> 微任務中的代碼 -> 宏任務中的代碼。
- promise:promise函數本身是同步執行的,只有其then或者catch等方法是異步執行的并且其回調函數會被放在事件循環中的微任務隊列,讓同步代碼先執行。
- async/await:當一個函數被添加async關鍵字的時候表明當前函數中可能會有異步方法,await關鍵字只能在async函數中使用并且后面跟一個表達式,在async函數中遇見await關鍵字時會同步執行后面的表達式并將表達式后面的代碼放入微任務隊列,讓同步代碼先執行。
- setTimeout/setInterval:定時器中的回調函數會被放在宏任務隊列,等同步代碼和微任務隊列中的代碼執行完畢后執行
vue知識點
面- 介紹一下什么是SSR
SSR 又稱服務端渲染,底層實現邏輯有點像同構。大概的一個流程時在服務端運行一遍代碼后,拿到html文件,將其
- 客戶端渲染的問題
- 在客戶端渲染時,會先加載html,解析html后,再請求一次JavaScript文件,渲染生成頁面。首屏加載事件慢,甚至出現白屏。
- 客戶端渲染的seo能力很弱。搜索引擎的識別內容主要還是html文件。
- ssr解決方式:ssr技術會讓框架代碼現在服務端執行一遍,用戶第一次請求的時候已經獲得了完整的html文件,節省了一個周期的http請求時間。也利于seo。在客戶端再執行一遍代碼后,又給了靜態html交互的能力。
- 缺陷:ssr技術讓原本簡單的項目執行起來十分復雜,項目的可維護性降低,debugger變得復雜。所以如果項目對首屏加載速度和seo需求不是那么大,盡量不適用ssr
面-vue的跨平臺是如何做到的
虛擬dom本質上就是一個js對象,實際開發中,都是對這個對象進行操作。跨平臺只要在vue的適配層添加響應的適配代碼,根據不同的平臺做出不同的對外接口。
面 - 文件上傳的幾種方式,聊聊大文件上傳
1.普通上傳方式
將文件進行編碼后上傳,然后服務端解碼 - 圖片轉base64上傳
但是轉換后的代碼往往比源文件更大,所以只適合傳遞一些小文件
使用formdata對象上傳文件。而且formdata可以直接整合表單信息統一上傳。只是使用不靈活,
將整個請求完全交給瀏覽器,或許會出現請求超時
2.大文件上傳
? 主要問題在于:大文件上傳的時候,花費時間太長,如果發送失敗,必須從頭再來
切片上傳
通過編碼方式上傳文件,通過slice方法對文件二進制內容進行切片處理,給每一個切片添加序號。服務端就可以還原切片了
斷點續傳
在上傳一個文件的時候,如果出現意外,上傳失敗,下次上傳時候,可以接著進度上傳文件。可以通過xhr對象的方法檢測文件時上傳的進度,將其保存在本地,下載上傳的時候從本地存儲獲得進度,重新開始上傳
進度暫停和停止
可以通過xhr上的方法對文件上傳進行一個暫停和繼續
面 - 組件設計和狀態設計
根據組件功能分析,設計適合這個組件的狀態
- 狀態設計
- 要用狀態描述所有內容
- 數據要結構化,易于代碼執行操作,適配組件使用
- 數據結構要是可拓展性的,比如數組和對象
- 切莫嵌套太深,遍歷影響性能
- 組件設計
- 從功能層次拆分代碼
- 盡量讓組件原子化,一個組件負責一個功能,然后根據需求自由組合
- 區分容器組件(只負責數據,一般是頂層組件)和視圖組件(只顯示視圖和用戶交互)
設計步驟:
- 分析頁面的功能,然后根據功能逐步拆分成組件
- 分析頁面的組件的數據流,決定好數據結構和容器組件
1-vue的使用
1-1 插值表達式
插值表達式中只能訪問data數據和部分全局變量,如Math,Date
1-2 指令
vue指令是vue框架對于一些操作的封裝,在模板編譯的時候,會解析成相對應的js代碼執行,通過:接收參數,通過.添加修飾符,以完成不同 的操作。
常傳的參數有:v-bind的屬性名
常用的修飾符有:
-
處理數據修飾符
- .lazy懶同步,
- .number 數據轉成數字類型同步到后臺。
- .trim()去掉首尾空白。
- .once()
-
事件修飾符
- .stop() 阻止事件冒泡
- .prevent()阻止默認行為
- .once()事件只觸發一次
- .self() 只能在自身觸發,不能事件委托
- .capture()在捕獲階段觸發
-
按鍵修飾符
- .鍵盤碼
- .鍵盤別名
-
v-model
只是一個語法糖,內部封裝了針對該元素的事件和屬性的綁定。可以通過自定義model,完成很多操作,比如組件之間更方便的傳值。
-
v-if 和 v-show
v-if底層是通過js判斷改向vnode添加哪項節點,所以如果沒有符合要求,該元素直接不會渲染。
v-show則是操作該元素的diaplay屬性。
看情況使用兩者
-
v-for 和 v-if
v-for 底層和react的列表渲染原理很像,遍歷該數據,將該數據每一項轉成一個有結構的數據類型,可以說是虛擬dom結構吧。。不能再同一個標簽是同時使用這兩個,v-for的優先級更高,
-
v-once
只解析一次
1-3計算屬性 和 過濾器 和 監聽屬性
計算屬性 - 多個數據影響一個數據
計算屬性實質上,是對插值表達式的一個優化方案。將過重的插值表達式邏輯掛載在實例上,但是存在作用域問題。所以出現了過濾器。
而且計算屬性對于某個計算結果,會進行緩存,若數據沒有變化,多次計算直接返回緩存的值。同時對該數據設置setter和getter,當該數據發生變化時,計算屬性能夠檢測到再重新計算。倘若長時間不調用計算屬性,則緩存的空間會被釋放。
-
初始化的時候
計算屬性不會求值,然后當我們的 render 函數執行訪問到 computed相關依賴 的時候,就觸發了計算屬性的 getter,它會拿到計算屬性對應的 watcher,然后執行 watcher.depend(),然后再去求值。
-
初始化過后
當computed的依賴發生變化的時候,就觸發了計算屬性的 getter,通知所有訂閱它變化的 watcher 更新,執行 watcher.update() 方法。如果頁面中沒有訂閱computed的變化,就不會求值,當下次再訪問這個計算屬性的時候才會重新求值。
我們要記住這一點,不僅僅是計算屬性依賴的值發生變化,而是當計算屬性最終計算的值發生變化才會觸發渲染 watcher 重新渲染。
監聽屬性 - 一個數據影響多個數據
監聽屬性,則是對data中的數據,設置了監聽,當數據變化的時候,執行對應的函數,必要的時候還要開啟深度監聽,由于深度監聽是遞歸監聽到底,所以這個方法十分消耗性能,要謹慎使用。需要執行異步操作或者一些開銷比較大的操作時候,監聽屬性更實用
計算屬性其實和監聽屬性實現原理方面都是差不多的,vue的data掛載在實例上的時候,當數據變化后,先調用watcher觀察者模式。然后調用計算屬性和觀察屬性
每個的使用場景
watch 屬性:適用于觀測某個值的變化去完成一段復雜的業務邏輯。
computed 屬性適合:用在模板渲染中,某個值是依賴了其它的響應式對象甚至是計算屬性計算而來如果是一個屬性,依賴多個屬性變化的時候。當數據監聽
過濾器:需要對全局數據進行某種操作的時候
1-4 生命周期
生命周期這個概念其實很抽象,我更原理理解為在組件某個階段鉤子函數的觸發。
- 初始化階段:將data數據掛載到vm實例中,對數據進行數據劫持。
-
beforeCreated 函數 - 是new Vue()后,觸發的第一個鉤子,當前所有的數據都不能訪問
掛載vue-router / vuex
-
created函數 - 實例創建完成后,此時可以使用數據/但無法操作dom,除非使用$nextTick.
-
找html中的掛載節點,通過el屬性或者手動$mount()設置
-
找用于渲染的模板
-
beforeMount - 掛載之前,此時模板已經導入渲染函數編譯。虛擬dom已經創建完成。此時也可以對數據進行更改,不會觸發update。
-
mounted函數,dom完成更新.完成數據雙向綁定。可以用$ref獲取dom
-
- 更新階段:當data中依賴項使用的數據發生變化的時候,開始更新階段
- beforeUpdate 函數 - 響應式數據發生更新,虛擬dom重新渲染前觸發,此時修改數據,不會觸發重渲染。
- update函數 : 通過虛擬dom進行diff算法對比,通過patch算法對新dom樹進行操作,然后渲染出來
- 銷毀階段:從視圖中銷毀dom,釋放子組件,事件監聽器等資源,若組件銷毀后,對應的事件沒有銷毀,會報錯
- beforeDestroy 函數:實例銷毀之前,此時還能操作實例
- destroyed函數:組件銷毀完成
1-5 事件監聽器
我們可以用$emit定義事件,可以被事件監聽器監聽到,事件監聽函數甚至可以監聽生命周期函數
- $on - 持續監聽事件
- $once - 只監聽一次事件
- $off - 停止監聽事件
1-6 內置組件
<component />
<transition />
<Keep - alive />
<slot/>
2-vue高級特性
2-1 .$nextTick
vue在數據改變后,會對dom進行相對于的更新,而nextTick是在dom更新完成后觸發的函數。處于減少dom操作次數的性能優化考慮,在一個宏任務里面的只要監聽到了數據變化,vue會開啟一個隊列,并緩沖在這次宏任務中的所有數據變更,都會在最后整合成一次數據變化,達到重復數據修改的去重操作。然后更新虛擬dom,此時nextTick是在dom更新完成后觸發的函數。處于減少dom操作次數的性能優化考慮,在一個宏任務里面的只要監聽到了數據變化,vue會開啟一個隊列,并緩沖在這次宏任務中的所有數據變更,都會在最后整合成一次數據變化,達到重復數據修改的去重操作。然后更新虛擬dom,此時nextTick是在dom更新完成后觸發的函數。處于減少dom操作次數的性能優化考慮,在一個宏任務里面的只要監聽到了數據變化,vue會開啟一個隊列,并緩沖在這次宏任務中的所有數據變更,都會在最后整合成一次數據變化,達到重復數據修改的去重操作。然后更新虛擬dom,此時nextTick函數觸發。所以一方面,我們的數據修改不能依賴上一個數據修改的值,另一方面,想要操作數據修改后的dom,要通過$nextTick函數好
原理:vue會根據當前瀏覽器環境,優先使用promise.then()和mutationObserver,如果不支持用settimeout代替
2-2 組件的name屬性 - 遞歸組件
可以自己將自己注冊成自己的子組件,用name屬性調用,達到組件遞歸的效果。用v-if結束遞歸。
2-3 組件通信
vue組件之間是封閉的,不能互相訪問數據,要想傳輸數據必須通過傳遞屬性的方式傳遞。由于單項數據流,父組件數據更新時候,子組件接收的數據自動更新,而且父組件的傳遞的數據,只能父組件自己來修改。
- 父子:props,parent/parent/parent/children , provide / inject , ref , $attrs / $listeners
- provide / inject 注入依賴,在祖先組件中向后代組件注入數據,無論層級多深,子組件總能訪問到該數據,在組件封裝的時候,還是很好用的
- 兄弟組件:evenBus , vuex
- 跨級通信:evenBus , vuex , provide / inject , $attr / $listeners
面–父傳子的生命周期
父組件給子組件傳遞數據的時候,
父組件開始更新 - 子組件1開始更新 - 子組件1更新完成- 子組件2開始更新 - 子組件2更新完成 - 父組件更新完成
面–父組件監聽子組件的生命周期
方法1- 父組件向子組件傳遞一個函數,props值為生命周期函數名,子組件通過$emit()提交相應的生命周期函數
// Parent.vue
<Child @mounted=“doSomething”/>// Child.vue
mounted() {
this.$emit(“mounted”);
}
復制代碼
復制代碼方法2- 在父組件引用子組件時通過 @hook 來監聽即可,如下所示:
// Parent.vue <Child @hook:mounted="doSomething" ></Child>doSomething() {console.log('父組件監聽到 mounted 鉤子函數 ...'); },// Child.vue mounted(){console.log('子組件觸發 mounted 鉤子函數 ...'); }, // 以上輸出順序為: // 子組件觸發 mounted 鉤子函數 ... // 父組件監聽到 mounted 鉤子函數 ... 復制代碼 復制代碼
當然 @hook 方法不僅僅是可以監聽 mounted,其它的生命周期事件,例如:created,updated 等都可以監聽。
2-3 slot插槽
插槽在我看來也是只是定制化組件時,讓組件通信之間能夠實現標簽傳遞,提高組件的復用性和個性化。
根據使用方式不同分為匿名插槽,具名插槽和作用域插槽。
作用域插槽能根據子組件數據來定制化數據
面- 如何在vue中提取可復用的組件
一般我們在開發的時候,如果遇到組件在能在多處使用,或者多個組件需要使用同于一套處理邏輯。我們會考慮將其抽離提取成一個可復用的組件。
復用組件的三個核心api
- prop:接收外部組件傳遞的數據,定制化可復用的組件
- emit:可以提交觸發事件函數
- slot:在可復用組件內根據外部組件傳入的數據,定制化可復用的組件
2-4 動態組件
動態組件時根據條件的改變來操作組件的渲染情況,常見于is和v-for
<component :is = "組件名" /> //通過is來控制組件渲染// is屬性配合v-for可以實現用動態組件通過數據結構來實現頁面展示data:{0:{type:'text',msg:"1111"},1:{type:'img',msg:"2222"},2:{type:'text',msg:"333"}}<div v-for = "(val,key) in data">//根據數據結構的不同,展示不同的組件。<component :is = " value.type === 'text' ? 'textComponent' : 'imgComponent' "/></div>
2-5 異步組件
異步組件主要是針對大組件的加載較慢的問題,讓他按需引入。如果不使用這個組件,則永遠不加載。
在路由中:component:()=>{return ‘組件地址’}
在組件注冊時候,組件地址寫成:component:()=>{return ‘組件地址’}
2-6 緩存組件 keep - alive
keep- alive組件包裹組件是,若組件反復切換時候,組件的狀態會被緩存下來。
沒有緩存的組件每次切換展示的生命周期:mouted - destroy
緩存的組件每次切換展示的生命周期:只有第一次加載的時候會出現mouted,切換時,不會出現destroy
2-7 mixin
mixin挺像react里面的高級組件。將組件相同邏輯的內容抽離出來放置到一個配置對象里面。誰需要這個配置,就用mixin混入該配置選項。
mixin類似于extend繼承方法,都是抽離出一個組件配置對象,然后混入,extend的先執行,extend的組件就叫做繼承組件
問題:
1.mixin閱讀不明確
2.多mixin會有沖突
3.mixin和組件之間存在多對多的關系,邏輯混亂
2-8 自定義指令
通過控制5個鉤子函數來實現自定義指令
3-vue底層原理
3-1組件化(vue核心)
組件化并不是一個新鮮的詞,前端的組件化是從后端發展過來,加以進化的。后端組件化,也能給組件注入數據,但是沒辦法做到通過參數定制組件。前端可以通過數據驅動視圖來更好的控制和維護組件。
其中vue數據驅動視圖的原理就是MVVM。
面–說說組件化工程化和模塊化
- 工程化 將項目進行分析構建,達到開發的時候文件結構清晰,分工明確,提高開發效率的目的
- 組件化: 根據業務邏輯的不同,將重復的代碼提取出來,合并成一個組件,在需要的使用該功能的地方使用該組件。側重于業務的解耦。
- 模塊化: 將分屬于同一功能/業務的代碼,單獨封裝成獨立的模塊,可以獨立運行。在業務的框架層面來通過接口互相調用。降低業務模塊之間的耦合。
相互之間的關系,組件化和模塊化時工程化的具體體現,而組件往往用于模塊中,處理業務模塊的功能需求
3-2響應式(
響應式驅動時建立在object.defineProperty()和寄存器getter和setter方法實現的一直設計模型,這個設計模型里面有觀察者和訂閱者模式,這個設計模型的核心機制和vm模塊
- 監聽對象(Obeserver ,dep , watcher)
- 通過Observer給data中的每個屬性轉換成getter和setter的形式。object.defineProperty()
- 當視圖元素通過觸發watcher來向data里面獲取數據,該元素就會被收集到getter里面的依賴項列表中。
- 當數據發生變化的時候,setter會監聽到,遍歷getter里面的依賴項列表,通過watcher來逐個通知依賴項更新數據
- 遞歸深度監聽對象屬性,遞歸到底,浪費性能
- 新增的數據,無法監聽
- 監聽數組
- 數組無法直接監聽數據本身,因為數組是通過方法來改變數組的內容,所以我們只能監聽操作數組的方法,來達到數組的數據的監聽。
- 操作數據的方法基本都在數組原型上面,為了不污染全局數組原型,可以用object.creted()在數組實例和原型之間設置一個攔截器。監聽攔截器里面的方法。
- 數組操作數據后,本身沒有該方法,就順著原型鏈往上查找,在找到數組原型之前,就在攔截器上找到了該方法。
- 攔截器上的方法一旦被使用,就會將這個依賴收集起來。
- 一旦數組數據變化,通知所以依賴項
- 只能監聽數組的部分方法。
3-3 vdom 和 diff
-
虛擬Dom
由于原生的命令式dom操作十分消耗性能且不容易維護,vue是數據驅動視圖,采用了vdom,js用樹狀對象來模擬dom的結構中的關鍵節點。將dom操作的計算放到js計算中。數據發生改變的時候,js計算出新舊dom的最小變更,然后一次性操作dom。這樣會很大程度節省性能。
<div className = "father">我是div<li> 我是li標簽</li> </div>const vDom = {tag:"div",props:{//屬性對象className :"father"},children:["我是div",{tag:"li",props:[],children:['我是li標簽']}] }
-
diff算法
diff算法用于在數據改變后,比較新舊vdom的數據結構,找出兩個數據不同的地方,然后更新改變的節點。由于樹數據結構的diff算法時間復雜度是O(n^3),所以vue里面的diff算法有三個規則:
- 只比較同一級別的節點,不跨級比較
- tag屬性一旦不同,直接刪除重建,不再深入比較
- tag和key相同時,直接認為時相同節點,不再深度比較,也不會動他。
-
vdom操作流程
模板標簽 => h 函數 (創建虛擬dom)=> vnode函數 => vnode =>patch 函數(對比新舊dom) => 渲染頁面
addvnodes函數 removenode函數
面- 為何要加上key
在進行diff算法的時候,能夠快速標記不用遍歷檢查的vnode,減少性能消耗。在增刪節點的時候,key能幫diff算法更加精準的定位要需要更新的位置。
3-4 模板編譯
將vue模板轉成能在js中操作的代碼,js即可執行模板中的插值表達式,指令。
內部實現流程:
-
將模板解析成AST (解析器)
遍歷整個模板,找到html標簽,標記{{}}插值表達式
-
遍歷AST找到{{}}插值表達式 (優化器)
標記解析{{}}插值表達式語法
-
生成渲染函數 (代碼生成器)
解析完{{}}插值表達式生成渲染函數
渲染函數核心語法是
with
語法。包含插值表達式的表達式,可以直接訪問data中的數據。<div v-if = " flag === true ">我是div標簽 </div> //渲染函數 with(this){ //vm實例,每一個插值表達式都通過這樣的形式訪問vm數據return creatElement ('div'),[flag === true ? '我是div標簽',' ' ] // 內部可以直接訪問data中的數據 }
-
執行渲染函數,得到vnode
-
將vnode傳入patch函數,將vnode渲染到dom節點中。
注:webpack使用vue-loader的時候,會自動編譯模板。若沒有提前編譯,就要在瀏覽器中編譯
3-5 組件更新 和 渲染過程
模板 => 模板編譯 => 渲染函數 => vnode => 渲染頁面
- 初次渲染流程
- 將模板解析為渲染函數
- 響應式系統收集數據依賴項
- 執行render函數,生成vnode
- 執行patch函數,渲染頁面
- 更新階段流程
- data數據變化觸發setter
- 重新執行render函數,生成新的vnode
- patch函數對比新舊vnode,渲染
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-7QFy0p5H-1598189226402)(C:\Users\ADMINI~1\AppData\Local\Temp\1591669577786.png)]
3-6 前端路由原理
vue路由是為了實現SPA(單頁應用),vue是單頁應用,所以當我們在頁面進行一些操作改變路由的變化是,是不會向服務器發送請求的,瀏覽器監聽到url的變化,從而更新頁面。 有兩種模式:
兩種模式都是返回單頁面應用,只是地址欄顯示不一樣。
1、hash 例如 juejin.im/#/index 多用于to B 業務的后臺管理系統
hash模式是用window.hashchange的方法監聽url,當URL的hash部分改變時,頁面不會重新加載。并且向服務端發送的請求是https://juejin.im/部分
注意: 頁面刷新的時候,不會向服務器發送請求
2、history 例如 [juejin.im/index 多用于toC的業務模式
history模式充分利用 history.pushStateAPI來完成URL跳轉而無須重新加載頁面。主要使用 history.pushState、history.popState和history.replaceState改變URL。使用history模式,我們需要在路由里面加這行代碼mode:history,然后需要后端配置一個覆蓋所有情況的候選資源:如果URL匹配不到任何靜態資源,則應該返回同一個index.html頁面,這個頁面就是你 app 依賴的頁面。
router.push、 router.replace 和 router.go 跟 window.history.pushState、 window.history.replaceState 和 window.history.go好像, 實際上它們確實是效仿 window.history API 的。
注意: 頁面刷新的時候,會向服務器發送請求,而用此時的url向地址發送請求時,后來需要處理url返回根頁面。
面- 如何實現vue-router切換頁面后,保持在頁面頂部/保持原先位置不變
vue-router提供了一個scrollBehavior,在切換路由額時候,可以控制頁面是滾到底部還是保持原先位置。只在history模式下可以用。
4-相關插件
4-1 axios工具包
基于promise的http庫,底層依賴是XMLHttpRequest
發送ajax的工具包,底層實際上是使用了promise異步實現的。
面–axios如何解決跨域問題?
axios不支持jsonp跨域,
針對后臺不支持options,要么讓后臺使用cors插件,要我么自己寫一個后臺,進行反向代理
- 請求攔截器,統一處理axios的請求后,發送請求
- 響應攔截器,拿到響應數據后,先處理一遍
4-2 vuex
Vuex 是一個專為 Vue.js 應用程序開發的狀態管理模式。每一個 Vuex 應用的核心就是 store(倉庫)。“store” 基本上就是一個容器,它包含著你的應用中大部分的狀態 ( state )。
(1)Vuex 的狀態存儲是響應式的。當 Vue 組件從 store 中讀取狀態的時候,若 store 中的狀態發生變化,那么相應的組件也會相應地得到高效更新。
(2)改變 store 中的狀態的唯一途徑就是顯式地提交 (commit) mutation。這樣使得我們可以方便地跟蹤每一個狀態的變化。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-WUv4SEc5-1598189226402)(C:\Users\ADMINI~1\AppData\Local\Temp\1591768522198.png)]
核心
- state 為單一狀態樹,在state中需要定義我們所需要管理的數組、對象、字符串等等
- getters 類似vue的計算屬性,主要用來過濾一些數據。
- mutation 更改store中state狀態的唯一方法就是提交mutation,store.commit。
- action actions可以理解為通過將mutations里面處里數據的方法變成可異步的處理數據的方法,簡單的說就是異步操作數據。view 層通過 store.dispath 來分發 action。
- module module其實只是解決了當state中很復雜臃腫的時候,module可以將store分割成模塊,每個模塊中擁有自己的state、mutation、action和getter。
面-- 頁面刷新的時候數據丟失
- 使用本地存儲vuex數據
- 使用插件
面 - vuex實現雙向綁定
如果直接同時使用v-model綁定vuex中的數據,數據修改時會報錯,因為state中的數據不是經過mutation修改的。
- 使用設有setter的計算屬性綁定v-model,計算屬性內部調用mutation方法
- 手動綁定state的值在value身上,然后監聽事件,事件回調函數使用mutation的值修改state
4-3 vue-router
1-使用步驟
- 準備好路由組件
- 定制路由規則
- 掛載路由規則到組件上
2- 編程式導航
通過調用函數將hash值調入history棧中,用戶后退也鞥返回。聲明式導航內部調用了history棧
3-路由元信息
可以在路由跳轉的時候存儲信息
4-導航跳轉流程
- 導航觸發
- 在失活的組件中調用離開守衛
- 調用全局前置守衛(判斷是否允許該用戶訪問前往的網頁)
- 調用重用組件內的組件更新守衛
- 在路由配置中調用組件
- 解析異步路由
- 全局解析守衛
- 導航被確認
- afterEach函數調用
- dom更新
5- 獲取路由跳轉的信息
this.$route.query
this.$route.params
面 - 如何監聽路由參數的變化
- 使用watch屬性來監聽hash值的變化
- 使用beforeRouteUpdate守衛
面 - 使用動態路由切換時候,組件沒有變化,不會觸發生命周期函數
- watch url的變化
- 為router - view 添加唯一的key為路由地址
面 - 實現路由解耦
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-wsWEtTel-1598189226403)(C:\Users\ADMINI~1\AppData\Local\Temp\1591668715781.png)]
4-4 vue-loader
作用:1.vue-loader是webpage里面的一個加載器,主要用于解析提取vue文件里面的代碼,比如邏輯代碼js,樣式代碼style,已經html模板,再將他們交給對應的loader去處理。
2.提前對html模板進行模板編譯
5- vue的性能優化
5-1 代碼層面的優化
-
v-if 和 v-show 區分使用場景
-
computed 和 watch 區分使用場景
-
v-for 遍歷必須為 item 添加 key,且避免同時使用 v-if
-
長列表性能優化
-
事件的銷毀
-
圖片資源懶加載
-
路由懶加載
-
第三方插件的按需引入
-
優化無限列表性能
-
服務端渲染 SSR or 預渲染
5-2 Webpack 層面的優化
- Webpack 對圖片進行壓縮
- 減少 ES6 轉為 ES5 的冗余代碼
- 提取公共代碼
- 模板預編譯
- 提取組件的 CSS
- 優化 SourceMap
- 構建結果輸出分析
- Vue 項目的編譯優化
5-3 基礎的 Web 技術的優化
- 開啟 gzip 壓縮
- 瀏覽器緩存
- CDN 的使用
- 使用 Chrome Performance 查找性能瓶頸
面- vue如何優化首屏加載速度
首屏加載數據,是指瀏覽器剛打開頁面時候,出現的內容
- 使用CDN資源,減小服務器帶寬壓力
- 路由懶加載
- 將一些靜態js css放到其他地方(如OSS),減小服務器壓力
- 按需加載三方資源,如iview,建議按需引入iview中的組件
- 使用nginx開啟gzip減小網絡傳輸的流量大小
- 若首屏為登錄頁,可以做成多入口,登錄頁單獨分離為一個入口
- 使用uglifyjs-webpack-plugin插件代替webpack自帶UglifyJsPlugin插件
使用CDN資源,減小服務器帶寬壓力
- 在index.html中引入cdn資源
...<body><div id="app"></div><!-- built files will be auto injected --><script src="https://cdn.bootcss.com/vue/2.5.2/vue.min.js"></script><script src="https://cdn.bootcss.com/vue-router/3.0.1/vue-router.min.js"></script><script src="https://cdn.bootcss.com/vuex/3.0.1/vuex.min.js"></script><script src="https://cdn.bootcss.com/vue-resource/1.5.1/vue-resource.min.js"></script></body>...
- 修改 build/webpack.base.conf.js
module.exports = {context: path.resolve(__dirname, '../'),entry: {app: './src/main.js'},externals:{'vue': 'Vue','vue-router': 'VueRouter','vuex':'Vuex','vue-resource': 'VueResource'},... }
- 修改src/main.js src/router/index.js 注釋掉import引入的vue,vue-resource
// import Vue from 'vue' // import VueResource from 'vue-resource' // Vue.use(VueResource)
路由懶加載
require.ensure方式
const workCircle = r => require.ensure([], () => r(require('@/module/work-circle/Index')), 'workCircle') const workCircleList = r => require.ensure([], () => r(require('@/module/work-circle/page/List')), 'workCircleList')
import方式
const workCircle = () => import('@/module/work-circle/Index')
將一些靜態js css放到其他地方(如OSS),減小服務器壓力
注意這里的js文件,需要將結果拋出,然后在需要用到該js的組件中import引入
按需加載三方資源,如iview,建議按需引入iview中的組件
按需引用請查看iview官方文檔iview
*使用nginx開啟gzip減小網絡傳輸的流量大小
React 知識點
1- react的使用
1-1 創建react元素的方式
- react.creatElement(標簽名/組件名,屬性對象,子元素 …)
- jsx語法(內部轉換成React.creatElement())
1-2 jsx{ }嵌入式表達式
在jsx格式中,{}里面的內容會動態解析,由js執行。
1-3 條件渲染
react中的條件渲染,三種方式
- 在函數中通過條件判斷,return哪種結構
- 用||和&&邏輯判斷符號
- 用三元運算符
1-4列表渲染
需要知道的一點是,jsx中如果插入數組,數組的內容會全部展示在jsx中,渲染的每一項要加上key屬性。
所以,可以通過map方法。將數組里面的每一項數據,來實現相對于的結構,然后后展示在jsx中。
1-5 組件
-
函數組件 (無狀態組件)
函數組件是一個純函數,輸入props。輸出jsx結構
-
類組件(有狀態組件)
-
受控組件
表單元素里面的value/chencked值和state中的值綁定,配合onChange事件,得到輸入的值,才能修改state值,表單才能正常顯示數值。
受控組件的onChange函數可以總結為一個函數
-
非受控組件
不受state控制,沒有和state綁定死值。
通過ref來實現操作該元素dom,拿到dom值
-
1-6 事件
-
事件對象
react用自己的操作事件的邏輯,對事件對象做了一個封裝。
傳參的時候,事件對象默認放在參數的最后一位
-
this指向
在JavaScript中,函數的傳遞,會讓this指向丟失。
-
箭頭函數調用內部函數
onClick ={ ()=> this.handleClick() } //直接在內部調用了事件函數,this借用了render的this
-
類實例方法
//用箭頭函數將函數定義在實例上,函數內部使用的時constroctor中的this handleClick = (參數,event) => { console.log(this) }
-
bind返回一個綁定好this的函數
// 1.在事件函數綁定的時候使用bind onClick = this.handleClick.bind(this) //this綁定到了render里面的this// 2.在構造函數中bind好constroctor中的this , 不用每次使用的時候都bind返回一個數據 this.handleClick = this.handleClick.bind(this)
-
1-7 組件通信
-
props
props是組件父組件給子組件傳遞數據的一個集合,是一個對象。可以通過propType插件來校驗和限制props數據的傳遞,子組件通過this.props得到傳遞數據的對象
父傳子: 父組件通過給子組件標簽添加屬性,來傳遞任意類型數據。
子傳父:父組件給子組件傳入一個能改變自己值的函數。
非父子:狀態提升,給組件a,傳遞數據,給組件b傳遞操作該數據的方法。
-
context
用于跨組件傳遞數據,生產者/消費者模型。
提供者組件為子組件提供數據,消費者組件的子組件能夠使用這些數據
const {Provider , Consumer} = React.createContext
1-8 生命周期
-
創建階段
-
constructor()
- 提供初始化數據
- 創建ref等元素掛載到實例身上
- 處理函數的this指向
-
render()
渲染視圖
-
componentDidMount()
視圖渲染完成
- 發送ajax請求
- 初始化dom操作
-
-
更新階段
-
shouldComponentUpdate()
更加新舊的比較,來決定的該組件需不需要更新。setState/props更新/強制更新觸發
-
render()
-
componentDidUpdate()
-
-
銷毀階段
不展示該組件
-
componentWillUnmount()
卸載完成前,需要手動清除自己添加的定時器和自定義事件
-
1-9 setState()
React中不能直接通過聲明式修改state的數據,必須通過setstate更新state的數據。
-
作用
- 修改了state
- 更新了視圖
-
特點
-
有時異步(react的普通使用),有時同步(定時器,自定義事件)
在react內部函數使用setstate時,數據異步更新(必須等到此次宏任務的微任務中執行)
-
有時合并更新(對象傳入),有時不合并更新(函數傳入)
第一個參數是函數的時候,不會合并更新,每次調用的時候,可以依賴于上一個setState的值,但是還是異步更新。
-
-
setState(更新的數據,回調函數)
這里的回調函數類似與vue中的nextTick,回調函數可以拿到最新的state值,在下一個宏任務最開始運行。
2- React 高級特性
2-1高階組件(公共邏輯代碼的抽離,minin已經棄用)
本質為一個函數,采用裝飾設計模式,接收一個基礎組件,輸出一個增強后的組件,實現組件狀態的復用。如果已經props穿透,可以多層嵌套。
// 基礎組件
class Base extends React.Component{state = {money:0}render(){return <div><h1> 我是Base組件 - 我有{ this.props.money || this.state.money}</div></div>}
}// 高階組件HOC
function WithMoney (Base){class AddMoney extends React.Component{state ={money:1000}render(){return <Base {...this.props} {...this.state}> </Base>}} renturn AddMoney
}//增強后Base組件
const BaseWithMoney = WithMoney(Base)
2-2 render - props (公共邏輯代碼的抽離,mixin已經棄用)
定制一個組件,在這個組件里面完成一部分功能(邏輯/ui),而另外一個組件需要這個功能的時候,將公共組件作為父組件/子組件,傳遞/接收對方的功能。
//功能組件class AddMoney extends React.Component{state ={money:1000}render(){return this.props.children(this.state.money)}}
//樣式組件
class Base extends React.Component{state = {money:0}render(){return <div><h1> 我是Base組件 - 我有{ this.props.money || this.state.money}</div></div>}
}//展示組件
class Home extends React.Component{render(){return <div><Money>(data)=><Base {...data}/></Money></div>}
}
2-3 Portals 傳送門
在不改變組件嵌套的結構情況下,實現自定義該組件在哪個節點渲染
class Base extends React.Component{state = {money:0}render(){return <div><h1> 我是Base組件 - 我有{ this.props.money || this.state.money}</div></div>}
}
//該組件在文檔自定義位置渲染,即使渲染位置變了,但是和父組件的練習沒有改變,事件冒泡也能實現
export default ReactDOM.CreateProtals(<Base/>,document.文檔任意節點)
2-4 異步組件
業務中的一些大組件不一定會被使用,如果同步加載,首屏加載時間延長,而且或許這個大組件根本用不到。
React中通過React.lazy達到異步加載組件的效果,使用React.suspense優化加載過程
//引入BigDemo組件
const BigDemo = React.lazy(()=>import("組件地址"))//加載大組件時展示的數據
<React.suspense fallback = { <div> Loading.....</div>}><BigDemo />
</React.suspense>
2-5 性能優化
代碼層面優化
-
減輕state數據,非更新視圖的數據不需要放在state中
-
優化state的數據結構,避免多層嵌套復雜數據類型
-
避免子組件的不必要更新
-
shouldComponentUpdate( nextprops,nextstate)
可以獲取最新的props和state,和舊值作比較,若一樣,則該組件不更新
-
使用純組件(類組件)
內部自動淺層次比較新舊值
-
React.memo(函數組件,比較函數 )
-
-
多使用不可變值
immutable.js,讓數據徹底成為不可變量。
基于數據共享,速度快,能達到深拷貝效果
-
長列表性能優化
-
事件的銷毀
-
圖片資源懶加載
-
路由懶加載
-
第三方插件的按需引入
-
優化無限列表性能
-
服務端渲染 SSR or 預渲染
Webpack 層面的優化
- Webpack 對圖片進行壓縮
- 減少 ES6 轉為 ES5 的冗余代碼
- 提取公共代碼
- 模板預編譯
- 提取組件的 CSS
- 優化 SourceMap
- 構建結果輸出分析
- React項目的編譯優化
- production自動開啟代碼優化、混淆、壓縮
Web 技術的優化
- 在服務端開啟 gzip 壓縮
- 瀏覽器緩存
- CDN 的使用
- 使用 Chrome Performance 查找性能瓶頸
2-6 組件懶加載
1.代碼分割 + import()
// 引入一個組件
import {add } from "./math"// 異步引入組件
// 觸發import()函數時才異步導入
import("./math").then((math) =>{math.add()
})
當webpack解析到這個語法的時候,自動進行代碼分割。
2.React.lazy() + Suspense
// 異步引入組件
//使用MyErrorBoundary包裹,更容易兼容錯誤
<MyErrorBoundary>//使用suspense組件包裹,更好的兼容等待頁面<Suspense fallback={<div>Loading...</div>}>//在組件首次渲染的時候自動導入const Component = React.lazy(()=>{import("./math")})</Suspense>
</MyErrorBoundary>
3- React 核心原理
3-1函數式編程
一種編程范式,主要特征是使用純函數和不可變量來實現數據驅動視圖效果
- 純函數:接收一個值,輸出一個值,不產生其他副作用
- 不可變量:數據不能通過操作自身進行數據改變,setState設置的值只能是一個新值,原來的數據永遠不能改變。
3-2 JSX編譯
- jsx轉譯成React.creatElement函數,得到react元素
- render函數執行,得到vnode(描述dom節點的js對象)
- 通過path函數渲染
3-3 組件渲染過程 和 更新過程
-
渲染階段
- 通過props/state獲得數據
- render函數直接生成vnode
- patch函數接收vnode,渲染
-
更新階段
- setsState(newvalue)
- render()根據newvalue得到newvnode
- patch函數(階段一):得到vnode。執行diff算法,得到操作dom最少的更新方式
- patch函數(階段二):將計算結果渲染到視圖
**patch階段的問題:**組件在更新階段,計算和視圖渲染都十分消耗性能,如果此時還有其他復雜dom操作(動畫,拖拽),cpu壓力很大,很有可能卡頓。
**fiber機制:**將patch第一階段進行任務拆分。通過window.requestIndleCallback監聽到dom是否更新,dom需要更新的時候,暫停diff算法。
3-4 合成事件機制
- 特點
- 所有的事件掛載到document中
- event事件對象不是原生的,是合成事件機制(SyntheticEvent函數)合成的事件對象。event.nativeEvent可以訪問到原生的事件對象
- 和vue與原生的事件不同
- 處理流程
- 點擊按鈕,觸發事件冒泡到document
- document掛載了React中的所有事件
- 通過合成事件函數生成合成事件
- 觸發對應的事件處理函數
- 作用
- React內部實現一套自己的事件處理邏輯,更好的兼容性和跨平臺
- 事件統一的掛載到document,減少內存消耗,解綁事件方便
- 方便事件的統一管理
3-5 setState 和 batchUpdate機制
setState執行流程
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-mBtei24i-1598189226405)(C:\Users\ADMINI~1\AppData\Local\Temp\1591758044422.png)]
在React內部采用transaction事務機制:
- 每個掛載在React中的函數,在執行前(入口)和執行結束(出口)都會執行一套處理邏輯
- 在掛載函數執行前,調用
isBatchUpdate = true
- 在掛載函數執行結束后,調用
isBatchUpdate = false
- 而在timeout和自定義事件回調函數執行的時候,isBathchUpdate已經是false,所以同步更新
面 - React和vue對比
-
相同
- 都采用組件化
- 都是數據驅動視圖
- 都使用vdom操作dom
- 都通過props傳遞數據
-
使用方式不同
-
React使用Jsx擁抱js體驗,vue采用模板擁抱html體驗
-
React是函數式編程,vue式聲明式編程
-
React只提供框架和核心驅動,vue封裝了很多操作
-
React講究狀態不可變,vue提倡狀態可變
-
webpack知識點
1. 什么是webpack,webpack的運行原理,如何打包 (字節跳動)
webpack是一個打包模塊化javascript的工具,在webpack里一切文件皆模塊,通過loader轉換文件,通過plugin注入鉤子,最后輸出由多個模塊組合成的文件,webpack專注構建模塊化項目。 WebPack可以看做是模塊打包機:它做的事情是,分析你的項目結構,找到JavaScript模塊以及其它的一些瀏覽器不能直接運行的拓展語言(Scss,TypeScript等),并將其打包為合適的格式以供瀏覽器使用。
2.什么是bundle,什么是chunk,什么是module?
- bundle:是由webpack打包出來的最終的文件
- chunk:代碼塊,一個chunk由多個模塊組合而成,用于代碼的合并和分割
- module:是開發中的單個模塊,在webpack的世界,一切皆模塊,一個模塊對應一個文件,webpack會從配置的entry中遞歸開始找出所有依賴的模塊
3.什么是Loader?什么是Plugin?
-
loader
Loader直譯為"加載器"。Webpack將一切文件視為模塊,但是webpack原生是只能解析js文件,如果想將其他文件也打包的話,就會用到loader。 Loaders是用來告訴webpack如何轉化處理某一類型的文件,并且引入到打包出的文件中
-
Plugin
Plugin直譯為"插件"。Plugin可以擴展webpack的功能,讓webpack具有更多的靈活性。 在 Webpack 運行的生命周期中會廣播出許多事件,Plugin 可以監聽這些事件,在合適的時機通過 Webpack 提供的 API 改變輸出結果。
4. 有哪些常見的Loader?他們是解決什么問題的?
- file-loader:把文件輸出到一個文件夾中,在代碼中通過相對 URL 去引用輸出的文件
- url-loader:和 file-loader 類似,但是能在文件很小的情況下以 base64 的方式把文件內容注入到代碼中去
- source-map-loader:加載額外的 Source Map 文件,以方便斷點調試
- image-loader:加載并且壓縮圖片文件
- babel-loader:把 ES6 轉換成 ES5
- css-loader:加載 CSS,支持模塊化、壓縮、文件導入等特性
- style-loader:把 CSS 代碼注入到 JavaScript 中,通過 DOM 操作去加載 CSS。
- eslint-loader:通過 ESLint 檢查 JavaScript 代碼
5. 有哪些常見的Plugin?
- define-plugin:定義環境變量
- html-webpack-plugin:簡化html文件創建
- uglifyjs-webpack-plugin:通過UglifyES壓縮ES6代碼
- webpack-parallel-uglify-plugin: 多核壓縮,提高壓縮速度
- webpack-bundle-analyzer: 可視化webpack輸出文件的體積
- mini-css-extract-plugin: CSS提取到單獨的文件中,支持按需加載
6.webpack的構建流程是什么?從讀取配置到輸出文件這個過程盡量說全
Webpack 的運行流程是一個串行的過程,從啟動到結束會依次執行以下流程:
- 初始化參數:從配置文件和 Shell 語句中讀取與合并參數,得出最終的參數;
- 開始編譯:用上一步得到的參數初始化 Compiler 對象,加載所有配置的插件,執行對象的 run 方法開始執行編譯;
- 確定入口:根據配置中的 entry 找出所有的入口文件;
- 編譯模塊:從入口文件出發,調用所有配置的 Loader 對模塊進行翻譯,再找出該模塊依賴的模塊,再遞歸本步驟直到所有入口依賴的文件都經過了本步驟的處理;
- 完成模塊編譯:在經過第4步使用 Loader 翻譯完所有模塊后,得到了每個模塊被翻譯后的最終內容以及它們之間的依賴關系;
- 輸出資源:根據入口和模塊之間的依賴關系,組裝成一個個包含多個模塊的 Chunk,再把每個 Chunk 轉換成一個單獨的文件加入到輸出列表,這步是可以修改輸出內容的最后機會;
- 輸出完成:在確定好輸出內容后,根據配置確定輸出的路徑和文件名,把文件內容寫入到文件系統。
7.如何利用webpack來優化前端性能?
-
壓縮代碼。刪除多余的代碼、注釋、簡化代碼的寫法等等方式。可以利用webpack的UglifyJsPlugin和ParallelUglifyPlugin來壓縮JS文件, 利用cssnano(css-loader?minimize)來壓縮css
-
利用CDN加速。在構建過程中,將引用的靜態資源路徑修改為CDN上對應的路徑。可以利用webpack對于output參數和各loader的publicPath參數來修改資源路徑
-
刪除死代碼(Tree Shaking)。將代碼中永遠不會走到的片段刪除掉。可以通過在啟動webpack時追加參數–optimize-minimize來實現
-
提取公共代碼。將代碼切片分組,公共代碼更容易命中緩存
-
懶加載
將代碼進行代碼分割,一般都是分割需要懶加載的組件或者公共代碼。然后組件加載方式為懶加載,再加載該組件
-
小圖片編譯成base64碼
-
bundle命名加hash值,若文件內容不變,則可以命中緩存
-
使用production模式打包,內置了很多優化代碼的配置:tree-sharking。es6引入時,執行前靜態編譯
-
scope Hosting:打包時,減少打包產生的作用域
8. 如何提高webpack的打包速度?
多進程打包壓縮代碼,忽視打包項,提前打包常用大型靜態文件避免擔反復編譯,利用緩存,縮小編譯搜索范圍
- happypack插件和ParallelUglifyPlugin插件: 多進程打包和多進程壓縮代碼,還可以利用hash緩存避免重復不必要操作
- IgnorePlugin和nopare:都可以忽視一些沒必要打包項
- dll: 采用webpack的 DllPlugin 和 DllReferencePlugin 引入dll,讓一些基本不會改動的代碼先打包成靜態資源,避免反復編譯浪費時間
- 利用緩存: webpack.cache、babel-loader.cacheDirectory、HappyPack.cache都可以利用緩存提高rebuild效率
- 縮小文件搜索范圍: 比如babel-loader插件,如果你的文件僅存在于src中,那么可以include: path.resolve(__dirname, ‘src’),當然絕大多數情況下這種操作的提升有限,除非不小心build了node_modules文件
9. 介紹模塊化發展歷程
- 模塊化主要是用來抽離公共代碼,隔離作用域,避免變量沖突等。
- IIFE: 使用自執行函數來編寫模塊化,特點:在一個單獨的函數作用域中執行代碼,避免變量沖突。
- AMD: 使用requireJS 來編寫模塊化,特點:依賴必須提前聲明好。
- CMD: 使用seaJS 來編寫模塊化,特點:支持動態引入依賴文件。
- CommonJS: nodejs 中自帶的模塊化。
- UMD:兼容AMD,CommonJS 模塊化語法。
- webpack(require.ensure):webpack 2.x 版本中的代碼分割。
- ES Modules: ES6 引入的模塊化,支持import 來引入另一個 js 。
10.webpack 熱更新原理
自動刷新,是整個網頁刷新,狀態丟失
熱更新,新代碼生效,網頁不刷新,狀態不丟失
熱更新是使用了HMR插件,我沒有仔細研究原理,但是猜測是監聽了系統對這部分文件的保存操作的監聽,然后執行更新,而插件內保存了網頁的狀態。
11-介紹一下babel
babel是一款JavaScript語言的編譯器,他能將高es版本的語言規范轉換成低版本。當然,高版本一些類似于promise等新增的低版本語言無法替換的新語法是無法轉換的
babel 的處理流程:
- 詞法解析,將字符串形式的代碼轉換成Tokens。
- 語法解析,解析器會把tokens轉換成抽象語法樹AST(核心數據結構)
- 遍歷AST,并應用AST轉換器,增刪改查AST節點(訪問者模式)-深度優先的查找原則。
- 根據新AST樹,生成新代碼
babel架構
訪問者會以深度優先
的順序, 或者說遞歸地對 AST 進行遍歷,其調用順序如下圖所示:
上圖中綠線
表示進入該節點,紅線
表示離開該節點。
NODEJS知識點
nodejs是一個基于v8引擎的js的運行環境,標準的模塊化開發環境,所有功能模塊按需導入。
服務器返回html文檔的過程:
- 服務器收到請求
- 解析url,了解請求數據
- 找到html文件,解析html文件成字符串格式,發送給客戶端
1.模塊分類
-
global模塊(除了global模塊,其他模塊都要引入)
在任何地方都能調用
-
path模塊
用于操作路徑解決路徑的兼容問題
-
fs模塊
操作文件
-
http模塊
- 創建一個服務器
- 監聽請求響應
- 設置端口,啟動服務器
-
art-template 模塊
用于后臺渲染
-
url模塊
解析url地址
-
mysql模塊
操作數據庫
2.node模塊類型
- 核心模塊:隨著node一起安裝
- 第三方模塊:下載引入的
- 自定義模塊:自己創建的
3-中間件
項目架構中,保護后端的一種手段,用戶只能訪問中間件,中間件訪問服務器。
中間件會輔助服務器處理部分請求,多個中間件串聯使用通過next()進入下一個中間件處理功能
4-node事件循環機制 和 瀏覽器的事件循環機制
4-1 瀏覽器的事件循環機制
瀏覽器是多進程的:
- 主進程:創建和銷毀其他進程
- GPU進程
- 第三方插件進程
- 瀏覽器內核渲染進程:每打開一個窗口就會創建一個
瀏覽器渲染進程包含多個線程
- GUI渲染進程:瀏覽器界面渲染
- js引擎線程 ------------主 線程 ----
- 事件觸發線程
- 定時器觸發線程 ----- 宏任務
- 異步請求線程
當瀏覽器js引擎這個主線程執行一段代碼的時候,會遇到一些異步操作,就會把該任務交給相對應的線程來處理,主線程繼續執行自己的代碼任務,主線程和定時器線程做的任務稱為宏任務( ui渲染/主代碼/定時器)。若在宏任務期間一些工作線程的任務完成了,這些任務稱之為微任務(promise,nexttick,事件回調)
那么主線程在進入下一個tick之前,會將這次tick產生的微任務執行玩。
這就是瀏覽器的執行機制。
node是單線程程序,通過異步i/O解決阻塞問題,更高效的使用cpu
node的事件循環機制和瀏覽器的,其實很類似,都是工作線程配合主線程來進行執行代碼。只不過node是在線程池中處理異步任務。但是由于線程池的原因導致node執行微任務的時機和瀏覽器相比略有差別
瀏覽器環境下,microtask 的任務隊列是每個 macrotask 執行完之后執行。而在 Node.js 中,microtask 會在事件循環的各個階段之間執行,也就是一個宏任務中的六個階段中的一個階段執行完畢,就會去執行 microtask 隊列的任務。
node和瀏覽器的事件循環機制大致邏輯是一樣的,只是node的工作線程更為復雜,不同的線程之間還有執行優先級。
小程序
wechat運行在客戶端系統,小程序運行在wechat上,h5的升級優化版。
面 - 小程序開發和vue開發的區別#$
小程序開發和vue開發十分類似,都是將一個組件的樣式,結構,數據,插槽,而且都可以引入了指令,都是js統一管理。但是在數據驅動和生命周期上面區別挺大。
vue直接通過mvvm將數據和視圖雙向綁定,講究可變值,且數據一變,視圖立馬更新。但是小程序不一樣,小程序要想數據改變,視圖里面改變,就要通過調用setdata()方法來調用
小程序真的很簡單,官方給小程序給了很多限定,同時給給開發者很多便利。官方標簽也就幾個,還使用數據驅動視圖。小程序頁面和功能本來就簡單,而且微信提供的接口多。小程序開發很簡單的。但凡會一點vue的開發者。看幾天文檔,就會了。
編程范式:
- 編程式 - 手動通過js指令操作dom
- 聲明式 - 通過操作數據,后臺根據數據幫你操作dom
1-文件架構
- APP
- APP.js全局入口文件
- APP.json 全局配置文件
- APP.wxss 全局樣式文件
- 每個組件
- .WXS 存儲數據和生命周期函數 , WXS和js代碼差不多,只是能夠在WXML中運行WXS腳本而已
- .json 存儲配置
- .WXML
- .WXSS
2- 雙線程模型
- 渲染層線程
- js層線程
通過阻塞和等待響應來配合
3- 小程序執行流程
- 啟動小程序
- 解析APP.json
- 注冊APP()
- 執行APP組件生命周期
- 加載注冊自定義組件
- 加載組件json文件
- 渲染層加載渲染結構文件
- 邏輯層加載js文件
- 執行生命周期
瀏覽器輸入url后發生了什么(網絡 / 瀏覽器)
? 這是一個好問題,其實細究起來里面的內容挺深的,里面涉及的內容很多。我試著把它講清楚
基本流程
1.DNS地址查詢
2.TCP連接
3.發送HTTP請求
4.服務器處理請求,以及響應
5.瀏覽器根據響應渲染頁面
6.tcp連接結束
1-DNS地址查詢
1.1什么是DNS
? DNS全程是 Domain Name System 域名系統(服務)協議。 我們訪問服務器時,其實訪問的是該服務器的ip地址,但是ip地址很難記憶,考慮到訪問的便捷性,就提出了DNS。DNS其實就是一個翻譯的功能吧。他可以把網址翻譯成對應的ip地址,我們就可以通過得到的ip地址訪問了。
1-2 DNS查詢
? 他的查詢是一種是一層層查詢的
-
查詢瀏覽器緩存
? 從html5過后,瀏覽器的緩存就用的越來越多了,這時候呢,如果瀏覽器緩存中有對應的ip地址,整個過程就結束了。
? 不過因為瀏覽器的緩存機制,比如瀏覽器的緩存大小和緩存時間的限制,都會導致DNS解析失敗。
-
查詢系統的緩存
? 如果在系統的hosts文件里面設置了DNS映射。也可以完成域名解析。
? 不過如果本地hosts文件被惡意修改,就會訪問到修改后的ip地址,造成域名劫持。
-
查找路由器的緩存
一般一些路由器也會緩存DNS
-
查找本地 DNS緩存服務器
根據網絡配置中的DNS服務器地址,訪問本地區的域名服務器。這個域名服務器緩存了大量的域名解析的結果,雖然也有時間控制。基本域名解析到這里可以完成。
-
遞歸查詢DNS服務器
-
本地DN服務器會將查詢域名的頂級域名服務器的IP地址返回到本地DNS
比如:com
-
本地DNS服務器再向頂級域發送請求,返回二級域的ip地址
比如:baidu
-
然后依次遞歸查詢,直到得到最終的查詢結果,將得到的ip地址返回本機
?
-
1-3 DNS中的安全問題
-
DNS欺騙
就是誘導用戶去訪問一個指定的ip地址
常見的就是緩存遭到了惡意修改。本機上的hosts文件吶,或者本地DNS服務器。可能造成的結果就是信息泄露啊。
-
對本地DNS服務器進行拒絕服務攻擊
讓本地DNS拒絕接受查詢請求的服務,結果就是,無法上網
而且攻擊DNS服務器的手段還挺多
1-4 DNS中的網絡性能優化
1-減少DNS的查找次數,減少CDN的重定向(負載均衡)
? 服務器資源是分布式的,DNS可以就近返回一個服務器ip地址,這就是負載均衡和DNS重定向
? CDN 內容分發網絡
? 在各個地區建立緩存服務器,瀏覽器發送數據請求的時候,經過算法會經過延遲最低的,堵塞最低的網路,訪問最近的服務器。而若該服務器沒有請求需要的內容,就會發送回源。去往上一層服務器查找
? 虎牙和阿里云EMS聯合
?
2-在html的meta標簽和link標簽告訴瀏覽器,對該頁面做預解析
- 用meta信息來告知瀏覽器, 當前頁面要做DNS預解析:
<meta http-equiv="x-dns-prefetch-control" content="on" />
- 在頁面header中使用link標簽來強制對DNS預解析:
<link rel="dns-prefetch" href="http://bdimg.share.baidu.com" />
2-TCP連接
2-1什么是tcp
? tcp是一種可靠的數據傳輸協議.在網絡傳輸中屬于傳輸層面。
? 傳輸時候,包裹了http報文數據,被ip報文包裹。
? 數據建立連接時候,通過標識位,ACK,FIN,SYN等和對方計算機控制數據傳輸進程。
2-2 三次握手和四次揮手
1.三次握手
-
客戶端發送SYN表示要和服務器建立連接,同時帶上ISN序列號 :
SYN + 客戶端序列號
-
服務器返回ACK(客戶端序列號+1)表示以及收到SYN,同時發送SYN加上自己的序列號
ACK(客戶端序列號+1)+服務端序列號
-
客戶端發送ACK確認收到對方的回復:
ACK(服務端序列號+1)
2.為什么要三次握手?
確認雙方都都能數據傳輸
- tcp是雙向傳輸的協議,首先是確保雙方都能接受和發送數據
- 第一次握手,表示發送方能夠發送數據
- 第二次握手,ACK代表接受放能夠收受數據,SYN確保接收方能夠發送數據。
- 第三次握手:確保發送方能夠接受數據
- 經過三次握手就能確定雙方都有接受和發送的功能,就沒必要四次,兩次就實現不了了
握手的次要目的是告知和協商一些信息,****
- MSS–最大傳輸包
- SACK_PERM–是否支持Selective ack(用戶優化重傳效率)
- WS–窗口計算指數(有點復雜的話先不用管)
3.四次握手
- 客戶端主動關閉的一方發送FIN,表示單方面要關閉數據的傳輸
- 服務端接收到FIN后,返回一個ACK表示收到
- 等到服務器的數據全部發送完成,也發送一個FIN。表示關閉數據傳輸
- 客戶端回復ACK表示確認
4.為什么要四次揮手
- TCP是雙向傳輸的,所以結束首先要確保雙方都關閉了數據傳輸端口
- 同時TCP是支持半關閉的,一方結束發送,但是能夠接收數據
- 因此接受和發送都要關閉,而且收到對方的關閉信息,還要確認回復
- 第一次,客戶端發送關閉發送數據的FIN,表示自己沒有數據要傳送了
- 第二次,服務器表示收到,客戶端進入等待狀態,但是還需要繼續發送數據給對方,不能,馬上回復FIN
- 第三次,服務端發送數據全部發送完成的FIN,表示發送完全部數據,進入確定狀態
- 第四次,客戶端回復ACK表示收到,服務端收到ACK后里立馬關閉傳輸接口。客戶端則是處于等待,若短時間內沒有再次收到服務端的FIN,則表示ACK以及送達,客戶端關閉接口
5超時和重傳
? 數據在傳輸時,存在一個數據丟失和網絡擁堵問題。發送方在發送數據時候會啟動一個計時器,如果在一定時間內沒有收到對方的接受確定。會重新發送一份數據。如果接收方收到了兩份相同的數據,會根據編號刪除一份數據
? 但是超時重傳會讓本就擁堵的網絡更加擁堵
6-tcp的可靠性如何保證
- 分塊傳送:數據被分割成最合適的數據塊(UDP的數據報長度不變)
- 等待確認:通過定時器等待接收端發送確認請求,收不到確認則重發
- 確認回復:收到確認后發送確認回復(不是立即發送,通常推遲幾分之一秒)
- 數據校驗:保持首部和數據的校驗和,檢測數據傳輸過程有無變化
- 亂序排序:接收端能重排序數據,以正確的順序交給應用端
- 重復丟棄:接收端能丟棄重復的數據包
- 流量緩沖:兩端有固定大小的緩沖區(滑動窗口),防止速度不匹配丟數據
3-發送HTTP請求
3-1.什么是HTTP協議
? 數據傳輸的規范
? Web使用一種名為HTTP(HyperText Transfer Protocol,超文本傳輸協議)的協議作為規范,完成從客戶端到服務器等一系列運作流程。而協議是指規則的約定。可以說,Web是建立在HTTP協議上通信的。
3-2.HTTP連接方式
-
串行連接
每次一個請求都要經過請求連接,請求響應,結束連接。反應速度特別慢,容易達到瀏覽器的請求上限
-
持久連接
keep-alive模式
http 1.0中默認是關閉的,需要在http頭加入"Connection: Keep-Alive”,才能啟用Keep-Alive;http 1.1中默認啟用Keep-Alive,如果加入"Connection: close “,才關閉。目前大部分瀏覽器都是用http1.1協議,也就是說默認都會發起Keep-Alive的連接請求了,所以是否能完成一個完整的Keep- Alive連接就看服務器設置情況。
建立連接后的一段時間可以進行多次請求。http1.1協議基本都是持久連接。但是由于一個請求結束才能進行下一個請求,容易造成請求堵塞
-
管道化持久連接
可以同時進行多次請求
-
HTTP 2.0多路復用
-
WebSocket
3-3.HTTP報文
1-報文格式
-
請求行
- 請求方法,協議版本
-
請求頭部
- 請求URI,客戶端信息,請求配置信息
-
請求體
- 用戶信息,數據信息
-
響應行
- 協議版本,狀態碼
-
響應頭部
- 請求服務器信息,資源配置信息
-
響應體
- 返回的資源
2-請求方式
GET - 獲取服務器資源
POST - 信息傳輸
PUT -文件傳輸
DELETE - 刪除文件
HEAD - 獲取報文首部
3-常見的狀態碼
? 1-1XX 大多數表示請求收到,還在處理
? 100 :繼續發送請求
? 101:需要切換HTTP協議。
? 2-2XX 請求已經被接受,理解
? 200:成功返回數據
? 201:請求成功,請求想要的資源已經創建
? 202
? 3-3XX 需要客戶端進行下一步操作才能完成,一般為重定向
? 304:頁面需要重定向
? 4- 4XX
? 客戶端發生錯誤,導致服務器的處理。服務器一般會返回一個錯誤說明
? 400:語法錯誤,服務器理解不了,常見表單驗證
? 401: 尋求用戶的授權信息
? 402: 服務里理解請求,但是拒絕執行
? 404: 服務器上并沒有請求需要的資源
? 5- 5XX 服務器端 發生異常
? 500 后臺代碼出錯
? 502 代理服務器出錯
3-4-HTTP版本
? http1.1 比較 http1.0
? 緩存處理的方式更多
? 帶寬和網絡優化
? 錯誤通知的管理
? Host管理
? 長連接
? HTTP的版本更新只是在TCP連接等上面做了一系列優化,但是本質沒有改變。他本質上還是讓數據傳輸處明文傳輸的的狀態。
-
信息可能被竊聽,使用抓包工具
-
無法知道通信雙方是誰,可能遭遇偽裝
-
信息可能被中間人篡改,無法保證報文的完整性
3-5-HTTPS
1.什么是HTTPS
- 對數據進行加密,建立一個安全的信息通道,保證傳輸過程中的數據安全
- 對網站服務器進行真實身份驗證
HTTPS是在THTTP基礎上建立SSL加密層,并且對傳輸的數據進行加密,能確認數據傳輸雙方信息的HTTP協議升級版
-
優勢
- 數據隱私性:內容經過對稱加密,每個連接生成唯一一個加密密鑰
- 數據完整性:內容的傳輸經過完整性校驗
- 身份認證:第三方無法偽造客戶端(服務端)身份
利于seo
-
劣勢
- 加密消耗CPU性能和內存
- 證書使用起來費時費錢
2- HTTPS功能實現
? https實際上只是披上SSL協議的HTTP協議,通過SSL協議的優勢彌補HTTP協議的缺陷。
1.內容被竊聽問題 - 加密
? 方法一:對稱性加密
? 這種加密方式的解密和加密都是用同一套密鑰。問題在于,如何安全的將對稱加密的密鑰發給對象,讓對方能夠解密信息。
?
? 方式二:非對稱加密
? 發送方有兩套密鑰,將公開密鑰發送給接收方,接收方通過公開密鑰加密數據,將信息返回。發送方又用私密密鑰解鎖數據。但是加密解密時間太長
? 公鑰加密的內容,只有私鑰可以解開,私鑰加密的內容,所有的公鑰都可以解開(當然是指和秘鑰是一對的公鑰)
? 方式三:對稱加密+非對稱加密
? 發送方通過對稱加密,將數據進行加密。然后通過對方的非對稱加密的公開密鑰加密對稱加密的密鑰。然后將發送數據和密鑰。
? 中間人能夠劫持公鑰,偽造假公鑰發送
2.報文被篡改 - 數字簽名
? 網絡傳輸要經過很多的中間節點,數據雖然無法被解密,但是很有可能被篡改。
? 數字簽名作用
- 能確定消息確實是由發送方簽名并發出來的,因為別人假冒不了發送方的簽名。
- 數字簽名能確定消息的完整性,證明數據是否未被篡改過。
? 發送者通過哈希函數將一段文本轉成消息摘要,再通過私鑰加密成數字簽名,將數字簽名和文本原文發送。接收者解密數字簽名生成消息摘要1,用哈希函數處理文本得到消息摘要2,對比兩個消息摘要,來確保信息的完整性。
3-通信方身份偽裝 - 數字證書
- 數字證書認證機構:通過服務端提供的信息進行認證,發布加密后的證書文件
- 客戶端發送請求時,服務端返回數字證書文件。
- 客戶端解密檢查數字證書的信息。
3-4-帶寬和延遲
影響一個 HTTP 網絡請求的因素主要有兩個:帶寬和延遲。
- **帶寬:**如果說我們還停留在撥號上網的階段,帶寬可能會成為一個比較嚴重影響請求的問題,但是現在網絡基礎建設已經使得帶寬得到極大的提升,我們不再會擔心由帶寬而影響網速,那么就只剩下延遲了。
- 延遲:
-
- 瀏覽器阻塞(HOL blocking):瀏覽器會因為一些原因阻塞請求。瀏覽器對于同一個域名,同時只能有 4 個連接(這個根據瀏覽器內核不同可能會有所差異),超過瀏覽器最大連接數限制,后續請求就會被阻塞。
- DNS 查詢(DNS Lookup):瀏覽器需要知道目標服務器的 IP 才能建立連接。將域名解析為 IP 的這個系統就是 DNS。這個通常可以利用DNS緩存結果來達到減少這個時間的目的。
- 建立連接(Initial connection):HTTP 是基于 TCP 協議的,瀏覽器最快也要在第三次握手時才能捎帶 HTTP 請求報文,達到真正的建立連接,但是這些連接無法復用會導致每次請求都經歷三次握手和慢啟動。三次握手在高延遲的場景下影響較明顯,慢啟動則對文件類大請求影響較大。
4- 瀏覽器渲染頁面
? 瀏覽器收到服務器返回的資源數據后,將資源渲染到瀏覽器窗口。主要功能就是向服務器發送請求,在瀏覽器窗口展示返回的網絡資源。能夠解析的資源必須符合W3C的規定,其他資源需要配置插件
4-1瀏覽器組成
- 用戶界面:地址欄等除去主窗口以外的部分
- 瀏覽器引擎:在用戶界面與渲染引擎之間傳輸指令
- 渲染引擎:展示請求的資源內容
- 網絡:負責網絡調用
- 用戶界面后端
- js引擎:執行js代碼
- 數據存儲:持久層
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-KNhsXWKD-1598189226416)(C:\Users\Administrator\Desktop\layers.png)]
4-2 瀏覽器如何解析資源渲染頁面
? 瀏覽器解析資源是一個邊解析邊渲染的過程。主要通過渲染引擎和js引擎來處理網絡資源
?
1.渲染引擎將html和css文檔解析成語法樹
? 將文檔解析成有意義的結構,讓瀏覽器能夠使用
? 階段一:詞法分析
? 將文檔輸出解析成token單元
? 階段二:語法分析
? 生成語法樹
? 階段三:將語法樹編譯成機器語言
2.渲染引擎將css語法樹和html語法樹結合成渲染樹
3.渲染引擎和js引擎
? 當解析html文檔遇到
4.觸發瀏覽器的paint事件,根據渲染樹計算元素位置,繪制
? DOM節點中的各個元素都是以盒模型的形式存在,這些都需要瀏覽器去計算其位置和大小等,這個過程稱為回流;當盒模型的位置,大小以及其他屬性,如顏色,字體,等確定下來之后,瀏覽器便開始繪制內容,這個過程稱為重繪。頁面在首次加載時必然會經歷reflow和repain。reflow和repain過程是非常消耗性能的,尤其是在移動設備上,它會破壞用戶體驗,有時會造成頁面卡頓。所以我們應該盡可能少的減少reflow和repain。
5.回流和重繪
? 回流:瀏覽器在進行布局操作,進行位置計算的時候發生
? 重繪:瀏覽器根據屬性渲染頁面;
? 回流一定重繪
優化:
1、瀏覽器自己的優化:瀏覽器會維護1個隊列,把所有會引起回流、重繪的操作放入這個隊列,等隊列中的操作到了一定的數量或者到了一定的時間間隔,瀏覽器就會flush隊列,進行一個批處理。這樣就會讓多次的回流、重繪變成一次回流重繪。
2、我們要注意的優化:我們要減少重繪和重排就是要減少對渲染樹的操作,則我們可以合并多次的DOM和樣式的修改。并減少對style樣式的請求。
**瀏覽器緩存
不過瀏覽器發送請求還有一種情況就是http緩存,也叫瀏覽器緩存。
瀏覽器和服務器通信的方式為應答模式,瀏覽器發送http請求 - 服務器響應該請求。
-
瀏覽器會根據第一次向瀏覽器發送請求后拿到的響應報文的響應頭中的緩存標識來決定是否緩存結果,命中則將請求結果存入瀏覽器緩存中
-
瀏覽器下一次發送請求,會查看瀏覽器緩存有沒有緩存此次請求的緩存結果
強緩存 : 瀏覽器的緩存數據,直接能夠使用
協商緩存 : 瀏覽器的數據不確定是否可用
當瀏覽器查看瀏覽器緩存時,會發生幾種情況:
- 不存在緩存結果和緩存標識,強緩存失效,直接向服務器發送請求
- 存在該緩存結果和緩存標識,但是此結果超過規定的時間限制已經失效,瀏覽器緩存返回緩存標識,攜帶緩存標識向瀏覽器發送請求,確認此緩存是否可用。
- 緩存能用,返回304,使用緩存
- 緩存不能用,返回200,使用新數據
瀏覽器離線緩存
HTML5提出的一個新的特性:離線存儲。通過離線存儲,我們可以通過把需要離線存儲在本地的文件列在一個manifest配置文件中,這樣即使在離線的情況下,用戶也可以正常看見網頁。
ajax請求和跨域問題
1- get 請求和get 請求的區別
get和post請求只是兩種不同的傳送請求的類型,底層都是tcp/ip協議。
- get請求的數據放在請求行中,post放在請求體中
- get發送請求的時候,會將請求頭和包含數據的請求行直接一起發送出去;post發送請求時,會先發送請求頭和請求行,間隔一段時間才會發送包含數據的請求體
- 網絡好的時候,兩者請求事件相差不大,網絡差的時候post文件更不容易丟失
- get發送請求的數據有格式和大小(4k)的限制,post則沒有限制
- get請求參數會保留在瀏覽器歷史記錄,post不會
2- 網絡傳輸常用的數據格式
xml和json
xml
可拓展標記語言,能夠傳輸數據
json
js對象標記,輕量級數據交換格式,本質上時特殊格式的字符串,包含了js的數據。
由于對象等一些屬性,并不能通過網絡傳輸,只能借助轉成json格式的方式傳輸,使用時再轉成對象數據模式。
json.stringfy(js數據)
json.parse(json字符串)
3- formdata 對象
以二進制的方式管理表單數據,用post方式,可以發送大體積文件。
可以通過xhr自帶的方法監聽上傳和下載進度
4- 跨域 / 同源
-
同源:兩個網站來自同一個服務器
- 域名相同
- 端口相同
- 協議相同
-
跨域:不同源網站,則跨域
- 不能共享cookie
- 不能相互操作dom
- 不能互相發送qjax請求
解決跨域
-
CORS
通過請求頭和響應頭來實現跨域資源訪問,請求頭中包含了請求來源的信息,若服務器同意訪問,就可以在響應頭中設置相對于的數據
- 簡單,支持各種傳輸類型
- 要對服務端接口進行改造
-
JSONP
在html中,一些標簽的資源請求不受同源策略的限制。比如
script
標簽。這時候就可以哦那個過script標簽的src屬性發送請求,獲得響應。- 兼容性好
- 只支持get請求,且安全性極低
-
正向代理 / 反向代理
委托能訪問目標網站的中間服務器代為發送和接收數據
v8引擎的內存控制
v8使用的內存是有限制的,而進程需要內存時,才會一點點給他。
垃圾回收機制
**分代式回收機制:**按照對象的存活時間,將對象劃在分代空間,老生代和新生代空間采用不同的算法處理數據。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-7RxfMltW-1598189226423)(C:\Users\ADMINI~1\AppData\Local\Temp\1592199080930.png)]
倘若老生代空間的對象長時間沒辦法被回收,就造成了內存泄漏。
service worker
是獨立于js線程的一個異步線程,不能訪問dom和全局變量,他有著自己的全局作用域。可以用于存儲和處理數據,多用于pwa(漸進式webapp)
性能優化
頁面初始階段加載慢,一般是資源加載過多過大,減少資源數量和資源大小
-
通過懶加載的方式來處理非首屏的圖片和組件
-
小圖標使用iconfont , 小圖片直接使用base64編碼置于html文檔中等方式來實現資源合并
-
使用緩存和cdn來減少請求的時間和次數
-
css,js文件混淆壓縮
-
圖片壓縮
-
在服務端開啟gzip進行全部文件壓縮
-
production模式自動內置優化,混淆+壓縮
-
多命中緩存
-
減少網絡請求
-
價紹資源體積
-
減少訪問次數
-
用cdn
-
懶加載
-
防抖節流
WEB安全
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-EOq4WwiW-1598189226424)(C:\Users\ADMINI~1\AppData\Local\Temp\1592382907762.png)]
1.xss攻擊
1-1 xss介紹
? 跨站腳本攻擊,簡稱XSS。是一種代碼注入攻擊。攻擊者在目標網站注入惡意腳本,讓他在瀏覽器運行,即可獲得用戶信息。
? XSS 的本質是:惡意代碼未經過濾,與網站正常的代碼混在一起;瀏覽器無法分辨哪些腳本是可信的,導致惡意腳本被執行。
? 而由于直接在用戶的終端執行,惡意代碼能夠直接獲取用戶的信息,或者利用這些信息冒充用戶向網站發起攻擊者定義的請求。
? 在部分情況下,由于輸入的限制,注入的惡意腳本比較短。但可以通過引入外部的腳本,并由瀏覽器執行,來完成比較復雜的攻擊策略。
1-2 惡意代碼注入方式
- 用戶的ugc信息,表單提交
- 第三方鏈接
- URL參數
- POST參數
- cookie
- refere
1-3 XSS攻擊分類
-
存儲型
存儲型 XSS 的攻擊步驟:
- 攻擊者將惡意代碼通過提交,放置到目標網站的數據庫中。
- 用戶打開目標網站,惡意代碼也從數據庫中提取出來,拼接到HTML中,返回到瀏覽器。
- 瀏覽器解析惡意代碼。
- 惡意代碼竊取用戶信息,冒充用戶進行操作
這種攻擊常見于帶有用戶保存數據的網站功能,如論壇發帖、商品評論、用戶私信等。
-
反射型
反射型XSS的攻擊步驟
-
攻擊者構造出特殊的url,包含惡意代碼。
-
用戶打開惡意代碼的URL時,服務端提取URL中的惡意代碼,拼接在返回html數據中
-
用戶接收到響應數據,開始執行,就執行到了惡意代碼。
-
惡意代碼竊取用戶信息,冒充用戶進行操作
需要用戶主動打開惡意的 URL 才能生效,攻擊者往往會結合多種手段誘導用戶點擊,常見于網頁搜索和跳轉。
-
-
DOM型
DOM 型 XSS 的攻擊步驟:
- 攻擊者構造出特殊的 URL,其中包含惡意代碼。
- 用戶打開帶有惡意代碼的 URL。
- 用戶瀏覽器接收到響應后解析執行,前端 JavaScript 取出 URL 中的惡意代碼并執行。
- 惡意代碼竊取用戶數據并發送到攻擊者的網站,或者冒充用戶的行為,調用目標網站接口執行攻擊者指定的操作。
DOM 型 XSS 跟前兩種 XSS 的區別:DOM 型 XSS 攻擊中,取出和執行惡意代碼由瀏覽器端完成,屬于前端 JavaScript 自身的安全漏洞,而其他兩種 XSS 都屬于服務端的安全漏洞。
1-4XSS攻擊預防
防護兩大要素:
-
防止攻擊者提交惡意代碼
- 在前端過濾惡意代碼。 不可行。攻擊者可以繞過前端過濾,直接發送請求。
- 過濾后端寫入數據庫的數據 只能過濾數字,郵件地址等明確性的數據。否則會容易由于數據不確定性,引起亂碼問題。
-
防止瀏覽器執行惡意代碼(主要防護途徑)
-
防止 HTML 中出現注入。存儲型,反射型
方案一:純前端渲染SSR
? 純前端渲染的過程:
? 瀏覽器先加載一個靜態 HTML,此 HTML 中不包含任何跟業務相關的數據。
? 然后瀏覽器執行 HTML 中的 JavaScript。
? JavaScript 通過 Ajax 加載業務數據,調用 DOM API 更新到頁面上。
方案二:對html進行轉義
針對<>等特殊字符串
-
防止 JavaScript 執行時,執行惡意代碼。
dom型避免將不可信的html插入到頁面中,減少使用innerHTML等方法。
dom的一些事件監聽器能夠識別字符串當作代碼執行。避免傳遞不可信的數據拼接到字符串,傳遞給這些API。比如onload,onerroe,href屬性,定時器,eval()
-
表單輸入長度控制。
-
驗證碼和cookie保護
-
避免拼接的內聯事件。盡量使用事件綁定
-
避免拼接html,框架很大程度減少了攻擊
-
2.CSRF攻擊
2-1 CSRF介紹
? CSRF 跨站請求偽造 :攻擊者誘導用戶進入第三方網頁,竊取用戶的信息,繞過被攻擊網站的后臺驗證,來進行某些操作
? 流程 : 1. 用戶登錄網站A,保留了登錄憑證(Cookie)
- 攻擊者誘導受害者登錄網站 B 。
3. 網站B通過用戶瀏覽器向網站A服務器發送請求,自動攜帶用戶的Cookie。
4. 網站A后臺認為是用戶在發送請求,正常執行請求
5. 攻擊者借用用戶的名義,進行操作
2-2 攻擊類型
? CSRF攻擊簡單來說就是冒充用戶發送請求,所以能發送請求的操作都能成為它的攻擊途徑
- GET類型CSRF攻擊
- POST類型CSRF攻擊
- 鏈接請求類型的CSRF攻擊:前兩種情況,用戶打開頁面就會中招,這種需要用戶額外點擊
2-3 CSRF攻擊特點
- 攻擊一般由第三方網站發起,由于冒充用戶,被攻擊網站無法阻止攻擊發生
- 不是竊取用戶數據,而是借助Cookie冒充用戶提交請求
- 可以用任何跨域請求達到攻擊效果
2-4 防護策略
? 防護策略只能從增強網站的安全性出發,因為后臺無法識別這種攻擊。根據CSRF攻擊特點,指定的方式有:
- 阻止不明外域的訪問
- 同源檢測
- Samesite Cookie
- 提交時要求附加本域,才能獲取信息
- CSRF Token
- 雙重Cookie
同源檢測防護
? 通過檢測前端請求的Origin Header 和Referer Header來確定請求的來源。檢測不到或者不是本域發起的請求,直接阻止這次請求
雙重Cookie驗證
? 由于攻擊的不能獲取Cookie,只是冒用,所以不能發送雙重Cookie
-
在用戶訪問網站頁面時,向請求域名注入一個Cookie,內容為隨機字符串(例如
csrfcookie=v8g9e4ksfhw
)。 -
在前端向后端發起請求時,取出Cookie,并添加到URL的參數中(接上例
POST https://www.a.com/comment?csrfcookie=v8g9e4ksfhw
)。 -
后端接口驗證Cookie中的字段與URL參數中的字段是否一致,不一致則拒絕。
實行成本低
Token防護
? 通過token字段登錄網站。網站開發的時候,面對請求時,手動添加Token,而不是瀏覽器自動添加。在我看來是最有效而簡單的操作方式。除非有XSS攻擊泄露了XSS,那么CSRF很難攻擊成功。
Samesite Cookie屬性
防止CSRF攻擊的辦法已經有上面的預防措施。為了從源頭上解決這個問題,Google起草了一份草案來改進HTTP協議,那就是為Set-Cookie響應頭新增Samesite屬性,它用來標明這個 Cookie是個“同站 Cookie”,同站Cookie只能作為第一方Cookie,不能作為第三方Cookie
2-5 CSRF 測試
? CSRFTester是一款CSRF漏洞的測試工具
3.點擊劫持攻擊
? 在WEb頁面隱藏了一個透明的iframe元素,誘導用戶點擊,進行一些不知名操作
4.后端一些攻擊漏洞:命令行注入和DDos攻擊
? DDos攻擊:不斷發送請求,讓網站響應崩潰
面 - 開發中的數據安全問題
前端的安全問題主要發生在代碼的安全問題,用戶在瀏覽器操作上的安全問題,和網絡傳輸的安全問題
代碼的安全問題
- 規范開發,避免使用引起xss攻擊的代碼
- 警惕使用第三方提供的頁面組件,這些頁面組件一般通過iframe方式引入天氣等插件。其實這個模塊不受我們控制的,很容易造成安全隱患。
- 防范本地內存泄漏,特別是離線應用和spa頁面,這些都在本地保存了很多隱私數據,此時如果有xss攻擊,意味著數據全部透明了。可以設置用戶離開清除數據、數據加密后保存等方式,但是也只是降低了一點風險。
- 還可以通過代碼混淆來保護代碼吧
網絡傳輸的安全問題
- 有時候出于性能考慮使用CDN,這時候攻擊者就可以劫持cdn資源,進行不法操作
- 由于http協議的裸奔性,任何一個節點的抓包工具都能獲取,所以更應該使用https協議和token字段
開發項目知識點
yarn
相比于npm的優勢
-
采用多線程下載,下載速度更快
-
yarn更加安全穩定
GIT
項目管理工具
常用的使用指令
git log
git reset 回到某個版本號
git branch 創建切換分支
git checkout -b 創建并切換分支
git merge 提交后合并分支
git clone
git push
git pull
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-g0XdhDfL-1598189226425)(C:\Users\ADMINI~1\AppData\Local\Temp\1592400824612.png)]
抓包工具
fiddler
linux基本指令
- 本地登錄線上機器:SSH 用戶名@ip地址
- 查看所有文件夾: ll / ls
- 查看隱藏文件夾:ll -a
- 查看指令文件:ls 文件名
- 創建文件夾: mkdir 文件夾名
- 創建文件: touch 文件名
- 創建并打開文件 : vim 文件名
- 刪除文件夾: rm -rf 文件夾名
- 前往文件夾: cd
- 重命名文件夾: mv
- 拷貝:cp 源文件夾名
?
開發流程
- 需求分析
- 了解背景
- 需求是否合理
- 需求是否閉環
- 開發難度
- 是否需要其他支持
- 結合小組項目給出排期
- 技術方案分析
- 技術求簡,只要能實現就行
- 寫出產出開發文檔
- 找準設計重點
- 開發
- 排期多流出一點時間
- 符合公司開發規范
- 寫開發文檔
- 及時寫單元測試
- mock api 模擬數據
- code review 同事看一下
- 聯調
- pm加需求
- 重新評估排期
- pm加需求
- 測試
- 上線
短信驗證碼和圖片驗證碼
-
圖片驗證碼
后臺隨機生成一串驗證碼,返回給客戶端,用戶輸入驗證碼。發送請求后,后臺驗證用戶是否存在以及驗證碼是否匹配,若都驗證正確,則返回登錄成功
-
短信驗證碼
輸入手機號碼,提交給后臺,后臺驗證手機號碼是否注冊。通過一套規則生成驗證碼,然后將短信碼和手機號給運營平臺,給用戶發送驗證碼。
后臺接收到驗證碼后,檢測是否和后臺的驗證碼匹配
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-OeXExIQH-1598189226426)(C:\Users\ADMINI~1\AppData\Local\Temp\1592301482820.png)]
移動端的兼容(安卓和iOS手機)
只有少數情況需要判斷操作 基本你就正常寫就行
兼容問題自己不常見到 大家記住幾個 面試問就說一下 如果面試官說的你不懂?我沒有遇見這個很正常
兼容問題 有很多版本都不一樣 安卓 ios也有不一樣 我們遇見了再去百度解決 如果面試 先記住幾個
1 怎么判斷是安卓還是 ios**
//獲取瀏覽器的userAgent,并轉化為小寫
var ua = navigator.userAgent.toLowerCase();
//判斷是否是蘋果手機,是則是true
var isIos = (ua.indexOf('iphone') != -1) || (ua.indexOf('ipad') != -1);
if(isIos){做蘋果手機兼容
}else{做安卓
}
2 兼容問題
1.禁止圖片點擊放大
部分安卓手機點擊圖片會放大,如需要禁止放大,只需要設置css屬性
img{ pointer-events: none;
}
這個會讓img標簽的點擊事件失效,如果想要給圖片添加點擊事件就要給上面再寫一層
2.禁止 iOS 識別長串數字為電話
<meta name="format-detection" content="telephone=no">
3.禁止復制、選中文本
設置CSS屬性 -webkit-user-select:none
4.一些情況下對非可點擊元素如(label,span)監聽點擊事件,不會在IOS下觸發,css增加cursor:pointer就搞定了
5.上下拉動滾動條時卡頓、慢
body {
-webkit-overflow-scrolling: touch;
overflow-scrolling: touch;
}
Android3+和iOS5+支持CSS3的新屬性為overflow-scrolling
6 安卓不會自動播放視頻
安卓autoplay沒效果 需要手動觸發一下
window.addEventListener('touchstart', function(){audio.play(); // 需要主動調用一下js 讓視頻播放
}, false);
7.半透明的遮罩層改為全透明
在ios上,當點擊一個鏈接或者通過js綁定了點擊事件的元素時,會出現一個半透明的背景,當手指離開屏幕,該灰色背景消失,出現“閃屏”
html, body {-webkit-tap-highlight-color: rgba(0,0,0,0);
}
html進行轉義**
針對<>等特殊字符串
-
防止 JavaScript 執行時,執行惡意代碼。
dom型避免將不可信的html插入到頁面中,減少使用innerHTML等方法。
dom的一些事件監聽器能夠識別字符串當作代碼執行。避免傳遞不可信的數據拼接到字符串,傳遞給這些API。比如onload,onerroe,href屬性,定時器,eval()
-
表單輸入長度控制。
-
驗證碼和cookie保護
-
避免拼接的內聯事件。盡量使用事件綁定
-
避免拼接html,框架很大程度減少了攻擊
2.CSRF攻擊
2-1 CSRF介紹
? CSRF 跨站請求偽造 :攻擊者誘導用戶進入第三方網頁,竊取用戶的信息,繞過被攻擊網站的后臺驗證,來進行某些操作
? 流程 : 1. 用戶登錄網站A,保留了登錄憑證(Cookie)
- 攻擊者誘導受害者登錄網站 B 。
3. 網站B通過用戶瀏覽器向網站A服務器發送請求,自動攜帶用戶的Cookie。
4. 網站A后臺認為是用戶在發送請求,正常執行請求
5. 攻擊者借用用戶的名義,進行操作
2-2 攻擊類型
? CSRF攻擊簡單來說就是冒充用戶發送請求,所以能發送請求的操作都能成為它的攻擊途徑
- GET類型CSRF攻擊
- POST類型CSRF攻擊
- 鏈接請求類型的CSRF攻擊:前兩種情況,用戶打開頁面就會中招,這種需要用戶額外點擊
2-3 CSRF攻擊特點
- 攻擊一般由第三方網站發起,由于冒充用戶,被攻擊網站無法阻止攻擊發生
- 不是竊取用戶數據,而是借助Cookie冒充用戶提交請求
- 可以用任何跨域請求達到攻擊效果
2-4 防護策略
? 防護策略只能從增強網站的安全性出發,因為后臺無法識別這種攻擊。根據CSRF攻擊特點,指定的方式有:
- 阻止不明外域的訪問
- 同源檢測
- Samesite Cookie
- 提交時要求附加本域,才能獲取信息
- CSRF Token
- 雙重Cookie
同源檢測防護
? 通過檢測前端請求的Origin Header 和Referer Header來確定請求的來源。檢測不到或者不是本域發起的請求,直接阻止這次請求
雙重Cookie驗證
? 由于攻擊的不能獲取Cookie,只是冒用,所以不能發送雙重Cookie
-
在用戶訪問網站頁面時,向請求域名注入一個Cookie,內容為隨機字符串(例如
csrfcookie=v8g9e4ksfhw
)。 -
在前端向后端發起請求時,取出Cookie,并添加到URL的參數中(接上例
POST https://www.a.com/comment?csrfcookie=v8g9e4ksfhw
)。 -
后端接口驗證Cookie中的字段與URL參數中的字段是否一致,不一致則拒絕。
實行成本低
Token防護
? 通過token字段登錄網站。網站開發的時候,面對請求時,手動添加Token,而不是瀏覽器自動添加。在我看來是最有效而簡單的操作方式。除非有XSS攻擊泄露了XSS,那么CSRF很難攻擊成功。
Samesite Cookie屬性
防止CSRF攻擊的辦法已經有上面的預防措施。為了從源頭上解決這個問題,Google起草了一份草案來改進HTTP協議,那就是為Set-Cookie響應頭新增Samesite屬性,它用來標明這個 Cookie是個“同站 Cookie”,同站Cookie只能作為第一方Cookie,不能作為第三方Cookie
2-5 CSRF 測試
? CSRFTester是一款CSRF漏洞的測試工具
3.點擊劫持攻擊
? 在WEb頁面隱藏了一個透明的iframe元素,誘導用戶點擊,進行一些不知名操作
4.后端一些攻擊漏洞:命令行注入和DDos攻擊
? DDos攻擊:不斷發送請求,讓網站響應崩潰
面 - 開發中的數據安全問題
前端的安全問題主要發生在代碼的安全問題,用戶在瀏覽器操作上的安全問題,和網絡傳輸的安全問題
代碼的安全問題
- 規范開發,避免使用引起xss攻擊的代碼
- 警惕使用第三方提供的頁面組件,這些頁面組件一般通過iframe方式引入天氣等插件。其實這個模塊不受我們控制的,很容易造成安全隱患。
- 防范本地內存泄漏,特別是離線應用和spa頁面,這些都在本地保存了很多隱私數據,此時如果有xss攻擊,意味著數據全部透明了。可以設置用戶離開清除數據、數據加密后保存等方式,但是也只是降低了一點風險。
- 還可以通過代碼混淆來保護代碼吧
網絡傳輸的安全問題
- 有時候出于性能考慮使用CDN,這時候攻擊者就可以劫持cdn資源,進行不法操作
- 由于http協議的裸奔性,任何一個節點的抓包工具都能獲取,所以更應該使用https協議和token字段
開發項目知識點
yarn
相比于npm的優勢
-
采用多線程下載,下載速度更快
-
yarn更加安全穩定
GIT
項目管理工具
常用的使用指令
git log
git reset 回到某個版本號
git branch 創建切換分支
git checkout -b 創建并切換分支
git merge 提交后合并分支
git clone
git push
git pull
[外鏈圖片轉存中…(img-g0XdhDfL-1598189226425)]
抓包工具
fiddler
linux基本指令
- 本地登錄線上機器:SSH 用戶名@ip地址
- 查看所有文件夾: ll / ls
- 查看隱藏文件夾:ll -a
- 查看指令文件:ls 文件名
- 創建文件夾: mkdir 文件夾名
- 創建文件: touch 文件名
- 創建并打開文件 : vim 文件名
- 刪除文件夾: rm -rf 文件夾名
- 前往文件夾: cd
- 重命名文件夾: mv
- 拷貝:cp 源文件夾名
?
開發流程
- 需求分析
- 了解背景
- 需求是否合理
- 需求是否閉環
- 開發難度
- 是否需要其他支持
- 結合小組項目給出排期
- 技術方案分析
- 技術求簡,只要能實現就行
- 寫出產出開發文檔
- 找準設計重點
- 開發
- 排期多流出一點時間
- 符合公司開發規范
- 寫開發文檔
- 及時寫單元測試
- mock api 模擬數據
- code review 同事看一下
- 聯調
- pm加需求
- 重新評估排期
- pm加需求
- 測試
- 上線
短信驗證碼和圖片驗證碼
-
圖片驗證碼
后臺隨機生成一串驗證碼,返回給客戶端,用戶輸入驗證碼。發送請求后,后臺驗證用戶是否存在以及驗證碼是否匹配,若都驗證正確,則返回登錄成功
-
短信驗證碼
輸入手機號碼,提交給后臺,后臺驗證手機號碼是否注冊。通過一套規則生成驗證碼,然后將短信碼和手機號給運營平臺,給用戶發送驗證碼。
后臺接收到驗證碼后,檢測是否和后臺的驗證碼匹配
[外鏈圖片轉存中…(img-OeXExIQH-1598189226426)]
移動端的兼容(安卓和iOS手機)
只有少數情況需要判斷操作 基本你就正常寫就行
兼容問題自己不常見到 大家記住幾個 面試問就說一下 如果面試官說的你不懂?我沒有遇見這個很正常
兼容問題 有很多版本都不一樣 安卓 ios也有不一樣 我們遇見了再去百度解決 如果面試 先記住幾個
1 怎么判斷是安卓還是 ios**
//獲取瀏覽器的userAgent,并轉化為小寫
var ua = navigator.userAgent.toLowerCase();
//判斷是否是蘋果手機,是則是true
var isIos = (ua.indexOf('iphone') != -1) || (ua.indexOf('ipad') != -1);
if(isIos){做蘋果手機兼容
}else{做安卓
}
2 兼容問題
1.禁止圖片點擊放大
部分安卓手機點擊圖片會放大,如需要禁止放大,只需要設置css屬性
img{ pointer-events: none;
}
這個會讓img標簽的點擊事件失效,如果想要給圖片添加點擊事件就要給上面再寫一層
2.禁止 iOS 識別長串數字為電話
<meta name="format-detection" content="telephone=no">
3.禁止復制、選中文本
設置CSS屬性 -webkit-user-select:none
4.一些情況下對非可點擊元素如(label,span)監聽點擊事件,不會在IOS下觸發,css增加cursor:pointer就搞定了
5.上下拉動滾動條時卡頓、慢
body {
-webkit-overflow-scrolling: touch;
overflow-scrolling: touch;
}
Android3+和iOS5+支持CSS3的新屬性為overflow-scrolling
6 安卓不會自動播放視頻
安卓autoplay沒效果 需要手動觸發一下
window.addEventListener('touchstart', function(){audio.play(); // 需要主動調用一下js 讓視頻播放
}, false);
7.半透明的遮罩層改為全透明
在ios上,當點擊一個鏈接或者通過js綁定了點擊事件的元素時,會出現一個半透明的背景,當手指離開屏幕,該灰色背景消失,出現“閃屏”
html, body {-webkit-tap-highlight-color: rgba(0,0,0,0);
}