你不得不熟悉且熟练掌握的前端知识
提示:內容較多,建議先收藏方便下次查看
文章目錄
- 一、HTML+CSS+JS
- 1.1 語義化的理解
- 1.2 常見語義化標簽及說明
- 1.3 瀏覽器渲染html過程(主要分為四個步驟)
- 1.4 重繪與回流(重排)
- 1.5 CSS阻塞與JS阻塞詳解
- 1.6 理解堆棧,基本數據類型與引用數據類型
- 1.7 進程與線程的區別
- 二、CSS
- 2.1 position的屬性
- 2.2 css選擇器
- 2.3 浮動
- 2.4 清除浮動的方法
- 2.5 深入理解CSS盒模型
- 2.6 水平居中的方式
- 2.7 垂直居中的方式
- 2.8 如何繪制一個三角形
- 三、JS
- 3.1 數組
- 3.2 set 和map 的區別
- 3.3 for of用法
- 3.4 forEach、for of 與 for in的區別
- 3.5 實現深拷貝的方式
- 3.6 localStorage和sessionStorage
- 3.7 private、protect、public關鍵字
- 四、前端框架
- 4.1 Vue概述及特點
- 4.2 Angular
- 4.3 MVVM
- 五、Vue知識點總結
- 5.1 vue生命周期
- 5.2 keep-alive的作用是什么?
- 5.3 父子組件之間通信方式
- 5.4 Vue中雙向數據綁定
- 5.5 自定義組件的雙向數據綁定實現
- 5.6 $nextTick的使用
- 5.7 computed 和 watch 的區別和運用的場景?
- 5.8 vuex(狀態管理)
- 5.9 v-if與v-show的區別
- 六、Vue3.0
- 6.1 生命周期的變化
- 6.2 setup函數
- 6.3 組件之間的通信
- 七、常見要點分析
- 7.1 SPA(單頁應用)首屏加載速度慢
- 7.2 如何實現路由懶加載
- 7.3 前端如何理解面向對象
- 7.4 如何理解構造函數
- 7.5 prototype(原型)的理解(可以先看7.6再看7.5)
- 7.6 __proto__的理解
- 7.6 constructor介紹
- 7.7 微任務與宏任務
- 7.8 async 與 await
- 7.9 JS當中的防抖(debounce)與節流(throttle)
- 7.10 JS當中的this
- 7.11 JS當中的call()、apply()
- 7.12 事件冒泡和事件捕獲
- 7.13 cookie、session與token
- 八、微信小程序
- 8.1 應用的生命周期函數
- 8.2 Page頁面的生命周期
- 8.3 Component的生命周期
- 九、UniApp
- 8.1 應用的生命周期函數
- 8.2 頁面的生命周期
一、HTML+CSS+JS
1.1 語義化的理解
含義:語義化是指用合理HTML標記以及其特有的屬性去格式化文檔內容。
使用合適的標簽干合適的事(各司其職)。
語義化的標簽能夠使代碼更加的清晰,結構明了。
有利于SEO,搜索引擎根據標簽來確定上下文和各個關鍵字的權重。
1.2 常見語義化標簽及說明
常見標簽: <title></title> // 頁面主體內容,用于提升搜索引擎排名<header></header> // 頁眉,包括網站標志、主導航、全站鏈接以及搜索框<nav></nav> // 導航 常用于頁面的導航部分<main></main> // 主要內容,一個頁面只能使用一次;若是 web 應用,則包含其主要功能<section></section> // 區塊 一般用于一組相似的內容,比如文章的章節,標簽頁等<aside></aside> // 側邊欄 表示內容與頁面主體內容無關的部分<footer></footer> // 頁腳 其它不常見標簽: <small>:呈現小號字體效果,指定細則,輸入免責聲明、注解、署名、版權。 <strong>:和 em 標簽一樣,用于強調文本,但它強調的程度更強一些。 <em>:將其中的文本表示為強調的內容,表現為斜體。 <mark>:使用黃色突出顯示部分文本。 <figure>:規定獨立的流內容(圖像、圖表、照片、代碼等等)(默認有40px左右margin)。 <figcaption>:定義 figure 元素的標題,應該被置于 figure 元素的第一個或最后一個子元素的位置。 <cite>:表示所包含的文本對某個參考文獻的引用,比如書籍或者雜志的標題。 <blockquoto>:定義塊引用,塊引用擁有它們自己的空間。 <time>:datetime屬性遵循特定格式,如果忽略此屬性,文本內容必須是合法的日期或者時間格式。 <abbr>:簡稱或縮寫。 <dfn>:定義術語元素,與定義必須緊挨著,可以在描述列表dl元素中使用。 <address>:作者、相關人士或組織的聯系信息(電子郵件地址、指向聯系信息頁的鏈接)。 <del>:移除的內容。 <ins>:添加的內容。 <code>:標記代碼。 <meter>:定義已知范圍或分數值內的標量測量。(Internet Explorer 不支持 meter 標簽) <progress>:定義運行中的進度(進程)。1.3 瀏覽器渲染html過程(主要分為四個步驟)
1. 解析HTML生成DOM樹-渲染引擎首先解析HTML文檔,生成DOM樹
2. 構建render樹-dom樹結合css文件生成渲染樹(Render樹)
3. 布局Render樹-對渲染樹的每個節點進行布局處理,確定其在屏幕上的顯示位置
4. 繪制Render樹-遍歷渲染樹并用UI后端層將每一個節點繪制出來
說明:
解析html和構建dom樹是同步進行的,這個過程就是逐行解析代碼,包括html標簽和js動態生成的標簽,最終生成dom樹。
構建render樹,就是把css文件和style標簽的中的內容,結合dom樹的模型,構建一個rendeer樹,寫到內存,等待進一步生成界面。
結合render樹,把dom節點的大小、位置計算出來。
把css中有關顏色的設置,背景、字體顏色等呈現出來
1.4 重繪與回流(重排)
repaint : 當諸如顏色背景等不會引起頁面布局變化,而只需要重新渲染的過程叫做重繪
reflow : 當render樹的一部分或者全部因為大小邊距等問題發生改變而需要重建的過程,叫做回流
什么會引起回流?
頁面渲染初始化
窗口resize事件觸發
改變瀏覽器的字體大小(回流+重繪)
改變元素的padding、border、margin(回流+重繪)
添加、刪除元素(回流+重繪)
讀取元素的某些屬性(offsetLeft,offsetTop,offsetHeight,offsetWidth,scrollTop… …)
減少回流
避免逐項更改樣式。最好一次性更改style屬性,或者將樣式列表定義為class并一次性更改class屬性。
避免循環操作DOM。
避免多次讀取offsetLeft等屬性。無法避免則將它們緩存到變量。
將復雜的元素絕對定位或固定定位,使它脫離文檔流。否則回流代價十分高
用transform做形變和位移.
display:none與visibility:hidden
display:none指的是元素完全不陳列出來,不占據空間,涉及到了DOM結構,故產生reflow與repaint
visibility:hidden指的是元素不可見但存在,保留空間,不影響結構,故只產生repaint (重繪)
1.5 CSS阻塞與JS阻塞詳解
CSS加載不會阻塞DOM樹解析,但會阻塞DOM樹的渲染
CSS加載會阻塞后面js語句的執行
關于CSS阻塞有幾下幾點需要特別說明:
CSS阻塞只有link引入的外部css才能夠產生css阻塞
在style標簽中的樣式是交給html解析器進行的,因此不會阻塞瀏覽器渲染(可能會產生閃屏)和DOM解析
如果css加載不阻塞render樹渲染的話,那么當css加載完之后,render樹可能又得重新重繪或者回流了,這就造成了一些沒有必要的損耗。
為了避免這種閃屏現象,所以一般推薦使用link引入的外部CSS樣式,但是這種方式會阻塞其后面JS語句的執行,因此我們需要注意以下幾點(如何提供CSS加載速度 ):
使用CDN節點進行外部資源加速。
對css進行壓縮(利用打包工具,比如webpack,gulp等)。
減少http請求數,將多個css文件合并。
優化樣式表的代碼
js阻塞
阻塞DOM解析
解析過程中無論遇到的JavaScript是內聯還是外鏈,只要瀏覽器遇到 script 標記,喚醒 JavaScript解析器,就會進行暫瀏覽器解析HTML,并等到 CSSOM 構建完畢,才去執行js腳本。所以實際工程中,我們常常將資源放到文檔底部
改變腳本加載次序defer與async
defer 與 async 可以改變之前的那些阻塞情形,這兩個屬性都會使 script 異步加載,然而執行的時機是不一樣的。
注意:在加載多個JS腳本的時候,async是無順序的加載,而defer是有順序的加載,在有async的情況下,js一旦下載好了就會執行,所以很有可能不是按照原本的順序來執行的。如果js前后有依賴性,用async,就很有可能出錯。`
defer 屬性表示延遲執行引入 JavaScript,即 JavaScript 加載時 HTML 并未停止解析,這兩個過程是并行的。
整個 document 解析完畢且 defer-script 也加載完成之后(這兩件事情的順序無關),會執行所有由 defer-script 加載的 JavaScript 代碼,再觸發 DOMContentLoaded(初始的 HTML 文檔被完全加載和解析完成之后觸發,無需等待樣式表圖像和子框架的完成加載) 事件 。
async 屬性表示異步執行引入的 JavaScript,與 defer 的區別在于,如果已經加載好,就會開始執行.
1.6 理解堆棧,基本數據類型與引用數據類型
1、堆棧
棧(stack):系統自動分配的內存空間,內存會由系統自動釋放,用來存放函數的參數值,局部變量的值等,特點是先進后出。
堆(heap):系統動態分配的內存,內存大小不一,內存不會自動釋放。一般由程序員分配釋放,主要負責像Obejct這種變量類型的存儲。
2、基本數據類型
概念:存放在棧內存中的簡單數據段,數據大小確定,內存空間大小確定。
6種基本數據類型:Undefined、Null、Boolean、Number、String、Symbol
3、引用數據類型
概念:存放在堆內存中的數據,如對象、數組、函數等。
名存在棧內存,值存在堆內存,棧內存會提供一個引用的地址指向堆內存中的值
1.7 進程與線程的區別
最大區別:進程是資源分配最小單位,線程是程序執行的最小單位。
進程有自己獨立的地址空間,每啟動一個進程,系統都會為其分配地址空間,建立數據表來維護代碼段、堆棧段和數據段;
線程沒有獨立的地址空間,同一進程的線程共享本進程的地址空間。
二、CSS
2.1 position的屬性
static 默認值,在沒有設置position屬性的時候,position默認為static 在文檔(頁面)中占位置
relative 相對定位。在使用top或者left進行位置移動的時候,參考的位置是自己原先(沒有定位時)所在的位置。 在文檔(頁面)中占位置。
absoluate 絕對定位。
fixed 固定定位。固定在當前可視窗口,不管頁面怎么上下,左右滑動,固定在窗口,都不會進行移動。 脫離文檔流,當與其他位置的元素發生重疊是,一直在其他元素上方。
sticky:粘性定位。即當元素在頁面中,網頁向上滑動,頁面頂部與元素剛開始 想重疊是,就可以設置吸頂效果,隨后就像固定定位一定定位在頁面頂部。為c3新增加的屬性。兼容性不好
2.2 css選擇器
id選擇器,類選擇器,標簽選擇器
后代選擇器:(#box div),選擇id為box元素內部所有的div元素
子選擇器:(.one>one_1),選擇父元素為.one的所有.one_1的元素
相鄰同胞選擇器:(.one+.two),選擇緊接在.one之后的所有.two元素
群組選擇器:(div,p),選擇div、p的所有元素
偽類選擇器
:link :visited :active
:hover 鼠標指針浮動在上面的元素
:focus 選擇具有焦點的
:first-child 父元素的首個子元素
:nth-child(n) 選擇父元素中第N個子元素
:last-child 父元素的最后一個元素
:disabled 選擇被禁用元素
:checked 選擇選中的元素
偽元素選擇器
::before 選擇器在被選元素的內容前面插入內容
::after 選擇器在被選元素的內容后面插入內容
::first-letter :用于選取指定選擇器的首字母
::first-line :選取指定選擇器的首行
舉例分析
偽元素::before. ::after 可實現效果如下:
偽元素妙用
偽元素實現換行,替代換行標簽
增強用戶體驗,使用偽元素實現增大點擊熱區(偽元素也是可以代表其宿主元素來響應的鼠標交互事件的)
利用 :after 清除浮動
2.3 浮動
float的屬性值有none、left、right
只有橫向浮動,并沒有縱向浮動
當元素應用了float屬性后,將會脫離普通流,其容器(父)元素將得不到脫離普通流的子元素高度。
如下代碼
效果如下:
2.4 清除浮動的方法
方法一:使用帶 clear 屬性的空元素 (在浮動元素后使用一個空元素,并在 CSS 中賦 予.clear{clear:both;}屬性即可清除浮動。)
方法二:使用 CSS 的 overflow 屬性
方法三:使用 CSS 的:after 偽元素
方法一:優點:簡單,代碼少,瀏覽器兼容性好。缺點:需要添加大量無語義的html元素,代碼不夠優雅,后期不容易維護。
方法二:觸發浮動元素父元素的 BFC (Block Formatting Contexts, 塊級格式化上下文),使到該父元素可以包含浮動元素。
方法三:利用::after偽元素在元素末尾添加一個內容為一個點并帶有clear:both屬性元素實現的。
方法三舉例:如下代碼會將2.3中的效果變成
.parent:after{content:"";display:block;clear:both;}2.5 深入理解CSS盒模型
盒模型的組成大家肯定都懂,由里向外content,padding,border,margin.
盒模型是有兩種標準的,一個是標準模型,一個是IE模型。
在標準模型中,盒模型的寬高只是內容(content)的寬高,
在IE模型中盒模型的寬高是**內容(content)+填充(padding)+邊框(border)**的總寬高。
標準模型 box-sizing:content-box;
IE模型 box-sizing:border-box;
2.6 水平居中的方式
1)通過margin: 0 auto; text-align: center實現CSS水平居中
.parent{width: 600px;height: 200px;} .child{width: 100px;height: 100px;margin: 0 auto;text-align: center;}2)通過display:flex實現CSS水平居中
justify-content屬性定義了項目在主軸上的對齊方式。
align-items屬性定義項目在交叉軸上如何對齊
3)通過position:absolute實現CSS水平居中
2.7 垂直居中的方式
1)通過display:flex實現CSS垂直居中
.parent{width:300px;height:300px;border: 1px solid red;display:flex;justify-content:center;align-items:center}2)通過position:absolute實現CSS水平居中
3)inline-block+vertical-aligin
.wrap {width: 300px;height: 300px;background-color: pink;text-align: center;line-height: 300px;} .box {width: 100px;height: 100px;/* 重新設置子元素的行高,否則會繼承父元素的行高*/line-height: 100px;background-color: plum;display: inline-block;/* middle 把此元素放置在父元素的中部。 */vertical-align: middle; }2.8 如何繪制一個三角形
.main {width: 100%;min-height: 100vh;background-color: #f5f5f5;}.content {width: 0;height: 0;border: 100px solid #000;border-top-color: red;border-bottom-color: transparent;border-left-color: transparent;border-right-color: transparent;}三、JS
3.1 數組
請到我的另一個博客學習,JS數組概覽(匯總)
3.2 set 和map 的區別
在JS中的默認對象的表示方式為{},即一組鍵值對,但是鍵必須是字符串。
為了使用Number或者其他數據類型作為鍵,ES6規范引入了新的數據類型Map。
Map(字典):是一組鍵值對的結構,具有極快的查找速度
鍵和值可以是任何的值,如下:
Set: es6新增的一種新的數據結構,常用作數組去重
如下:
兩者都能使用的遍歷方法:
keys()
values()
forEach
entries()
WeakSet和WeakMap
WeakSet :只能儲存對象引用,不能存放值
WeakSet: 成員都是弱引用,可以被垃圾回收機制回收,可以用來保存DOM節點,不容易造成內存泄漏。
WeakMap:只接受對象作為鍵名(null除外),鍵名是弱引用,鍵值可以是任意的,鍵名所指向的對象可以被垃圾回收,此時鍵名是無效的。
WeakSet和WeakMap:不能遍歷
3.3 for of用法
示例代碼如下:
// 定義一個數組 var arr = ['1', '2', '3', '4', '5', '6']; // 循環遍歷數組中的每個元素 for (var value of arr) {// console.log(value); // 1,2,3,4,5,6 }// 定義一個字符串 var str = "zyzhang"; // 循環遍歷字符串中的每個字符 for (var value of str) {// console.log(value) // z y z h a n g } // 定義一個對象 雖然可以遍歷對象但并不推薦,推薦使用 for in var obj = {"name": "zyzhang", "age": "20"}; // 循環遍歷對象中的所有屬性(是屬性而不是值) for(var value in obj) {console.log(value) // name age }3.4 forEach、for of 與 for in的區別
forEach 不能使用break return 結束并退出循環
for in 和 for of 可以使用break return;
for of 適合遍歷數組或者類數組。
for in 適合遍歷對象
3.5 實現深拷貝的方式
淺拷貝 : 拷貝的對象只是一個引用,指向同一個地址,修改數據會影響原數據。
深拷貝: 復制出來的每個對象都有屬于自己的內存空間,不會互相干擾。
1)Json.stringify和Json.parse
如果對象中包含function或RegExp這些就不能用這種方法了
2)函數庫lodash的_.cloneDeep方法
3)使用遞歸的方式實現深拷貝:(如下:)
4)ES6解構
只能深度拷貝對象的第一層,如果對象中的屬性也是對象的話,沒有辦法進行深度拷貝的。
var obj = {name:'123',age:1}; var obj2 = {...obj}5) Object.assign() 對象的合并
只能深度拷貝對象的第一層,如果對象中的屬性也是對象的話,沒有辦法進行深度拷貝的
3.6 localStorage和sessionStorage
都是用來存儲臨時信息,生命周期一個是永久的,一個為當前窗口或標簽頁。
sessionStorage 在同一個頁面中數據共享
localStorage 可以在多個頁面同一瀏覽器共享
3.7 private、protect、public關鍵字
private關鍵字:只在本類中可以使用 默認值
protected關鍵字:在本類及子類中可以使用
public關鍵字:在所有的類中可以使用
四、前端框架
4.1 Vue概述及特點
Vue是一個構建用戶界面的漸進式的Javastrap框架
底層是由JavaScript實現
漸進式:即逐漸做加法的一種模式,例如vue中的雙向綁定的特性,vue中的路由,vue中的vuex等都是選擇性加入的而不是必須的。
Vue特點:
組件化模式
聲明式編碼,讓編碼人員無需直接操作DOM,提高開發效率
4.2 Angular
Angular 應用是模塊化的,它擁有自己的模塊化系統,稱作 NgModule。
Angular特點:
Angula+Typescript,具有較強的模塊化思想,代碼結構較為清晰。
標準化的開發方式,后期能極大的提高開發生產力,提高開發效率。
依賴注入(DI):是當類需要執行其功能時,所需要的服務或對象
其它
vue與angular是數據雙向綁定,而react由于是單向數據流
angular中的雙向數據綁定是基于臟檢查機制
vue的雙向數據綁定是基于ES5的getter和setter來實現
4.3 MVVM
M : model層
VM:視圖模型層(負責View和Model的交互和協作)
V:view層
VM層通過接口從后臺M層請求數據,VM層繼而和V層實現數據雙向數據綁定(業務邏輯層)
我們清楚知道在mvvm架構中,數據層和視圖層是不能直接通信的,所以通過ViewModel來通信,而ViewModel就是定義了一個Observe觀察者。
監聽數據變化,對視圖內容進行更新
監聽視圖變化,通知數據改變
五、Vue知識點總結
5.1 vue生命周期
| beforeCreate: 創建前 | el和data都沒有初始化,不能訪問data、method |
| created :創建后 | vue實例中的data、method已被初始化,屬性也被綁定,但是此時還是虛擬dom,真正dom還沒生成,$el 還不可用。一般進行數據的初始化 |
| beforeMount: 掛載前 | 模板已經編輯完成,但還沒有被渲染至頁面中(即為虛擬dom加載為真實dom) |
| Mounted:掛載后 | 模板已經被渲染成真實DOM,用戶已經可以看到渲染完成的頁面 |
| beforeUpdate:更新前狀態 | view層數據發生變化才會觸發 |
| updated | 數據已經更改完成,dom也重新render完成。 |
| activated | keep-alive 組件激活(顯示)時調用。 |
| deactivated | keep-alive 組件停用(隱藏)時調用。 |
| beforeDestroy | 銷毀前執行 一般在這清除計時器、清除非指令綁定的事件等等 |
| destroyed | 銷毀后 (Dom元素存在,只是不再受vue控制),卸載watcher,事件監聽,子組件。 |
5.2 keep-alive的作用是什么?
顧名思義:保持活躍
vue是組件化變成,有著自己的生命周期從創建到銷毀,如果使用keep-alive的作用就是使組件保持活躍,不會別銷毀掉。
這在實際開發中是非常常見的,比如:
在頁面中可能存在輸入框,選擇框等信息,跳轉路由返回后這些內容不能再清空啊,所以這個時候keep-alive起到非常關鍵的作用。
補充:include和exclude指定是否緩存某些組件 非常靈活根據實際需要使用。
<!-- 指定home組件和about組件被緩存 --> <keep-alive include="home,about" ><router-view></router-view> </keep-alive>5.3 父子組件之間通信方式
父子組件之間的通信
props 和 $emit 最常用的一種方式
ref 通過refs拿到子組件的實例
$children 和 $parent 不方便維護
provide/inject 多用于高階組件庫,平常開發一般不使用,不利于代碼維護
vuex 常用于多個組件需要共享同一狀態時。
舉例:
<!--ref主動尋找子組件組件--><one ref="child"></one> mounted(){//用法:this.$refs['child'].xxx()console.log(this.$refs['child']); }Vuex跨級組件之間傳遞
vuex:單項數據流,在全局通過state存放數據,通過mutation修改state中的數據,如果存在異步操作,需要先通過action再通過mutaion修改state數據。
5.4 Vue中雙向數據綁定
用法: <表單元素 v-model=“變量” >
vue雙向數據綁定是通過數據劫持,結合發布訂閱模式方式來實現的。
核心:Object.defineProperty方法
Object.defineProperty()
語法:Object.defineProperty(obj,prop,descriptor)
obj——要在其上定義屬性的對象。
prop——要定義或修改的屬性的名稱。
descriptor——將被定義或修改的屬性描述符。
不難發現當改變數據的時候會調用set方法 vue中的雙向綁定就是據此實現的。
5.5 自定義組件的雙向數據綁定實現
父組件寫法:
<Child v-model:num="num"></Child> <h1>父組件值:{{num}}</h1>子組件寫法:
<template><div><div>{{ `子組件值: ${num}` }}</div><button @click="click">點擊此處修改值</button></div> </template><script> export default {name: "",data() {return {};},props: {num: {type: Number}},created() {},mounted() {this.valueData = this.num;},methods: {click() {this.valueData++;this.$emit("update:num", this.valueData);}} }; </script>擴展:vue2.3之后提供了sync方式,也能實現雙向綁定 此時子組件中就不需要model的定義了
5.6 $nextTick的使用
官方解釋:將回調延遲到下次DOM更新循環之后執行。
Vue 在更新 DOM 時是異步執行的。當數據發生變化,Vue將開啟一個異步更新隊列,視圖需要等隊列中所有數據變化完成之后,再統一進行更新
在數據變化后執行的某個操作,而這個操作需要使用隨數據變化而變化的DOM結構的時候,這個操作就需要方法在nextTick()的回調函數中。
在vue生命周期中,如果在created()鉤子進行DOM操作,也一定要放在nextTick()的回調函數中。
5.7 computed 和 watch 的區別和運用的場景?
computed: 計算屬性。依賴其它屬性值(一般沒有計算屬性,通過methods也能實現,但是他們之前的區別就是計算屬性是基于它的依賴緩存的,一個計算屬性所依賴的數據發生變化時,它才會重新取值,大大提高了性能)
watch: 監聽數據的變化。更多的是「觀察」的作用,類似于某些數據的監聽回調 ,每當監聽的數據變化時都會執行回調進行后續操作;
運用場景:
computed - 需要進行數值計算,并且依賴于其它數據時
例如:購物車計算價格(只要購買數量,購買價格,優惠券,折扣券等任意一個發生變化,總價都會自動跟蹤變化).
watch擅長處理的場景:一個數據影響多個數據
當我們需要在數據變化時執行異步或開銷較大的操作時,應該使用 watch。
應用場景:1、監聽父組件接收子組件傳過來的值,因為該操作是異步的,子組渲染之后才會被傳。2、監聽路由變化,3,搜索欄
使用watch需要注意的點:
watch有兩個參數;
immediate:組件加載立即觸發回調函數執行,
deep: 深度監聽,為了發現對象內部值的變化,復雜類型的數據時使用,例如數組中的對象內容的改變
watch中的函數名稱必須要和data中的屬性名一致,watch依賴于data中的屬性,data中的屬性發生變化的時候,watch中的函數就會發生變化。
watch不支持緩存;
補充:此處參考網上博客
原文鏈接:https://blog.csdn.net/weixin_44718974/article/details/116201240
5.8 vuex(狀態管理)
屬性介紹:
state: 基本數據(數據源存放地)
getters: 可以讀取state中的數據
mutations : 提交更改數據的方法,同步!
actions : 像一個裝飾器,包裹mutations,使之可以異步。
modules : 模塊化Vuex,每個模塊中都有自己的state、getter、mutations、actions
定義
// 引用 import store from './store'//定義基礎的數據 state: {num: 99},//getter為state的計算屬性 getters: {getNum: (state) => state.num,//獲取num },//mutations可更改狀態的邏輯,同步操作 mutations: {setNum: (state, data) => state.num = data },//提交mutation,異步操作actions: {acSetNum(context, age) {setTimeout(() => {//延時1秒提交至mutations中的方法context.commit("setNum", age);}, 1000);}使用
1)直接使用如下 this.$store.commit("setNum", 999); // mutationsthis.$store.dispatch("acSetNnum"); // actions2)vuex中的輔助函數 import { mapState, mapGetters } from "vuex"; //導入vuex的輔助函數 import { mapMutations, mapActions } from "vuex"; //導入vuex的輔助函數computed: {// 映射 state 中的數據為計算屬性...mapState(["age"]),// 映射 getters 中的數據為計算屬性...mapGetters(["getNum"]), },methods: {//用于生成與 mutations 對話的方法,即:包含 $store.commit(xx) 的函數...mapMutations(["setNum"]),//用于生成與 actions 對話的方法,即:包含 $store.dispatch(xx) 的函數...mapActions(["acSetNum"]), },5.9 v-if與v-show的區別
v-if指令是直接銷毀和重建DOM達到讓元素顯示和隱藏的效果;
v-show指令是通過修改元素的CSS屬性(display)讓其顯示或者隱藏;
使用v-show會更加節省性能上的開銷;當只需要一次顯示或隱藏時,使用v-if更加合理。
v-for優先級比v-if
在vue2中v-for優先級比v-if
在vue3中v-if優先級更高
v-for和v-if在同一標簽中使用也會報錯,解決辦法可以在外面套一個template標簽,或者使用computed來對數組進行過濾然后渲染
六、Vue3.0
6.1 生命周期的變化
Vue3.0中取消了beforeCreate 和 created 兩個階段,同樣的新增了一個 setup
其它變化不大只是名字變了,具體如下:
beforeMount 掛載之前 改名 onBeforeMount
mounted 掛載之后 改名 onMounted
beforeUpdate 數據更新之前 改名 onBeforeUpdate
updated 數據更新之后 改名 onUpdated
beforeDestroy 銷毀前 改名 onBeforeUnmount
destoryed 銷毀后 改名 onUnmounted
6.2 setup函數
setup函數是 Composition API(組合API)的入口
在setup函數中定義的變量和方法最后都是需要 return 出去的不然無法在模板中使用
注意點
setup 函數中,無法使用 data 和 methods 的變量和方法
setup函數中this還不是組件實例,即this就是undefined
setup函數只能是同步的不能是異步的
setup 參數 props
<HelloWorld :msg="msg" state='111' @handle='handleEvent' /> <template v-slot:header>張三 </template> export default {props: {title: String},setup(props) {console.log(props.title)} }因為 props 是響應式的,你不能使用 ES6 解構,它會消除 prop 的響應性。
如果需要解構 props,可以在 setup 函數中使用 toRefs 函數來完成此操作:
如果 title 是可選的 prop,則傳入的 props 中可能沒有 title 。在這種情況下,toRefs 將不會為 title 創建一個 ref 。你需要使用 toRef 替代它:
import { toRef } from 'vue' setup(props) {const title = toRef(props, 'title') }setup 參數 context
<slot name="header"></slot> export default {setup(props, context) {// context.attrs context.slots context.emit context.exposeconsole.log(context.attrs) // {msg: '張三', state: '111'}const handleClick = function() {context.emit('handle', '子級數據傳遞')}return { handleClick }} }context是一個普通的JavaScript對象,不是響應式的因此可以使用ES6解構
export default {setup(props, { attrs, slots, emit, expose }) {...} }注意點:
attrs(獲取當前標簽上的所有屬性的對象) 但是該屬性是props中沒有聲明接收的所有的對象。
如果你使用props去獲取值,同時props中你聲明了你要獲取的值 則:獲取的值是undefined
6.3 組件之間的通信
與vue2.0唯一的區別就是寫法上了,如下子組件寫法:
<script setup lang="ts">import { ref } from 'vue'const emit = defineEmits(['changeItem'])const props = defineProps({type: Number,children: Array})const changeChild = (stuId) => {emit('changeItem', stuId)}</script>七、常見要點分析
7.1 SPA(單頁應用)首屏加載速度慢
首屏加載:瀏覽器從響應用戶輸入網址地址,到首屏內容渲染完成的時間。
-
加載慢的原因
網絡問題;資源文件過大;請求過多;渲染內容阻塞等。
-
解決方案
減小入口文件體積 (常用手段路由懶加載)
靜態資源本地緩存(前端合理使用localStorage;后端采用http緩存,設置Cache-Control,Last-Modified,Etag等響應頭)
圖片資源的壓縮 (適當壓縮、在線字體圖標,或者雪碧圖來減輕http請求壓力)
使用SSR(服務端渲染)
7.2 如何實現路由懶加載
vue組件異步加載
{path: '/xxx',name: 'cName',component: resolve => require(['./components/xxx.vue'], resolve) } // 實現懶加載,一個組件會生成一個js文件ES6標準語法import() (推薦使用)
routes:[ path: 'xxx',name: 'cName',component: () => import('./components/xxx.vue') ]webpack的require,ensure()
const HelloWorld = resolve =>{require.ensure([],()=>{resolve(require('@/components/HelloWorld'))}) }routes:[{{path: './', name: 'HelloWorld',component: HelloWorld} }]7.3 前端如何理解面向對象
在理解面向對象之前先理解一下面向過程編程:
即按步驟編程(函數和變量)
而面向對象呢?是將我們的需求分析成一個一個對象,利用對象中的屬性和方法最后按照步驟編程。
面向對象特點:
1)抽象
核心的東西抽出來,把與我們要解決的問題有關的東西拿出來擺在面前。
比如我們熟知的date對象,我們知道它的一個方法getFullYear,我們不需要知道它的原理,而是會用就行。
2)封裝
把一個具有相同的特征和行為的客觀事物封裝成抽象的類。
3)繼承
讓某一個類型的對象獲得另一個類型對象的屬性和方法。
4)多態
一個類實例中的相同方法和屬性在不同場景有不同的表現形式。
7.4 如何理解構造函數
構造函數:可以理解為把對象里的一下屬性和方法抽象出來封裝到函數里面
構造函數主要用來在創建對象時完成對對象屬性的一些初始化等操作, 當創建對象時, 對象會自動調用它的構造函數。
構造函數和對象的區別:
對象是一個具體事物,構造函數實際上是一個泛類
利用構造函數創建對象的過程也稱為對象的實例化
7.5 prototype(原型)的理解(可以先看7.6再看7.5)
prototype屬性是函數獨有的,從一個函數指向一個對象,它的含義是函數的原型對象,也就是這個函數所創建的實例的原型對象。
分析: 舉例如下代碼(看注釋)
let arr = [1,2,3,4,5]; // 字面量寫法 // 實際是是使用了內置內Array let arr = new Array(1,2,3,4,5) // 此時我們可以使用arr.push(6) 向數組中添加一個元素 // 但是此時arr這個對象是沒有push方法的 它又是如何做到的呢? // 這個時候 Array.prototype 出來了。 // 系統會默認基于 __proto__進行查找,第一個查找的就是 Array.prototype,發現存在即開始執行push方法。7.6 __proto__的理解
__proto__和constructor屬性是對象所獨有的;
proto__屬性都是由一個對象指向一個對象(指向它們的原型對象,也可以理解為父對象)
每一個對象(除null)都會有的屬性__proto,這個屬性指向該對象的原型。
分析
由此可見上文中的arr這個對象的原型即arr__proto__ == Array.prototype 兩者完全一樣。
這么理解下來上文就更加清晰了
7.6 constructor介紹
constructor屬性也是對象才擁有的,它是從一個對象指向一個函數,含義就是指向該對象的構造函數
舉例分析
function Person(){} var person1 = new Person() person1.name = "zyzhang" // true console.log(Person === Person.prototype.constructor);7.7 微任務與宏任務
JavaScript的一大特點就是單線程, 同一時間只能做一件事情,主要和它的用途有關, JavaScript主要是控制和用戶的交互以及操作DOM。注定它是單線程。
所以如果全部代碼都是同步執行的,這會引發很嚴重的問題,比方說我們要從遠端獲取一些數據,難道要一直循環代碼去判斷是否拿到了返回結果么?就像去飯店點餐,肯定不能說點完了以后就去后廚催著人炒菜的,會被揍的。
于是就有了異步事件的概念,注冊一個回調函數,比如說發一個網絡請求,我們告訴主程序等到接收到數據后通知我,然后我們就可以去做其他的事情了。
任務隊列與事件循環:
1、所有的同步任務都在主線程上執行,行成一個執行棧。
2、主線程之外,還存在一個"任務隊列"(task queue)。只要異步任務有了運行結果,就在"任務隊列"之中放置一個事件。
3、 一旦"執行棧"中的所有同步任務執行完畢,系統就會讀取"任務隊列",看看里面有哪些事件。那些對應的異步任務,于是結束等待狀態,進入執行棧,開始執行。
4、主線程不斷重復上面的第三步。
JavaScript 把異步任務又做了進一步的劃分,異步任務又分為:微任務和宏任務
宏任務:
setTimeout、setInterval
異步 Ajax 請求
文件操作
script中整體的代碼
UI渲染
DOM事件
微任務:
Promise 、 async/await
執行順序如何?看懂下面兩張圖就基本OK了
7.8 async 與 await
1、async 告訴程序這是一個異步,awiat 會暫停執行async中的代碼,等待await 表達式后面的結果,跳過async 函數,繼續執行后面代碼
2、async 函數會返回一個Promise 對象,那么當 async 函數返回一個值時,Promise 的 resolve 方法會負責傳遞這個值;當 async 函數拋出異常時,Promise 的 reject 方法也會傳遞這個異常值
3、await 操作符用于等待一個Promise 對象,并且返回 Promise 對象的處理結果(成功把resolve 函數參數作為await 表達式的值),如果等待的不是 Promise 對象,則用 Promise.resolve(xx) 轉化
7.9 JS當中的防抖(debounce)與節流(throttle)
防抖只會在最后一次事件后執行觸發函數,節流不管事件多么的頻繁,都會保證在規定時間段內觸發事件函數。
防抖
指觸發事件后在 n 秒內函數只能執行一次,如果在 n 秒內又觸發了事件,則會重新計算函數執行時間。
節流
判斷是否達到一定的時間來觸發事件。某個時間段內只能觸發一次函數。
函數防抖(debounce)
- search搜索聯想,用戶在不斷輸入值時,用防抖來節約請求資源;
- window觸發resize的時候,不斷的調整瀏覽器窗口大小會不斷的觸發這個事件,用防抖來讓其只觸發一次
函數節流(throttle)
- 鼠標不斷點擊觸發,mousedown(單位時間內只觸發一次)
- 監聽滾動事件,比如是否滑到底部自動加載更多,用throttle來判斷
舉例分析:
<!DOCTYPE html> <html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>防抖與節流</title><style>.input {width: 300px;height: 45px;border: 1px solid #ddd;border-radius: 5px;text-indent: 6px;font-size: 18px;}</style></head><body><input class="input" oninput="change(event)" onporpertychange="change(event)" /><input class="input" oninput="change2(event)" onporpertychange="change2(event)" /></body><script>change = debounce((e)=>{console.log("防抖======",e.target.value)},500, true) // true: 立即執行 false: 延遲change2 = throttle((e)=>{console.log("節流======",e.target.value)},500, 1) // 1: 時間戳 2: 定時// 防抖function debounce(func,delay,immediate) {let timer, context, args;return function() {context = this;args = arguments;if (timer) clearTimeout(timer);if(immediate) {let callNow = !timer;timer = setTimeout(()=>{timer = null;},delay)if(callNow) func.apply(context,args)} else {timer = setTimeout(()=>{func.apply(context,args)},delay)}}}// 節流function throttle(func,delay,type) {let timer, context, args, previous = 0;return function() {context = this;args = arguments;if(type == 1) { // 時間戳let now = Date.now();if (now - previous > delay) { func.apply(context,args);previous = now;}} else { // 定時if(!timer) {timer = setTimeout(()=>{timer = null;func.apply(context,args)},delay);}}}}</script> </html>7.10 JS當中的this
定義:當前執行上下文(global、function或eval)的一個屬性, 在非嚴格模式下,總指向一個對象;在嚴格模式下可以是任意值。
在全局上下文中,函數調用中直接使用this,this指向window
通過對象調用,this指向調用方法的對象
箭頭函數——this與所在上下文this指向相同
構造函數——this指向構造出的對象
案例分析,請問如下代碼中的this指向什么:
var a = 0; var obj = {a: 2,foo: function(){function test(){console.log(this); }return test;} } obj.foo()()分析:obj.foo()執行完畢返回test,然后變成了test()所以屬于函數的獨立調用。
鞏固練習-如下代碼請分析:
var a = 0; function foo(){console.log(this); } var obj = { a: 2, foo: foo } obj.foo() // var bar = obj.foo; // bar()上述等價于
var obj = { a: 2, foo: function() {console.log(this);} } obj.foo() // 所以此處屬于對象方法調用 因此this指向objvar bar = obj.foo 等價于
var bar = function() {console.log(this) } // 此時 bar() 很明顯屬于函數的獨立調用 因此指向 window7.11 JS當中的call()、apply()
先看如下代碼,請分析console.log打印結果:
var obj = {myFun: function(...agreement){console.log(this.name + ":" + this.age); } } var db = {name: "德瑪",age: 99} obj.myFun(db,'a','b','c'); // 屬于對象方法的調用 this指向obj obj.myFun(db,[1,2,3]); // 屬于對象方法的調用 this指向obj輸出結果undefined,因為obj對象中并沒有name屬性和age屬性
再看如下代碼:
由此可見call方法和apply方法能夠改變this指向。
補充說明:還有另外一個作用:借用別的對象的方法(用一個對象替換掉另一個對象(this))
7.12 事件冒泡和事件捕獲
事件冒泡:從下至上,當給父子元素的同一事件綁定方法的時候(比如click點擊事件),觸發子元素身上的事件,執行完畢之后,也會觸發父級元素相同的事件。
事件捕獲:從上至下到指定元素,當出發子元素身上到事件的時候,先觸發父元素,然后再傳遞給子元素。
阻止事件冒泡
e.stopPropagation()
vue中直接使用.stop
補充:(vue事件修飾符)
.prevent -------等于javascript的event.preventDefault() 阻止默認程序的運行
capture 作用:打亂冒泡順序
.self 作用:不讓子元素的事件觸發自己綁定的事件,但是不會阻止冒泡!
.once 顧名思義,事件只會觸發一次
7.13 cookie、session與token
cookie 存儲在客戶端
當訪問一個網站,客戶端發送一個請求到服務器,服務器會返回set-cookie頭部;
客戶端保存cookie,之后向服務器發送請求時,httpRequest請求都會包含一個cookie頭部;
最后服務端返回響應數據
session: 會話,保存于服務端
服務器為每個用戶瀏覽器創建一個會話對象(session對象)
token令牌;當客戶端登錄后服務器端收到請求后去驗證,驗證成功后服務器會返回一個token發送給客戶端;
客戶端將token存儲起來;后面每次請求時帶上token,服務器端收到請求先驗證token,驗證成功返回請求數據。
區別:
token更適用于移動應該;cookie不支持手機端訪問;
token支持跨域訪問;cookie不支持跨域訪問;
Session 是一種記錄服務器和客戶端會話狀態的機制,使服務端有狀態化,可以記錄會話信息。而 Token 是令牌,訪問資源接口(API)時所需要的資源憑證。Token 使服務端無狀態化,不會存儲會話信息。
八、微信小程序
8.1 應用的生命周期函數
onLaunch:小程序初始化完成后調用。
onShow:初始化后或者切回前臺時會觸發。
onHide:切到后臺時觸發
8.2 Page頁面的生命周期
onLoad:頁面加載的時觸發,一個頁面只調用1次
onShow:頁面的顯示。
onReady:監聽頁面初次渲染完成,一個頁面只調用1次
onHide:頁面隱藏但未卸載的時候觸發的,如 wx.navigateTo 或底部tab切換到其他頁面,小程序切入后臺等。
onUnload:頁面卸載時觸發,如wx.redirectTo或wx.navigateBack到其他頁面時。
8.3 Component的生命周期
created 當組件實例剛被創建時
attached 在組件完全初始化完畢并且進入頁面節點樹后, attached生命周期被觸發。
detached 組件離開頁面節點樹后, detached生命周期被觸發。
ready 視圖層布局完成。
九、UniApp
8.1 應用的生命周期函數
onLaunch:當uni-app 初始化完成時觸發(全局只觸發一次)
onShow:當 uni-app 啟動,或從后臺進入前臺顯示
onHide:當 uni-app 從前臺進入后臺
onError: 當 uni-app 報錯時觸發
8.2 頁面的生命周期
onInit:監聽頁面初始化
onLoad: 監聽頁面的加載
onShow:頁面的顯示。
onReady:監聽頁面初次渲染完成。
onHide:監聽頁面隱藏
onUnload:監聽頁面隱藏
onResize:監聽窗口尺寸變化
onPullDownRefresh
onReachBottom
…
總結
以上是生活随笔為你收集整理的你不得不熟悉且熟练掌握的前端知识的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux多进程编程
- 下一篇: HTML+CSS期末大作业 中国传统美食