Vue2和Vue3的區(qū)別
雙向數(shù)據(jù)綁定原理不同
Vue2 的雙向數(shù)據(jù)綁定是利用ES5的一個(gè)APIObject.definePropert()
對(duì)數(shù)據(jù)進(jìn)行劫持,結(jié)合發(fā)布訂閱模式的方式來實(shí)現(xiàn)的。Vue3 中使用ES6的Proxy API
對(duì)數(shù)據(jù)代理。Vue2 不支持碎片。Vue3 支持碎片,就是說可以擁有多個(gè)根節(jié)點(diǎn)
API 類型不同
(1) Vue2 使用選項(xiàng)類型api,在代碼里分割了不同的屬性:data,computed,method等。
(2) Vue3 使用合成型api, 能讓我們使用方法來分割,相比于舊的api 使用屬性來分組,這樣代碼會(huì)更加簡便和整潔。定義數(shù)據(jù)變量和方法不同
Vue2是把數(shù)據(jù)放到了data 中,在 Vue2中 定義數(shù)據(jù)變量是data(){},創(chuàng)建的方法要在method:{}
Vue3 就需要使用一個(gè)新的setup()方法,此方法在組件初始化構(gòu)造的時(shí)候觸發(fā),設(shè)立響應(yīng)式數(shù)據(jù):1)從vue 引入 reactive;2)使用 reactive ()方法來聲明數(shù)據(jù)為響應(yīng)性數(shù)據(jù);3) 使用setup()方法來返回我們的響應(yīng)性數(shù)據(jù),從而template 可以獲取這些響應(yīng)性數(shù)據(jù)。-
生命周期鉤子函數(shù)不同
Vue2 中的生命周期:beforeCreate 組件創(chuàng)建之前;created 組建創(chuàng)建之后;beforeMount 組件掛載到頁面之前執(zhí)行;Mounted 組件掛載到頁面之后執(zhí)行,beforeUpdate 組件更新之前;updated組件更新之后
Vue3 中的生命周期:setup 開始創(chuàng)建組件;onBeforeMount 組件掛載到頁面之前執(zhí)行;onMounted 組件掛載到頁面之后執(zhí)行;onBeforeUpdate 組件更新之前;onUpdated 組件更新之后;而且 Vue3 生命周期在調(diào)用前需要先進(jìn)行引入。除了這些鉤子函數(shù)外,Vue3 還增加了 onRenderTracked 和onRenderTriggered 函數(shù)。
父子傳參不同
Vue2 父傳子,會(huì)調(diào)用this$emit 然后傳入事件名和對(duì)象。
Vue3 父傳子,在Vue3 中的setup()中的第一參數(shù)content 對(duì)象中就有 emit,那么我們只要在setup()接收第二個(gè)參數(shù)中使用分解對(duì)象法取出emit 就可以在setup 方法中隨意使用了。指令與插槽不同
Vue2 中使用slot 可以直接使用slot ;v-for 與v-if 在Vue2中優(yōu)先級(jí)高的是v-for 指令,而且不建議一起使用。
Vue3 中必須是使用v-slot的形式;vue 3中v-for 與v-if ,只會(huì)把當(dāng)前v-if 當(dāng)作v-for 的一個(gè)判斷語句,不會(huì)相互沖突;
Pinia和Vuex 區(qū)別
Vuex和Pinia都是用于狀態(tài)管理的庫,但它們有一些區(qū)別。
- 架構(gòu)設(shè)計(jì):Vuex是Vue.js官方提供的狀態(tài)管理庫,而Pinia是由Vue作者維護(hù)的另一個(gè)狀態(tài)管理庫。Vuex采用了集中式的架構(gòu),將所有的狀態(tài)存儲(chǔ)在一個(gè)單一的全局狀態(tài)樹中,通過mutations和actions來修改和處理狀態(tài)。而Pinia采用了去中心化的架構(gòu),將狀態(tài)分布在多個(gè)模塊中,每個(gè)模塊擁有自己的狀態(tài)、mutations和actions。,它專注于提供一個(gè)簡單的API來管理應(yīng)用程序的狀態(tài)。相比之下,Vuex是一個(gè)更完整的狀態(tài)管理庫,它提供了更多的功能,比如模塊化、插件和嚴(yán)格模式等。Pinia是基于Vue 3的Composition API構(gòu)建的。
體積和復(fù)雜性:由于Vuex是Vue.js的官方狀態(tài)管理庫,它在Vue.js項(xiàng)目中廣泛使用,并擁有龐大的生態(tài)系統(tǒng)。相比之下,Pinia是一個(gè)相對(duì)較新的庫,較小且更簡單。這使得Pinia在一些小型或簡單的項(xiàng)目中可能更容易上手,而Vuex則更適合大型和復(fù)雜的項(xiàng)目。
TypeScript 支持:在類型安全性方面,Vuex從Vue 2.x版本開始引入了對(duì)TypeScript的支持,但需要使用額外的插件來實(shí)現(xiàn)類型檢查。而Pinia在設(shè)計(jì)之初就對(duì)TypeScript提供了原生的支持,提供了更好的類型推導(dǎo)和類型檢查的支持。
代碼風(fēng)格和語法:Vuex使用了更傳統(tǒng)的mutations和actions的方式來修改和處理狀態(tài),而Pinia更加傾向于直接操作狀態(tài)。
Vue Router如何實(shí)現(xiàn)?如何匹配路徑分發(fā)組件?
https://blog.csdn.net/weixin_42122355/article/details/117968861
https://wenku.baidu.com/view/93c3c8db834d2b160b4e767f5acfa1c7ab008221.html?wkts=1709687718511&bdQuery=Vue+Route%E5%A6%82%E4%BD%95%E5%8C%B9%E9%85%8D%E8%B7%AF%E5%BE%84%E5%88%86%E5%8F%91%E7%BB%84%E4%BB%B6%3F&needWelcomeRecommand=1
<Keep-alive>保存的是什么?內(nèi)部子組件狀態(tài)會(huì)保留嗎?會(huì)執(zhí)行生命周期嗎?
<keep-alive>
是 Vue.js 提供的一個(gè)抽象組件,用于緩存其內(nèi)部的子組件狀態(tài)而不銷毀它們。當(dāng)子組件被包裹在 <keep-alive> 組件內(nèi)時(shí),Vue.js 會(huì)將這些子組件緩存起來,而不是每次切換時(shí)銷毀和重新創(chuàng)建子組件。
<keep-alive> 保存的內(nèi)容:
組件狀態(tài):<keep-alive> 會(huì)保存子組件的狀態(tài),包括數(shù)據(jù)、DOM 狀態(tài)和子組件的實(shí)例。
DOM 元素:子組件的 DOM 結(jié)構(gòu)也會(huì)被保留在內(nèi)存中,這樣在重新激活時(shí)可以直接顯示,而不需要重新渲染。
內(nèi)部子組件狀態(tài)保留:
內(nèi)部子組件狀態(tài)會(huì)保留:在 <keep-alive> 包裹的子組件中,子組件的狀態(tài)會(huì)得到保留,包括數(shù)據(jù)、計(jì)算屬性等,在切換到該子組件時(shí),不需要重新初始化和獲取數(shù)據(jù)。
子組件生命周期鉤子執(zhí)行:
- activated 生命周期鉤子:當(dāng)組件在 <keep-alive> 中被激活時(shí)(被切換到),會(huì)觸發(fā)activated生命周期鉤子,可以在這個(gè)鉤子中執(zhí)行需要在組件顯示時(shí)進(jìn)行的操作。
- deactivated 生命周期鉤子:當(dāng)組件在 <keep-alive> 中被停用(被切換出去)時(shí),會(huì)觸發(fā)deactivated生命周期鉤子,可以在這個(gè)鉤子中執(zhí)行需要在組件隱藏時(shí)進(jìn)行的操作。
<keep-alive> 對(duì)內(nèi)部子組件的狀態(tài)進(jìn)行了緩存,可以節(jié)省資源和提高性能,同時(shí)能夠保留子組件的狀態(tài)和 DOM 結(jié)構(gòu),在特定情況下可以避免了頻繁的初始化和渲染操作。
Computed值什么時(shí)候變化
computed是vue的計(jì)算屬性,是根據(jù)依賴關(guān)系進(jìn)行緩存的計(jì)算,只有在它的相關(guān)依賴發(fā)生改變時(shí)才會(huì)進(jìn)行更新。
computed的每一個(gè)計(jì)算屬性都會(huì)被緩存起來,只要計(jì)算屬性所依賴的屬性發(fā)生變化,計(jì)算屬性就會(huì)重新執(zhí)行,視圖也會(huì)更新。
應(yīng)用場景:
當(dāng)一個(gè)數(shù)據(jù)受多個(gè)數(shù)據(jù)影響時(shí),可以使用computed
1.本組件計(jì)算
2.計(jì)算props的值
3.計(jì)算vuex的state或者getters值的變化
如何優(yōu)化Vue的性能
一、渲染優(yōu)化
v-for
避免v-if和v-for的同級(jí)使用,v-for的優(yōu)先級(jí)比v-if高,會(huì)導(dǎo)致數(shù)據(jù)渲染錯(cuò)誤
v-for設(shè)置key的值,盡量不適用index,使用數(shù)據(jù)中唯一的標(biāo)識(shí),有利于dom的定位與diff。v-show和v-if的選擇
經(jīng)常復(fù)用的組件用v-show來渲染(v-show是隱藏不銷毀)
相反則用v-if(直接判斷是否創(chuàng)建)長列表優(yōu)化
純粹做數(shù)據(jù)展示,不需要熱更新
處于data中的數(shù)據(jù)會(huì)被監(jiān)視,發(fā)生變化時(shí)數(shù)據(jù)就發(fā)生變化
所以采用object.freeze(數(shù)據(jù))方法凍結(jié)數(shù)據(jù)。長列表
采用虛擬滾動(dòng),只渲染少部分區(qū)域的內(nèi)容
只渲染視口部分的數(shù)據(jù),也就是說渲染的DOM節(jié)點(diǎn)個(gè)數(shù)是固定的
自己封裝:
數(shù)據(jù)一次性給:
元素監(jiān)聽scroll事件(滾動(dòng)事件)
計(jì)算可視化高度一次能裝幾個(gè)列表,然后從總數(shù)據(jù)中進(jìn)行slice截取
每一次滾動(dòng)后根據(jù)scrollTop值獲取一個(gè)可以整除itemH結(jié)果進(jìn)行偏移(scrollTop:滾動(dòng)條移動(dòng)的距離)
- keep-alive緩存頁面
- 減少后臺(tái)訪問
- 路由懶加載
- 圖片懶加載
Token、Cookie、Session、LocalStorage 的介紹及區(qū)別:
-
Token:
- 定義:Token是一種用于身份驗(yàn)證和授權(quán)的令牌,通常由服務(wù)器頒發(fā)給客戶端,并在客戶端持有。
- 使用:Token通常被放置在請求的頭部(Header)中,用于驗(yàn)證用戶的身份,可以用于實(shí)現(xiàn)用戶認(rèn)證和授權(quán)。
- 特點(diǎn):Token通常是無狀態(tài)的,服務(wù)器不會(huì)在后端存儲(chǔ)Token,而是由客戶端攜帶Token以完成驗(yàn)證過程。
-
Cookie:
- 定義:Cookie是在客戶端存儲(chǔ)的一小段文本信息,由服務(wù)器發(fā)送給瀏覽器,瀏覽器會(huì)將Cookie保存在客戶端。
- 使用:主要用于跟蹤用戶的會(huì)話狀態(tài)、存儲(chǔ)用戶偏好設(shè)置等。
- 特點(diǎn):Cookie可以設(shè)置過期時(shí)間,可以在瀏覽器和服務(wù)器之間來回傳遞數(shù)據(jù)。
-
Session:
- 定義:Session是在服務(wù)器端存儲(chǔ)的關(guān)聯(lián)用戶會(huì)話的信息,通常通過唯一的標(biāo)識(shí)符來綁定用戶的會(huì)話。
- 使用:用于保持用戶會(huì)話狀態(tài),存儲(chǔ)用戶登錄狀態(tài)、數(shù)據(jù)等。
- 特點(diǎn):Session存儲(chǔ)在服務(wù)器端,相對(duì)于Cookie更安全,但會(huì)占用服務(wù)器資源。
-
LocalStorage:
- 定義:LocalStorage是瀏覽器提供的一種用于存儲(chǔ)較大量數(shù)據(jù)的機(jī)制,存儲(chǔ)在客戶端瀏覽器中,數(shù)據(jù)不會(huì)失效。
- 使用:用于本地存儲(chǔ)數(shù)據(jù),持久保存在客戶端瀏覽器中。
- 特點(diǎn):LocalStorage數(shù)據(jù)保留在瀏覽器中,跨頁面和刷新后數(shù)據(jù)依然存在,不會(huì)隨著會(huì)話結(jié)束而失效,比較適合長期存儲(chǔ)。
-
區(qū)別:
- 位置:Token、Cookie、LocalStorage存儲(chǔ)在客戶端,Session存儲(chǔ)在服務(wù)器端。
- 生命周期:Cookie和LocalStorage有時(shí)效期限,Session在一定時(shí)間內(nèi)有效,Token通常不過期。
- 容量:Cookie的存儲(chǔ)容量有限,LocalStorage相對(duì)較大,Session取決于服務(wù)器資源的限制,Token不占用服務(wù)器資源。
- 安全性:Token相對(duì)較安全,Cookie存在安全性問題,Session相對(duì)安全,LocalStorage較為易受 XSS 攻擊。
- 跨域:Token可以跨域使用,Cookie的跨域有限制,Session一般不跨域,LocalStorage是域名限定的。
原生JS綁定的點(diǎn)擊事件
可以使用addEventListener()函數(shù)來添加點(diǎn)擊事件的處理程序,
addEventListener()函數(shù):
第一個(gè)參數(shù)event:監(jiān)聽的事件名稱
第二個(gè)參數(shù)是函數(shù):需要執(zhí)行的事件
第三個(gè)參數(shù)是useCapture(變量):用來判斷是捕獲還是冒泡
1)當(dāng)useCapture為true的時(shí)候是在捕獲階段觸發(fā)事件 (捕獲事件觸發(fā)順序是由父到子)
2)當(dāng)useCapture為false的時(shí)候是在冒泡階段觸發(fā)事件(默認(rèn)為false)(冒泡事件觸發(fā)順序是由子到父)
3)第三個(gè)參數(shù)不一定是 bool 值,也可以是個(gè)對(duì)象,它提供了更多選項(xiàng)。
once:只執(zhí)行一次。
passive:承諾此事件監(jiān)聽不會(huì)調(diào)用 preventDefault,這有助于性能。
useCapture:是否捕獲(否則冒泡)。
事件冒泡和事件捕獲
冒泡事件:事件由子元素傳遞到父元素的過程叫做冒泡
捕獲事件:事件由父元素傳遞到子元素的過程叫做事件捕獲
阻止冒泡與阻止默認(rèn)
1.阻止冒泡就是讓我們的層級(jí)事件不再觸發(fā),在點(diǎn)擊子級(jí)時(shí),父級(jí)不會(huì)觸發(fā)點(diǎn)擊事件。一般我們使用e.stoppropagation();來阻止冒泡。
2.阻止默認(rèn):一般我們在文檔中想復(fù)制一些文字,按住就可以勾選,但是當(dāng)我們使用了阻止默認(rèn),內(nèi)容就無法勾選。通常我們使用e.preventDefault()方法來阻止默認(rèn)。
3.總結(jié):e.stoppropagation()阻止冒泡 e.preventDefault()阻止默認(rèn) return false;既阻止冒泡又阻止默認(rèn)。
onclick和addEventListener('click',handler)的區(qū)別
1.addEventListener可以同時(shí)綁定多個(gè)事件,onclick只能綁定一個(gè)
2.addEventListener我們可以決定DOM事件的觸發(fā)是以事件捕獲的事件流還是事件冒泡的事件流方式
3.onclick移除事件直接等于null即可,但addEventListener
需要div.removeEventListener
HTTP 狀態(tài)碼:
HTTP 狀態(tài)碼是作為 HTTP 協(xié)議的一部分,用于指示客戶端和服務(wù)器之間請求的處理情況。以下是常見的 HTTP 狀態(tài)碼類別及其含義:
1xx - 信息性狀態(tài)碼:
100 Continue:服務(wù)器已接收請求的初始部分,等待客戶端繼續(xù)發(fā)送其余部分。
101 Switching Protocols:服務(wù)器已切換協(xié)議,客戶端應(yīng)切換到新協(xié)議。2xx - 成功狀態(tài)碼:
200 OK:請求成功。
201 Created:請求已經(jīng)被創(chuàng)建。
204 No Content:沒有返回內(nèi)容。3xx - 重定向狀態(tài)碼:
301 Moved Permanently:請求的資源已經(jīng)被永久移動(dòng)到新的位置。
302 Found:請求的資源臨時(shí)移動(dòng)到新的位置。
304 Not Modified:資源未修改,仍可使用緩存版本。4xx - 客戶端錯(cuò)誤狀態(tài)碼:
400 Bad Request:請求無效。
401 Unauthorized:請求未經(jīng)授權(quán)。
403 Forbidden:禁止訪問。
404 Not Found:資源未找到。5xx - 服務(wù)器錯(cuò)誤狀態(tài)碼:
500 Internal Server Error:服務(wù)器內(nèi)部錯(cuò)誤。
502 Bad Gateway:網(wǎng)關(guān)錯(cuò)誤。
503 Service Unavailable:服務(wù)不可用。
504 Gateway Timeout:網(wǎng)關(guān)超時(shí)。
Vue循環(huán)時(shí)綁定的key有什么作用
- 性能優(yōu)化:Vue 使用 key 來最小化 DOM 的操作,有助于提高列表的性能。使用 key 可以告訴 Vue 哪些元素是已經(jīng)存在的、新增的或被移除的,從而幫助 Vue 優(yōu)化列表的渲染過程。
- 維護(hù)組件狀態(tài):設(shè)置 key 可以幫助 Vue 識(shí)別每個(gè)列表項(xiàng),從而在列表重新渲染時(shí)保留組件的狀態(tài)。如果不為列表項(xiàng)設(shè)置 key,在列表變化時(shí)可能會(huì)導(dǎo)致組件的狀態(tài)丟失或混亂。
- 唯一性:key 必須在同一級(jí)的兄弟元素中具有唯一性,確保 Vue 能夠正確地識(shí)別每個(gè)列表項(xiàng),準(zhǔn)確地跟蹤列表項(xiàng)的變化。
redux
1.redux 是一個(gè)獨(dú)立專門用于做狀態(tài)管理的 JS 庫(不是 react 插件庫)
2.它可以用在 react, angular, vue 等項(xiàng)目中, 但基本與 react 配合使用
3.作用: 集中式管理 react 應(yīng)用中多個(gè)組件共享的狀態(tài)
- redux與Vuex的區(qū)別
vuex定義了state、getter、mutation、action四個(gè)對(duì)象;redux定義了state、reducer、action。
vuex觸發(fā)方式有兩種commit同步和dispatch異步;redux同步和異步都使用dispatch
Redux 使用的是不可變數(shù)據(jù),而Vuex的數(shù)據(jù)是可變的。Redux每次都是用新的state替換舊的state,而Vuex是直接修改
Redux 在檢測數(shù)據(jù)變化的時(shí)候,是通過 diff 的方式比較差異的,而Vuex其實(shí)和Vue的原理一樣,是通過 getter/setter來比較的
防抖和節(jié)流
防抖 :指在一定時(shí)間內(nèi),多次觸發(fā)同一個(gè)事件,只執(zhí)行最后一次操作。使用防抖技術(shù),將一定時(shí)間內(nèi)的多次觸發(fā)合并為一次操作,只請求一次服務(wù)器數(shù)據(jù),減少了請求次數(shù)和服務(wù)器負(fù)載。
節(jié)流 :指在一定時(shí)間內(nèi),多次觸發(fā)同一個(gè)事件,只執(zhí)行第一次操作。例如,當(dāng)我們拖動(dòng)網(wǎng)頁上的滾動(dòng)條時(shí),會(huì)不斷觸發(fā) onscroll 事件,如果每次觸發(fā)都去計(jì)算滾動(dòng)距離,會(huì)造成瀏覽器性能下降。此時(shí)就可以使用節(jié)流技術(shù),將一定時(shí)間內(nèi)的多次觸發(fā)限制為一次操作,只計(jì)算一次滾動(dòng)距離,提高了瀏覽器性能和用戶體驗(yàn)。
防抖的應(yīng)用場景:
1. 搜索框?qū)崟r(shí)搜索:在搜索框中輸入關(guān)鍵詞時(shí),防抖可以延遲請求發(fā)送,只在用戶輸入完成或者停頓一段時(shí)間后才觸發(fā)實(shí)際的搜索請求,避免頻繁的網(wǎng)絡(luò)請求。
2. 窗口大小調(diào)整:當(dāng)用戶調(diào)整瀏覽器窗口大小時(shí),窗口大小變化事件會(huì)連續(xù)觸發(fā),使用防抖可以確保只在用戶完成調(diào)整后再執(zhí)行相應(yīng)的響應(yīng)邏輯,以避免過多的布局計(jì)算。
節(jié)流的應(yīng)用場景:
1. 頁面滾動(dòng)加載:在無限滾動(dòng)的頁面中,滾動(dòng)事件會(huì)頻繁觸發(fā),使用節(jié)流可以控制數(shù)據(jù)加載的頻率,防止短時(shí)間內(nèi)多次加載數(shù)據(jù),提高頁面加載性能。
2. 按鈕防重復(fù)點(diǎn)擊:當(dāng)用戶點(diǎn)擊按鈕執(zhí)行某個(gè)操作時(shí),使用節(jié)流可以確保按鈕在一定時(shí)間內(nèi)只能觸發(fā)一次,防止用戶重復(fù)點(diǎn)擊造成誤操作。
JS的事件循環(huán)
JavaScript事件循環(huán)是一種處理異步事件和回調(diào)函數(shù)的機(jī)制,它是JavaScript實(shí)現(xiàn)異步編程的核心。JavaScript事件循環(huán)是為了解決JavaScript作為單線程語言時(shí)的并發(fā)性問題而設(shè)計(jì)的,引入了異步編程模型和事件循環(huán)機(jī)制,它可以監(jiān)聽消息隊(duì)列中的事件并根據(jù)優(yōu)先級(jí)順序依次執(zhí)行相應(yīng)的回調(diào)函數(shù)。
這種機(jī)制允許JavaScript在等待某些操作完成的同時(shí),可以執(zhí)行其他任務(wù),從而避免了阻塞,提高了效率和并發(fā)性。
JavaScript的事件循環(huán)是一種用于管理執(zhí)行長期運(yùn)行任務(wù)的機(jī)制,它允許瀏覽器處理用戶交互、DOM事件、setTimeout回調(diào)和其他異步任務(wù),而不會(huì)阻塞UI。
事件循環(huán)基本步驟如下:
檢查宏任務(wù)隊(duì)列(如setTimeout的回調(diào)、setInterval的回調(diào)、用戶輸入、UI交互等)。執(zhí)行一個(gè)宏任務(wù)。
檢查微任務(wù)隊(duì)列(如Promise的回調(diào)、MutationObserver的回調(diào)等)。執(zhí)行所有微任務(wù)。
返回步驟1,重復(fù)這個(gè)過程,直到宏任務(wù)隊(duì)列和微任務(wù)隊(duì)列都為空。
如何實(shí)現(xiàn)響應(yīng)式對(duì)象
響應(yīng)式:可以自動(dòng)響應(yīng)數(shù)據(jù)變量的代碼機(jī)制,如:當(dāng)有一個(gè)值發(fā)生了變化,引用了這個(gè)值的地方會(huì)自動(dòng)重新執(zhí)行
將一個(gè)普通對(duì)象轉(zhuǎn)為一個(gè)響應(yīng)式對(duì)象,即通過reactive函數(shù),他接收一個(gè)普通對(duì)象,返回的是一個(gè)proxy對(duì)象。
在reactive函數(shù)中,需要用到porxy的兩個(gè)捕獲器get與set,get是用來收集依賴的,當(dāng)我們對(duì)象的某個(gè)屬性值變化時(shí),我們可以在set捕獲器中捕獲到,讓他重新執(zhí)行需要響應(yīng)的函數(shù)
不管我們set還是get,我們都需要找到,對(duì)應(yīng)的依賴來執(zhí)行,所以我們需要用一個(gè)合適的數(shù)據(jù)結(jié)構(gòu)來存取我們對(duì)應(yīng)的依賴(數(shù)據(jù)結(jié)構(gòu):WeakMap中的屬性名是對(duì)象,值為map map中的屬性名是對(duì)象的屬性名,值為new Depend())
// 當(dāng)前需要收集的響應(yīng)式函數(shù)
let activeReactiveFn = null
// 響應(yīng)式的函數(shù)
function watchFn(fn) {
activeReactiveFn = fn
fn()
activeReactiveFn = null
}
// 依賴類
class Depend {
constructor() {
// 依賴容器
this.reactiveFns = new Set()
}
// 添加依賴的方法
depend() {
activeReactiveFn && this.reactiveFns.add(activeReactiveFn)
}
// 執(zhí)行依賴的方法
notify() {
this.reactiveFns.forEach(fn => {
fn()
})
}
}
// 獲取當(dāng)前依賴 數(shù)據(jù)結(jié)構(gòu):WeakMap中的屬性名是對(duì)象,值為map map中的屬性名是對(duì)象的屬性名,值為new Depend()
const targetMap = new WeakMap()
function getDepend(target, key) {
let map = targetMap.get(target)
if (!map) {
map = new Map()
targetMap.set(target, map)
}
let depend = map.get(key)
if (!depend) {
depend = new Depend()
map.set(key, depend)
}
return depend
}
// 將對(duì)象變?yōu)轫憫?yīng)式
function reactive(obj) {
return new Proxy(obj, {
get(target, key, receiver) {
// 收集依賴
const depend = getDepend(target, key)
depend.depend()
return Reflect.get(target, key, receiver)
},
set(target, key, newValue, receiver) {
Reflect.set(target, key, newValue, receiver)
// 獲取當(dāng)前依賴,并重新執(zhí)行
const depend = getDepend(target, key)
depend.notify()
}
})
}
const infoProxy = reactive({
name: "xt", // depend對(duì)象
age: 18 // depend對(duì)象
})
// 當(dāng)infoProxy.address變化時(shí)需要執(zhí)行的代碼 當(dāng)其首次執(zhí)行行 我們需要收集依賴
watchFn(() => {
console.log(infoProxy.name)
})
watchFn(() => {
console.log(infoProxy.age)
})
infoProxy.name = "tx"
infoProxy.name = "20"
單項(xiàng)數(shù)據(jù)流和雙向數(shù)據(jù)流綁定
單向數(shù)據(jù)流:是指數(shù)據(jù)在應(yīng)用程序中的流動(dòng)方向是單向的,從父組件流向子組件,而不會(huì)反向流動(dòng)。數(shù)據(jù)的更新只能通過父組件對(duì)子組件進(jìn)行傳遞,子組件無法直接更改父組件的數(shù)據(jù)。如:vue的props
雙向數(shù)據(jù)綁定:允許數(shù)據(jù)在父子組件之間進(jìn)行雙向的同步更新。當(dāng)一個(gè)組件的數(shù)據(jù)發(fā)生改變時(shí),雙向數(shù)據(jù)綁定會(huì)自動(dòng)更新其他相關(guān)的組件。
vue支持單向綁定和雙向綁定
單向綁定:插值形式{{data}},v-bind也是單向綁定
雙向綁定:表單的v-model,用戶對(duì)View層的更改會(huì)直接同步到Model層
組件通信
實(shí)現(xiàn)組件通信的方式:
- 父組件 → 子組件 :props
- 子組件 → 父組件 :emit 可以實(shí)現(xiàn)子給父通信即vm.$emit( event, arg )
- 全局事件總線eventBus:$bus 全能:在兩個(gè)組件中通過分別調(diào)用這個(gè)實(shí)例的事件觸發(fā)和監(jiān)聽來實(shí)現(xiàn)通信。
import Bus from 'eventBus.js';
sayHello() {
Bus.$emit('sayHello', 'hello');
}
import Bus from 'eventBus.js';
Bus.$on('sayHello', target => {
console.log(target); // => 'hello'
});
- 插槽 :子組件中的提供給父組件使用的一個(gè)占位符,用<slot></slot> 表示,父組件可以在這個(gè)占位符中填充任何模板代碼,如 HTML、組件等,填充的內(nèi)容會(huì)替換子組件的<slot></slot>標(biāo)簽。
- Vuex
action和mutation
在 Vuex 中,action 和 mutation 是用來管理應(yīng)用狀態(tài)的兩個(gè)重要概念,它們有以下區(qū)別:
-
Mutation:
- 作用:Mutations 是 Vuex 中用于修改狀態(tài)的唯一方法,它們是同步的函數(shù)。
- 使用場景:通常在 Mutations 中進(jìn)行簡單的狀態(tài)更改,如更新 state 的值。
- 規(guī)范:Mutations 必須是純函數(shù)(Pure Functions),即給定固定的輸入,每次返回固定的輸出,不應(yīng)該有副作用。
- 調(diào)用方式:通過 commit 方法觸發(fā) Mutations 的調(diào)用。
-
Action:
- 作用:Actions 用于處理異步操作、邏輯處理或批量觸發(fā)多個(gè) Mutations,它們是異步的函數(shù)。
- 使用場景:在 Actions 中可以包含異步操作,例如調(diào)用后端 API 請求數(shù)據(jù),在處理完異步操作后再提交 Mutation。
- 規(guī)范:Actions 不直接修改 state,而是通過提交 Mutations 來改變 state。
- 調(diào)用方式:通過 dispatch 方法觸發(fā) Actions 的調(diào)用。
-
區(qū)別總結(jié):
- 同步 vs 異步:Mutation 是同步操作,而 Action 是異步操作。
- 純函數(shù) vs 異步操作:Mutation 是純函數(shù),而 Action 可以包含各種異步操作。
- 直接修改 vs 間接修改:Mutation 直接修改狀態(tài),而 Action 通過提交 Mutation 間接修改狀態(tài)。
- 調(diào)用方式:Mutation 通過 commit 觸發(fā),Action 通過 dispatch 觸發(fā)。
在 Vuex 應(yīng)用中,通常建議使用 Actions 來處理異步邏輯和業(yè)務(wù)邏輯,而通過 Mutation 來修改狀態(tài)。
axios
Axios 是一個(gè)基于 Promise 的 HTTP 客戶端,可以在瀏覽器和 Node.js 中發(fā)送 HTTP 請求。它支持處理請求和響應(yīng)數(shù)據(jù)的轉(zhuǎn)換以及攔截請求和響應(yīng)等功能。
使用 Axios 發(fā)送請求。例如,發(fā)送一個(gè) GET 請求:
axios.get('https://api.example.com/data')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});
在上面的例子中,使用 axios.get() 發(fā)送一個(gè) GET 請求到指定的 URL,然后根據(jù)返回的 Promise 對(duì)象進(jìn)行處理??梢酝ㄟ^ .then() 處理成功的響應(yīng)結(jié)果,通過 .catch() 處理請求失敗的情況。
除了 GET 請求,Axios也支持其他HTTP請求方法,如 POST、PUT、DELETE等,使用方式類似。同時(shí),Axios也支持設(shè)置請求頭、請求攔截器、響應(yīng)攔截器等功能,以滿足各種需求。
Promise
Promise 對(duì)象是 JavaScript 提供的用于處理異步操作的一種方式,它表示一個(gè)異步操作的最終完成(或失?。?,并返回相應(yīng)的結(jié)果值。
-
Promise 的原理:
- 狀態(tài):Promise 對(duì)象有三種狀態(tài):
Pending(進(jìn)行中)
、Fulfilled(已成功)
和Rejected(已失敗)
。 - 處理過程:Promise 實(shí)例被創(chuàng)建時(shí)處于
Pending
狀態(tài),表示異步操作尚未完成。當(dāng)操作成功完成時(shí),Promise進(jìn)入Fulfilled
狀態(tài),返回成功的結(jié)果;當(dāng)操作失敗時(shí),Promise 進(jìn)入Rejected
狀態(tài),返回失敗的原因。 - Promise 的狀態(tài)改變:
Pending
:初始狀態(tài),可以改變?yōu)?Fulfilled 或 Rejected。
Fulfilled
:表示操作成功完成,不可再變?yōu)槠渌麪顟B(tài)。
Rejected
:表示操作失敗,不可再變?yōu)槠渌麪顟B(tài)。
- 狀態(tài):Promise 對(duì)象有三種狀態(tài):
- 可以手動(dòng)修改 Promise 的狀態(tài)嗎:
JavaScript 中的 Promise 對(duì)象狀態(tài)是自動(dòng)管理的,一旦狀態(tài)發(fā)生變化,就無法手動(dòng)修改。Promise 的狀態(tài)改變是由異步操作結(jié)果決定的,無法直接干預(yù)或修改其狀態(tài),這是為了保證異步操作的穩(wěn)定性和準(zhǔn)確性。
Hash模式和History模式
History 模式
??在 History 模式下,Vue Router 通過使用 HTML5 History API 來管理路由,不會(huì)在 URL 中使用哈希(#)作為路由的標(biāo)記。相反,它依賴于瀏覽器的 History API 來管理 URL 的變化。
??使用 History 模式需要后端服務(wù)器的配合。當(dāng)用戶在瀏覽器中直接訪問頁面時(shí),或者刷新頁面時(shí),后端服務(wù)器需要配置,以確保返回對(duì)應(yīng)的前端路由頁面。這是因?yàn)樵?History 模式下,前端的路由和后端的路由是分離的,后端需要將所有路由請求都重定向到前端的入口頁面。
??服務(wù)器需要進(jìn)行相應(yīng)的配置,以確保在刷新頁面或直接訪問某個(gè)子路由時(shí),仍能正確返回前端路由對(duì)應(yīng)的頁面。
示例 URL:https://example.com/my-routeHash 模式
??在 Vue Router 中,Hash 模式是一種簡單且常見的路由模式,它使用 URL 中的哈希(#)來管理路由。當(dāng) URL 中的哈希值發(fā)生變化時(shí),Vue Router 將根據(jù)哈希值來匹配對(duì)應(yīng)的路由。
??使用 hash 模式時(shí),URL 中會(huì)有一個(gè) # 符號(hào),后面跟著路由路徑。
??通過監(jiān)聽 hashchange 事件來改變 URL 中的哈希值,實(shí)現(xiàn)前端路由跳轉(zhuǎn)。不需要服務(wù)器進(jìn)行特殊配置,因?yàn)楣2糠值淖兓粫?huì)發(fā)送到服務(wù)器。
示例 URL:https://example.com/#/my-routeHistory 模式 與 Hash 模式 的區(qū)別
??History 模式的 URL 更美觀和干凈,更類似傳統(tǒng)的 URL 結(jié)構(gòu)。
??Hash 模式的 URL 兼容性好,不需要特殊的服務(wù)器配置,可以在幾乎所有的環(huán)境中使用。
??在使用 History 模式時(shí),需要確保服務(wù)器端配置正確,以便在刷新頁面或直接訪問子路由時(shí),能正確返回對(duì)應(yīng)的頁面。而 Hash 模式不需要這樣的配置。
??總之,History 模式的 URL 可能會(huì)更符合用戶的習(xí)慣,但需要對(duì)服務(wù)器進(jìn)行配置。Hash 模式則更簡單易用,但 URL 中會(huì)有一個(gè) # 符號(hào)。
import VueRouter from 'vue-router';
import Hello from "../components/Hello.vue"
import Vue from "vue";
Vue.use(VueRouter)
const router = new VueRouter({
mode: 'history',//或hash
base:'/app2/',
routes:[
{
path: '/hello',
name: 'hello',
component: Hello
},
],
})
export default router;
diff算法
diff算法就是進(jìn)行虛擬節(jié)點(diǎn)對(duì)比,并返回一個(gè)patch對(duì)象,用來存儲(chǔ)兩個(gè)節(jié)點(diǎn)不同的地方,最后用patch記錄的消息去局部更新Dom。diff的過程就是調(diào)用名為patch的函數(shù),比較新舊節(jié)點(diǎn),一邊比較一邊給真實(shí)的DOM打補(bǔ)丁
- diff算法的特點(diǎn)
比較只會(huì)在同層級(jí)進(jìn)行, 不會(huì)跨層級(jí)比較,在diff比較的過程中,循環(huán)從兩邊向中間比較。diff 算法的在很多場景下都有應(yīng)用,在 vue 中,作用于虛擬 dom 渲染成真實(shí) dom 的新舊 VNode 節(jié)點(diǎn)比較 - diff算法的步驟:
- 用 JavaScript 對(duì)象結(jié)構(gòu)表示 DOM 樹的結(jié)構(gòu);然后用這個(gè)樹構(gòu)建一個(gè)真正的 DOM 樹,插到文 檔當(dāng)中
- 當(dāng)狀態(tài)變更的時(shí)候,重新構(gòu)造一棵新的對(duì)象樹。然后用新的樹和舊的樹進(jìn)行比較(diff),記錄兩棵樹差異
- 把第二棵樹所記錄的差異應(yīng)用到第一棵樹所構(gòu)建的真正的DOM樹上(patch),視圖就更新了
- 比較方式
diff整體策略為:深度優(yōu)先,同層比較;
比較只會(huì)在同層級(jí)進(jìn)行, 不會(huì)跨層級(jí)比較,比較的過程中,循環(huán)從兩邊向中間收攏 - 原理分析
當(dāng)數(shù)據(jù)發(fā)生改變時(shí),set方法會(huì)調(diào)用Dep.notify通知所有訂閱者Watcher,訂閱者就會(huì)調(diào)用patch給真實(shí)的DOM打補(bǔ)丁,更新相應(yīng)的視圖
虛擬Dom
虛擬DOM的概念是通過狀態(tài)生成一個(gè)虛擬節(jié)點(diǎn)樹,然后使用虛擬節(jié)點(diǎn)樹進(jìn)行渲染。在渲染之前,會(huì)使用新生成的虛擬節(jié)點(diǎn)和上一次生成的虛擬節(jié)點(diǎn)進(jìn)行對(duì)比,只渲染不同的部分
-
vue中的虛擬DOM
vue中狀態(tài)變化時(shí),只能通知到組件,組件內(nèi)部的變化需要通過虛擬DOM去進(jìn)行比對(duì)與渲染。我們使用模板來描述狀態(tài)與DOM之間的映射關(guān)系。vue通過編譯將模板轉(zhuǎn)換成渲染函數(shù),執(zhí)行渲染函數(shù)就可以得到一個(gè)虛擬節(jié)點(diǎn)樹,使用虛擬節(jié)點(diǎn)數(shù)就可以渲染頁面
虛擬DOM在vue中主要提供與真實(shí)節(jié)點(diǎn)對(duì)應(yīng)的虛擬節(jié)點(diǎn)vnode,然后需要將vnode和oldVnode進(jìn)行比對(duì),然后更新視圖,對(duì)比兩個(gè)虛擬節(jié)點(diǎn)的算法是patch(diff的一部分)算法
瀏覽器的代理、緩存和跨域問題
-
瀏覽器緩存:
瀏覽器緩存是指瀏覽器在本地存儲(chǔ)已請求過的資源(如網(wǎng)頁、圖片、樣式表等),以便在之后的訪問中能夠更快地獲取這些資源而不需要重新下載。瀏覽器緩存分為兩種:
強(qiáng)制緩存:瀏覽器直接從本地緩存中獲取資源,不發(fā)起請求到服務(wù)器,通過設(shè)置響應(yīng)頭中的 Cache-Control 和 Expires 實(shí)現(xiàn)。
協(xié)商緩存:瀏覽器發(fā)起請求到服務(wù)器,經(jīng)過協(xié)商后確定是否直接從緩存中獲取資源,通過設(shè)置響應(yīng)頭中的 Last-Modified 和 ETag 實(shí)現(xiàn)。
-
跨域問題:
跨域是指瀏覽器出于安全考慮限制了不同域下的頁面之間的交互??缬虬ㄒ韵虑闆r:
不同域名:例如 http://example.com 和 http://test.com。
不同子域:例如 http://sub1.example.com 和 http://sub2.example.com。
不同端口:例如 http://example.com:8080 和 http://example.com:9090。- 跨域解決方案:
- JSONP:通過動(dòng)態(tài)創(chuàng)建 script 標(biāo)簽實(shí)現(xiàn)跨域請求。
- CORS(跨域資源共享):在服務(wù)端設(shè)置相應(yīng)的響應(yīng)頭,允許跨域請求。
- 代理:通過同源策略的限制,通過自己的服務(wù)器來轉(zhuǎn)發(fā)請求。
- iframe:通過 iframe 的跨域特性實(shí)現(xiàn)數(shù)據(jù)的傳遞。
- 跨域資源共享(XHR2):以 XMLHttpRequest 對(duì)象為基礎(chǔ)的原生支持跨域請求的技術(shù)。
- 跨域解決方案:
-
瀏覽器緩存和跨域問題關(guān)聯(lián):
跨域請求會(huì)受到同源策略的限制,使得瀏覽器在進(jìn)行跨域請求時(shí)會(huì)受到緩存控制的影響。
如果跨域請求是可緩存的,則瀏覽器會(huì)根據(jù)響應(yīng)頭中的緩存信息來確定是否將響應(yīng)緩存下來,從而影響后續(xù)的請求。
-
瀏覽器的代理問題
代理服務(wù)器:代理服務(wù)器是位于客戶端和目標(biāo)服務(wù)器之間的服務(wù)器,作為中間人來轉(zhuǎn)發(fā)請求和響應(yīng),隱藏真實(shí)的客戶端 IP 地址。
代理類型:
正向代理:代理服務(wù)器代表客戶端向目標(biāo)服務(wù)器發(fā)送請求。
反向代理:代理服務(wù)器代表目標(biāo)服務(wù)器接收客戶端的請求。作用:
隱私保護(hù):代理可以隱藏客戶端真實(shí)的 IP 地址,提高個(gè)人隱私保護(hù)。
訪問控制:可以通過代理服務(wù)器控制訪問權(quán)限,實(shí)現(xiàn)訪問控制策略。
網(wǎng)絡(luò)性能:通過代理服務(wù)器緩存網(wǎng)頁內(nèi)容,提高頁面加載速度。
訪問限制:某些網(wǎng)絡(luò)可能會(huì)對(duì)特定 IP 地址或國家限制訪問,代理可以繞過這種限制。
- 使用場景:
訪問受限資源:訪問需要特定 IP 或地區(qū)才能訪問的資源。
加速訪問:通過代理服務(wù)器緩存常用頁面或資源,加快訪問速度。
突破封鎖:在某些國家或網(wǎng)絡(luò)環(huán)境下,訪問受限的網(wǎng)站或服務(wù)。
- 風(fēng)險(xiǎn):
安全性:公共代理可能存在安全風(fēng)險(xiǎn),包括泄漏用戶信息和篡改請求響應(yīng)。
穩(wěn)定性:代理服務(wù)可能不穩(wěn)定,導(dǎo)致訪問速度變慢或無法正常訪問目標(biāo)網(wǎng)站。
隱私:使用不受信任的代理服務(wù)可能暴露個(gè)人隱私。
前端模式(前端九種設(shè)計(jì)模式)
1. 外觀模式(Facade Pattern)
它提供了一個(gè)簡單的接口,用于訪問復(fù)雜的系統(tǒng)或子系統(tǒng)。通過外觀模式,客戶端可以通過一個(gè)簡單的接口來訪問復(fù)雜的系統(tǒng),而無需了解系統(tǒng)內(nèi)部的具體實(shí)現(xiàn)細(xì)節(jié)。
外觀模式常常被用于封裝一些常用的操作,以簡化代碼復(fù)雜度和提高代碼可維護(hù)性。
2. 代理模式(Proxy Pattern)
代理模式是一種結(jié)構(gòu)型模式,它允許在不改變原始對(duì)象的情況下,通過引入一個(gè)代理對(duì)象來控制對(duì)原始對(duì)象的訪問。代理對(duì)象充當(dāng)原始對(duì)象的中介,客戶端與代理對(duì)象交互,代理對(duì)象再將請求轉(zhuǎn)發(fā)給原始對(duì)象。
代理模式在前端開發(fā)中經(jīng)常被用來處理一些復(fù)雜或者耗時(shí)的操作,例如圖片的懶加載、緩存等。代理對(duì)象可以在加載圖片時(shí)顯示占位符,當(dāng)圖片加載完成后再替換占位符,從而提高頁面加載速度和用戶體驗(yàn)。
另外,代理模式還可以用來實(shí)現(xiàn)一些權(quán)限控制的功能。例如,在用戶登錄后,代理對(duì)象可以檢查用戶的權(quán)限,只有具有相應(yīng)權(quán)限的用戶才能夠訪問某些功能或者頁面。
在 JavaScript 中,代理模式通常使用 ES6 中新增的 Proxy 對(duì)象來實(shí)現(xiàn)。Proxy 對(duì)象允許攔截對(duì)對(duì)象的各種操作,包括讀取、賦值、函數(shù)調(diào)用等。通過使用 Proxy 對(duì)象,我們可以在不改變原始對(duì)象的情況下,控制對(duì)原始對(duì)象的訪問。
當(dāng)我們需要為某個(gè)類或者對(duì)象添加一些額外的行為或者控制訪問時(shí),可以使用代理模式。
前端設(shè)計(jì)模式中的
3. 工廠模式(Factory Pattern)
將對(duì)象的創(chuàng)建和使用分離,由工廠類負(fù)責(zé)創(chuàng)建對(duì)象并返回。在前端開發(fā)中,可以使用工廠模式來動(dòng)態(tài)創(chuàng)建組件。
前端中的工廠模式是一種創(chuàng)建對(duì)象的設(shè)計(jì)模式,它可以讓我們封裝創(chuàng)建對(duì)象的細(xì)節(jié),我們使用工廠方法而不是直接調(diào)用 new 關(guān)鍵字來創(chuàng)建對(duì)象,使得代碼更加清晰、簡潔和易于維護(hù)。在前端開發(fā)中,工廠模式通常用于創(chuàng)建多個(gè)相似但稍有不同的對(duì)象,比如創(chuàng)建一系列具有相同樣式和行為的按鈕或者表單。
在實(shí)現(xiàn)工廠模式時(shí),通常需要?jiǎng)?chuàng)建一個(gè)工廠函數(shù)(或者叫做工廠類),該函數(shù)可以接受一些參數(shù),并根據(jù)這些參數(shù)來創(chuàng)建對(duì)象。例如,我們可以創(chuàng)建一個(gè)ButtonFactory函數(shù),它接受一個(gè)type參數(shù),用于指定按鈕的類型,然后根據(jù)type參數(shù)創(chuàng)建不同類型的按鈕對(duì)象。
4. 單例模式(Singleton Pattern)
保證一個(gè)類只有一個(gè)實(shí)例,并提供一個(gè)訪問它的全局訪問點(diǎn)。在前端開發(fā)中,可以使用單例模式來管理全局狀態(tài)和資源。使用場景:
- 對(duì)象字面量
- 構(gòu)造函數(shù)
- 模塊模式
- vuex和redux
5. 策略模式(Strategy Pattern)
定義一系列的算法,將每一個(gè)算法都封裝起來,并且使它們可以相互替換。在前端開發(fā)中,可以使用策略模式來動(dòng)態(tài)切換組件的算法和行為。
它可以讓我們在不改變對(duì)象本身的情況下,通過修改其內(nèi)部的算法實(shí)現(xiàn)不同的行為。策略模式常常被用于實(shí)現(xiàn)一些復(fù)雜的業(yè)務(wù)邏輯,特別是需要根據(jù)不同的條件進(jìn)行處理的情況。
6. 迭代器模式(Iterator Pattern)
提供一種方法順序訪問一個(gè)聚合對(duì)象中的各個(gè)元素,而不需要暴露該對(duì)象的內(nèi)部表示。在JavaScript中,可以使用迭代器模式來操作數(shù)組或類數(shù)組對(duì)象。
在迭代器模式中,集合對(duì)象包含一個(gè)方法,用于返回一個(gè)迭代器,該迭代器可以按順序訪問該集合中的元素。迭代器提供了一種通用的接口,使得可以使用相同的方式遍歷不同類型的集合對(duì)象。
在前端開發(fā)中,迭代器模式經(jīng)常用于處理集合數(shù)據(jù),例如數(shù)組、列表等。通過使用迭代器模式,可以輕松地遍歷集合對(duì)象的元素,而不必?fù)?dān)心它們的實(shí)現(xiàn)方式。
7. 觀察者模式(Observer Pattern)
當(dāng)對(duì)象間存在一對(duì)多的關(guān)系時(shí),使用觀察者模式。當(dāng)被觀察的對(duì)象發(fā)生變化時(shí),其所有的觀察者都會(huì)收到通知并進(jìn)行相應(yīng)的操作。在JavaScript中,可以使用回調(diào)函數(shù)或事件監(jiān)聽來實(shí)現(xiàn)觀察者模式。
在前端開發(fā)中,觀察者模式常被用來實(shí)現(xiàn)組件間的數(shù)據(jù)傳遞和事件處理。比如,當(dāng)一個(gè)組件的狀態(tài)發(fā)生改變時(shí),可以通過觀察者模式來通知其他組件更新自身的狀態(tài)或視圖。
在觀察者模式中,通常會(huì)定義兩種角色:
Subject(主題):它是被觀察的對(duì)象,當(dāng)其狀態(tài)發(fā)生改變時(shí)會(huì)通知所有的觀察者。
Observer(觀察者):它是觀察主題的對(duì)象,當(dāng)主題狀態(tài)發(fā)生改變時(shí)會(huì)接收到通知并進(jìn)行相應(yīng)的處理。
8. 中介者模式(Mediator Pattern)
通過一個(gè)中介對(duì)象來封裝一系列對(duì)象之間的交互。在JavaScript中,可以使用事件調(diào)度器來實(shí)現(xiàn)中介者模式。
在前端開發(fā)中,中介者模式常常被用于管理復(fù)雜的用戶界面或組件之間的交互,比如 GUI 組件、聊天室、游戲等等。通過引入一個(gè)中介者對(duì)象,各個(gè)組件可以向中介者對(duì)象發(fā)送消息或事件,而不需要知道消息或事件的接收者是誰。中介者對(duì)象負(fù)責(zé)接收并分發(fā)消息或事件,從而實(shí)現(xiàn)組件之間的解耦和統(tǒng)一管理。
9.訪問者模式(Visitor Pattern)
是一種行為型設(shè)計(jì)模式,用于將操作與其所操作的對(duì)象分離開來。該模式的核心思想是將操作封裝在一個(gè)訪問者對(duì)象中,而不是分散在各個(gè)對(duì)象中。通過將操作與對(duì)象分離開來,訪問者模式可以在不修改對(duì)象結(jié)構(gòu)的情況下,添加新的操作。
在前端開發(fā)中,訪問者模式通常用于處理DOM樹上的操作。由于DOM樹結(jié)構(gòu)通常很深,而且節(jié)點(diǎn)類型不同,因此對(duì)DOM樹進(jìn)行一系列的操作,常常需要寫很多代碼。而訪問者模式可以將這些操作抽象出來,封裝到訪問者對(duì)象中,從而簡化了代碼量。
在訪問者模式中,有兩種角色:訪問者(Visitor)和被訪問者(Element)。被訪問者是一組對(duì)象,它們具有不同的接口,用于接受訪問者的訪問。訪問者則是一組對(duì)象的操作,用于處理被訪問者。訪問者通常會(huì)遍歷整個(gè)被訪問者的結(jié)構(gòu),并對(duì)每個(gè)節(jié)點(diǎn)進(jìn)行操作。
flex布局
Flex布局又稱彈性布局,它使用flexbox使得容器有了彈性,更加適應(yīng)各種設(shè)備的不同寬度,而不必依賴于傳統(tǒng)的塊狀布局和浮動(dòng)定位。它是CSS3中新增的規(guī)范,目前主流瀏覽器均已支持。
分布式存儲(chǔ)
分布式存儲(chǔ)是一種去中心化存儲(chǔ),通過資源虛擬化、負(fù)載均衡、跨節(jié)點(diǎn)保護(hù)等技術(shù),把多臺(tái)存儲(chǔ)設(shè)備的資源進(jìn)行整合處理,整合成一個(gè)虛擬的存儲(chǔ)設(shè)備,統(tǒng)一對(duì)外提供存儲(chǔ)服務(wù)。在數(shù)據(jù)存儲(chǔ)時(shí),會(huì)均衡的把數(shù)據(jù)分散存儲(chǔ)在每臺(tái)底層存儲(chǔ)設(shè)備上,最后達(dá)到數(shù)據(jù)分布存儲(chǔ)的目的。
Vue如何監(jiān)聽數(shù)據(jù)
watch監(jiān)聽
你可以為一個(gè)特定的數(shù)據(jù)字段添加一個(gè)watcher函數(shù),當(dāng)該字段的值改變時(shí)會(huì)自動(dòng)調(diào)用此函數(shù)。示例代碼如下所示:
data() {
return {
message: 'Hello Vue!'
}
},
watch: {
// 監(jiān)聽message字段的變化
message(newValue, oldValue) {
console.log('Message changed from', oldValue, 'to', newValue);
}
}
上面的代碼將在控制臺(tái)輸出每次message字段的新值和舊值。
計(jì)算屬性(computed property)
你也可以創(chuàng)建一個(gè)計(jì)算屬性來根據(jù)其他數(shù)據(jù)字段的值進(jìn)行計(jì)算并返回結(jié)果。示例代碼如下所示:
data() {
return {
firstName: '',
lastName: ''
};
},
computed: {
fullName() {
if (this.firstName && this.lastName) {
return `${this.firstName} ${this.lastName}`;
} else {
return '';
}
}
}
JS異步怎么實(shí)現(xiàn)?
回調(diào)函數(shù)、事件監(jiān)聽、發(fā)布/訂閱、Promise對(duì)象、async和await函數(shù)
XSS攻擊
xss攻擊是跨站腳本攻擊,例如在表單中提交含有可執(zhí)行的javascript的內(nèi)容文本,如果服務(wù)器端沒有過濾或轉(zhuǎn)義這些腳本,而這些腳本由通過內(nèi)容的形式發(fā)布到了頁面上,這個(gè)時(shí)候如果有其他用戶訪問這個(gè)網(wǎng)頁,那么瀏覽器就會(huì)執(zhí)行這些腳本,從而被攻擊,從而獲取用戶的cookie等信息。
解決:
1、對(duì)于敏感的cookie信息,使用HttpOnly,使document對(duì)象中找不到cookie。
httpOnly 是一個(gè)常見的 Cookie 屬性,用于增加對(duì)于跨站點(diǎn)腳本攻擊(XSS)的防護(hù)。將 Cookie 的 httpOnly 屬性設(shè)置為 true 會(huì)限制瀏覽器端 JavaScript 對(duì)該 Cookie 的訪問,只允許在 HTTP 請求中自動(dòng)發(fā)送 Cookie,而禁止通過 JavaScript 來讀取或修改該 Cookie。
2、對(duì)于用戶輸入的信息要進(jìn)行轉(zhuǎn)義。
http、https加密
http是明文傳輸,https是密文傳輸,在http的基礎(chǔ)上添加 SSL/TLS協(xié)議進(jìn)行加密保護(hù),需要提供SSL證書,在證書下使用對(duì)稱加密。
SSL
全稱為Secure Sockets Layer
,即安全套接層。SSL協(xié)議位于TCP/IP協(xié)議與各種應(yīng)用層協(xié)議之間,為數(shù)據(jù)通訊提供安全支持。
CSS重設(shè)
一種避免瀏覽器兼容性問題的方法,CSS 重設(shè)也叫CSS復(fù)位、默認(rèn)CSS、CSS重置等。CSS重設(shè)就是由于各種瀏覽器解釋CSS樣式的初始值有所不同,導(dǎo)致設(shè)計(jì)師在沒有定義某個(gè)CSS屬性時(shí),不同的瀏覽器會(huì)按照自己的默認(rèn)值來為沒有定義的樣式賦值,所以我們要先定義好一些CSS樣式,來讓所有瀏覽器都按照同樣的規(guī)則解釋CSS,這樣就能避免發(fā)生這種問題。
es6新增特性
1.let和const關(guān)鍵字
2.解構(gòu)賦值
3.箭頭函數(shù)
4.模板字符串:使用反引號(hào)``代替雙引號(hào)創(chuàng)建字符串
5.標(biāo)簽?zāi)0?br>
6.擴(kuò)展運(yùn)算符
7.新增了一些字符串和數(shù)組方法
8.Symbol
9.迭代器(Iterator)
10.生成器
11.Promise承諾
1.let和const關(guān)鍵字
微任務(wù)和宏任務(wù)
微任務(wù)(microtask) 微任務(wù)是指在當(dāng)前任務(wù)執(zhí)行結(jié)束后立即執(zhí)行的任務(wù),它可以看作是在當(dāng)前任務(wù)的“尾巴”添加的任務(wù)。
宏任務(wù)(macrotask) 宏任務(wù)是指需要排隊(duì)等待 JavaScript 引擎空閑時(shí)才能執(zhí)行的任務(wù)。常見的宏任務(wù)包括 setTimeout、setInterval、I/O 操作、DOM 事件等。常見的微任務(wù)包括 Promise 回調(diào)和 process.nextTick。
JavaScript 引擎會(huì)先執(zhí)行當(dāng)前任務(wù)中的所有微任務(wù),然后再執(zhí)行宏任務(wù)隊(duì)列中的第一個(gè)任務(wù)。
要區(qū)分微任務(wù)和宏任務(wù),是因?yàn)槲⑷蝿?wù)和宏任務(wù)的執(zhí)行順序不同,這對(duì) Web 開發(fā)中一些異步操作的實(shí)現(xiàn)有著重要的影響。 在 JavaScript 中,微任務(wù)會(huì)優(yōu)先于宏任務(wù)執(zhí)行。這意味著在當(dāng)前任務(wù)執(zhí)行結(jié)束后,所有微任務(wù)都會(huì)被立即執(zhí)行,而宏任務(wù)只有在所有微任務(wù)執(zhí)行完畢后才會(huì)執(zhí)行。這種執(zhí)行順序保證了微任務(wù)的優(yōu)先級(jí),可以避免一些問題的出現(xiàn)
GET與POST
相同點(diǎn)
GET 請求和 POST 請求底層都是基于 TCP/IP 協(xié)議實(shí)現(xiàn)的,使用二者中的任意一個(gè),都可以實(shí)現(xiàn)客戶端和服務(wù)器端的雙向交互。
不同點(diǎn)
- get請求一般是去取獲取數(shù)據(jù)(其實(shí)也可以提交,但常見的是獲取數(shù)據(jù));post請求一般是去提交數(shù)據(jù)。
- get因?yàn)閰?shù)會(huì)放在url中,所以隱私性,安全性較差,請求的數(shù)據(jù)長度是有限制的,不同的瀏覽器和服務(wù)器不同,一般限制在 2~8K 之間,更加常見的是 1k 以內(nèi);post請求是沒有的長度限制,請求數(shù)據(jù)是放在body中;
- get請求刷新服務(wù)器或者回退沒有影響,post請求回退時(shí)會(huì)重新提交數(shù)據(jù)請求。
- get請求可以被緩存,post請求不會(huì)被緩存。
- get請求會(huì)被保存在瀏覽器歷史記錄當(dāng)中,post不會(huì)。get請求可以被收藏為書簽,因?yàn)閰?shù)就是url中,但post不能。它的參數(shù)不在url中。
- get請求只能進(jìn)行url編碼(appliacation-x-www-form-urlencoded),post請求支持多種(multipart/form-data等)。