Vue是什么
是一套漸進(jìn)式框架澡屡,與其他框架不同的是,Vue可以自底向上逐層應(yīng)用咐旧,vue核心只關(guān)注視圖層驶鹉,容易上手,方便與第三方庫整合铣墨,可以完成復(fù)雜的單頁面應(yīng)該提供驅(qū)動(dòng)
Vue的優(yōu)點(diǎn)
- 輕量級(jí)框架:只關(guān)注視圖室埋,構(gòu)建視圖的集合
- 簡單易學(xué),中文文檔沒有語言障礙
- 雙向數(shù)據(jù)綁定伊约,操作數(shù)據(jù)簡單
- 組件化姚淆,構(gòu)建單頁面應(yīng)該有優(yōu)勢(shì)
- 視圖數(shù)據(jù)分離,使用數(shù)據(jù)更方便
- 虛擬DOM碱妆,原生dom操作很費(fèi)性能
Vue的基本原理
創(chuàng)建實(shí)例時(shí)肉盹,遍歷 data 用 Object.defineProperty() (vue3 使用 proxy)將他們轉(zhuǎn)為 getter/setter,并且在內(nèi)部跟蹤疹尾,每個(gè)組件實(shí)例都有 watcher 程序上忍, 屬性發(fā)生變化時(shí),會(huì)通知 watcher 重新計(jì)算纳本,然后更新組件
雙向數(shù)據(jù)綁定
vue 是采用 數(shù)據(jù)劫持 + 發(fā)布者-訂閱制模式 的方式窍蓝,通過 Object.defineProperty 來劫持 所有屬性的 setter/getter , 在數(shù)據(jù)有變化,發(fā)布消息給訂閱制繁成,觸發(fā)響應(yīng)的 事件監(jiān)聽(watcher)回調(diào)吓笙。
使用 Object.defineProperty 的缺點(diǎn)
通過下標(biāo)方式修改數(shù)組數(shù)據(jù),或者給對(duì)象增加屬性巾腕,不可以觸發(fā)渲染面睛,因?yàn)镺bject.defineProperty 攔截不到這些操作, 大部分的數(shù)組都攔截不到尊搬, vue 內(nèi)部通過重寫函數(shù)的方式 解決了叁鉴,數(shù)組改數(shù)據(jù) :push,pop佛寿,shift幌墓,unshift,splice冀泻,sort常侣,reverse
vue3 使用了 proxy 對(duì)對(duì)象進(jìn)行代理, 實(shí)現(xiàn)數(shù)據(jù)劫持弹渔,使用 proxy 的好處胳施,可以完美監(jiān)聽數(shù)據(jù)的改變,并可以深度的監(jiān)聽數(shù)據(jù)肢专, 唯一的缺點(diǎn)就是 兼容問題:Proxy是Es6 語法
MVC
- mvc 通過 model , view 和 controller 的方式組織代碼結(jié)構(gòu)巾乳,view負(fù)責(zé)頁面顯示您没,model負(fù)責(zé)存儲(chǔ)業(yè)務(wù)數(shù)據(jù)和相應(yīng)數(shù)據(jù)操作,并且view和model 使用了觀察者模式
- 當(dāng) model 改變時(shí) 通知 有關(guān) view 更新頁面胆绊,controller 是view 和 model的紐帶,通過 view 來 對(duì) model 更改欧募,然后 model 再去通知 view 更新压状,過程都是單向的
MVVM
- model 代表數(shù)據(jù)模型,view 代表UI視圖跟继, view,model 負(fù)責(zé) 監(jiān)聽model的變化控制視圖种冬,視圖變化 通知數(shù)據(jù),
- view 和 model 沒有關(guān)系舔糖,是通過viewmodel 來進(jìn)行聯(lián)系的
- 缺點(diǎn)
- 難調(diào)試娱两,大模塊,使用方便和保證數(shù)據(jù)的一致性金吗,但不釋放內(nèi)存造成很多開銷
- 大的圖形應(yīng)用程序 十兢, 視圖裝太多,viewmodel構(gòu)架維護(hù)成本高
MVP
- 和 MVC 唯一不同的 在于 Presenter 和 Controller 摇庙,MVC在model 發(fā)生變化的時(shí)候旱物,通知 view ,view 和 model 偶合在一起卫袒,邏輯復(fù)雜的時(shí)候宵呛,代碼可能造成混亂,并對(duì)復(fù)用造成一些問題
- MVP 通過 Presenter 來實(shí)現(xiàn)對(duì) view 來實(shí)現(xiàn)夕凝,model 的解耦宝穗,MVC 中Controller 只知道 model 的接口, 沒辦法控制 view 的更新码秉,MVP 通過 View 暴露給 Presenter將model 和 view 綁定到一起逮矛,實(shí)現(xiàn) view 和 model 的同步更新
Vue 性能優(yōu)化
編碼階段
- 盡量減少data中數(shù)據(jù),因?yàn)橛迷黾?getter 和 setter, 會(huì)收集到 watcher
- v-if 和 v-for 不一起使用
- v-for 盡量使用 事件代理
- SPA(單頁面應(yīng)用)采用 keep-alive 緩存
- key 保證唯一
- 使用路由懶加載泡徙,異步組件
- 防抖節(jié)流
- 第三方模塊按需導(dǎo)入
- 長列表滾動(dòng)到可視區(qū)再加載
- 圖片懶加載
SEO 優(yōu)化
- 服務(wù)端 渲染 SSR
打包優(yōu)化
- 壓縮代碼
- 使用 cdn 加載第三方模塊
- Tree Shaking/Scope Hoisting (搖樹優(yōu)化)/ (作用域提升)
- 搖樹:依賴ES6導(dǎo)入橱鹏, 直把用到的方法放到 build中,沒用到的 擦除堪藐,立即執(zhí)行函數(shù)無法擦除莉兰,可以裝
npm i purgecss-webpack-plugin -D
擦除無效的css(要配置)- 作用域提升:將所有模塊按照代碼引入順序放在一個(gè)函數(shù)作用域里,然后適當(dāng)重命名防止變量沖突礁竞,減少函數(shù)聲明和內(nèi)存開銷
- 多線程打包 happypack
- 使用插件 happypack
- splitChunks 抽離公共文件
- webpack 把公用的代碼 單獨(dú)提取成一個(gè)文件
- sourceMap 優(yōu)化
- webpack 代碼映射技術(shù)糖荒,通過映射可以追蹤到源代碼的報(bào)錯(cuò)
用戶優(yōu)化
- 骨架屏
- PWA
- 首屏可以部署在服務(wù)端,響應(yīng)式界面模捂,沉浸式體驗(yàn)(在支持 PWA 的瀏覽器和手機(jī)應(yīng)用上可以直接將 Web 應(yīng)用添加到用戶的主屏幕上)
- 使用 緩存優(yōu)化(客戶端捶朵,服務(wù)端緩存): 協(xié)商緩存蜘矢,強(qiáng)制緩存。 服務(wù)端開啟 gzip 壓縮
如何提升單頁面(spa single page app)應(yīng)用首屏加載速度
- 減小入口文件
- 靜態(tài)資源本地緩存
- 圖片資源壓縮综看,合并(精靈圖)
- 開啟 gzip 壓縮包
- 品腹、使用服務(wù)器渲染
Vue 初次渲染
- 步驟 :
- $mount () : 初始化 Vue
- mountComponent : (渲染的入口函數(shù))
- _render:(執(zhí)行render函數(shù),獲得虛擬DOM)
- __update:(將虛擬DOM轉(zhuǎn)真實(shí)DOM并渲染)
Computed 和 Watch
computed
- 支持緩存红碑,依賴的數(shù)據(jù)發(fā)生變化才會(huì)重新計(jì)算
- 不支持異步舞吭,當(dāng)有計(jì)算屬性的時(shí)候,無法監(jiān)聽數(shù)據(jù)變化
- 默認(rèn)走緩存析珊,基于依賴的響應(yīng)式進(jìn)行緩存羡鸥,或者 父組件傳遞過來的props 的數(shù)據(jù)進(jìn)行計(jì)算
- 可以使用 getter 和 setter 方法更靈活
watch
- 不支持緩存,數(shù)據(jù)變化 會(huì)觸發(fā)響應(yīng)的操作
- 支持異步監(jiān)聽忠寻,兩個(gè)參數(shù)惧浴,一個(gè)是最新的值,第二個(gè)是舊值
- 當(dāng)一個(gè)屬性發(fā)生變化就做像一個(gè)的操作
- immediate: 立即監(jiān)視奕剃, deep : 深度監(jiān)視 衷旅, handle: 監(jiān)聽函數(shù)
使用場景:
- 計(jì)算 當(dāng)進(jìn)行計(jì)算,可以依賴緩存特性祭饭,避免每次都要計(jì)算
- 當(dāng)需要數(shù)據(jù)變化時(shí) 執(zhí)行異步芜茵,或者 開銷較大時(shí),使用 watch , 限制執(zhí)行該操作的頻率倡蝙,得到最終結(jié)果前九串,設(shè)置中間狀態(tài)(防抖),計(jì)算屬性不行
watch只監(jiān)聽對(duì)象上的想監(jiān)聽屬性寺鸥,如何排除其他屬性監(jiān)聽
// 可以 直接監(jiān)聽 "params.a":{...}
data() {
return {
params: {
a: 1,
b: 2,
},
};
},
mounted() {
// 遍歷所有的對(duì)象屬性猪钮, 篩選出要監(jiān)聽的屬性
Object.keys(this.params)
.filter((item) => {
return item === "a";
})
// 遍歷要監(jiān)聽的數(shù)組
.forEach((item) => {
// 用 vue 實(shí)例的 watch 開啟監(jiān)聽
// $watch 參數(shù)1 要監(jiān)聽的屬性, 2 監(jiān)聽的處理函數(shù)胆建, 3 配置項(xiàng)烤低, 可以深度和立即監(jiān)聽
this.$watch(
(vm) => {
vm.params[item];
},
this.watchFun,
{
deep: true,
}
);
});
},
methods: {
edit() {
this.params.a = 10;
this.params.b = 10;
},
watchFun() {
console.log("對(duì)象單獨(dú)屬性更新");
},
},
watch: {
// params: {
// deep: true,
// handler() {
// console.log("更新了");
// },
// },
},
slot
是 vue 內(nèi)容分發(fā)機(jī)制,插槽是子組件的一個(gè)模板標(biāo)簽 笆载,這個(gè)標(biāo)簽由父組件決定扑馁,有默認(rèn)插槽,具名插槽和作用域插槽
- 默認(rèn): 匿名插槽凉驻,slot 沒有 name 屬性值的時(shí)候顯示 默認(rèn)的腻要,一個(gè)組件只能有一個(gè)匿名
- 具名:帶有名字的插槽,可以有多個(gè)
- 作用域: 可以有名字也可以無涝登,不同點(diǎn)雄家,在子組件渲染時(shí),可以將子組件內(nèi)部的數(shù)據(jù)傳遞給父組件胀滚,父組件根據(jù)子組件的數(shù)據(jù)決定如何渲染
vue 的 hook 使用
-
清除定時(shí)器
// 清除定時(shí)器 const timer = setInterval(() => { console.log(1); }, 1000); // $once 監(jiān)聽趟济,只觸發(fā)一次 // 使用 hook 調(diào)用 銷毀前的生命周期函數(shù) 清空定時(shí)器 this.$once("hook:beforeDestroy", () => { clearInterval(timer); });
-
父組件監(jiān)聽子組件的聲明周期函數(shù)
// 1. 用 $emit 監(jiān)聽 // 父組件 <!-- 監(jiān)聽子組件的 mounted 事件 --> <DomeChilred @changeMount="changeMount" /> // 監(jiān)聽處理 changeMount // 子組件 mounted() { // 子組件聲明周期 觸發(fā) 就像父組件發(fā)信號(hào) this.$emit("changeMount", "監(jiān)聽成功"); }, // 2. 使用 hook 監(jiān)聽 --》 缺點(diǎn)是不可以攜帶子組件的參數(shù)到父組件 // 父組件 <!-- 使用 hook --> <DomeChilred @hook:mounted="changeMount" /> changeMount() { console.log("子組件觸發(fā)了 mounted"); }, // 子組件 不用操作
保存頁面(組件)當(dāng)前狀態(tài)
兩種情況乱投。組件會(huì)被卸載 和不會(huì)被卸載
卸載
- 將狀態(tài)存在:LocalStorage / sessiconStorage,卸載組件 就在 beforeDestroy 存進(jìn)去,進(jìn)入頁面的時(shí)候加一個(gè) flag 判斷是否用緩存數(shù)據(jù)顷编,
- 優(yōu)點(diǎn):兼容好戚炫,不用庫,簡單媳纬,
- 缺點(diǎn):JSON轉(zhuǎn)字符串 是深拷貝嘹悼,function 不會(huì)保存,Date,和正則 不是原來的值层宫,flag不好控制,容易失效
- 路由傳值:通過路由傳參其监,可以實(shí)現(xiàn)簡單的路由傳值
- 優(yōu)點(diǎn):簡單萌腿,不污染localstorage... 可以傳遞Date正則(彌補(bǔ)上面)
- 缺點(diǎn):跳轉(zhuǎn)別的組件也帶著數(shù)據(jù)
不被卸載
- 要切換的組件是子組件,父組件中正常存儲(chǔ)頁面狀態(tài) 抖苦,可以用 <keep-alive> 來緩存頁面 組件在切換 調(diào)用 activated 和 deactivated 聲明周期函數(shù)
- 優(yōu)點(diǎn):代碼量少毁菱,不需要考慮狀態(tài)傳遞的錯(cuò)誤
- 缺點(diǎn): 增加 父組件的維護(hù)成本 、 需要傳遞props 到子組件锌历, 無法利用路由定位頁面
keep-alive 動(dòng)態(tài)組件 緩存
參數(shù):
- include 字符或正則贮庞,只有匹配到的緩存 - 白名單
- exclude 字符 | 正則 旨椒, 匹配到的不緩存 - 黑名單
- max number 可以緩存多少
<!-- 基本 -->
<transition>
<keep-alive>
<!-- 緩存 + 動(dòng)態(tài) 可以 if 判斷 + transiton(動(dòng)畫) 一起-->
<component :is="view"></component>
</keep-alive>
</transition>
讓組件 + 2個(gè)聲明周期苫拍, activated 激活煎饼, deactevated 失活
beforeDestroy 和 destroyed 不在觸發(fā)
常用的事件修飾符
- .stop ==> event.stopPropagation() 阻止事件冒泡
- .prevent ==> event.preventDefault() 取消默認(rèn)事件泥技,不停止傳播
- .capture ==> 事件捕獲
- .self ==> 只觸發(fā)自己范圍內(nèi)的事件钧汹, 不包含子元素
- .once ==> 只會(huì)觸發(fā)一次
v-if聊疲、v-show济榨、v-html
- v-if 懶惰的克婶, 第一次是 false 就不加載扇丛,切換時(shí) 標(biāo)簽創(chuàng)建銷毀术吗, 在虛擬 dom 操作,開銷比 v-show 大 原理: VNode 不會(huì)生成
- v-show 直接創(chuàng)建 顯示和隱藏都是用 css display 來控制的帆精,直接生成较屿,在用 display:none隱藏
- v-html : 先移除節(jié)點(diǎn)下的所有節(jié)點(diǎn),在 innerHTML 添加 卓练, 可能會(huì)導(dǎo)致 xss 攻擊隘蝎,里面的樣式還有使用 /deep/ 穿透
- 使用場景,v-show 適合頻繁切換
data 為什么不是函數(shù)
使用多個(gè)組件復(fù)用時(shí)昆庇,都使用data對(duì)象中數(shù)據(jù)末贾,形成變量污染,主要是隔離作用域整吆,讓每個(gè)組件都有自己的數(shù)據(jù)
vue重置data或者獲取data初始值
// 初始值的 data
console.log(this.$options.data());
// 當(dāng)前的 data
console.log(this.$data);
LRU 緩存策略
在內(nèi)存中找出 最久沒有使用的數(shù)據(jù)拱撵,換新數(shù)據(jù) 辉川, LRU 算法根據(jù)數(shù)據(jù)的歷史記錄進(jìn)行淘汰,最常見的是一個(gè)鏈表保存數(shù)據(jù)緩存 拴测, 詳細(xì)實(shí)現(xiàn):
- 新數(shù)據(jù)插入到鏈表頭部
- 每當(dāng)緩存數(shù)據(jù)被訪問乓旗,則數(shù)據(jù)移到鏈表頭部
- 鏈表滿了將鏈表尾部數(shù)據(jù)丟棄
$nextTick
- 本質(zhì)是對(duì) js 執(zhí)行原理 EventLoop 的一個(gè)應(yīng)用,模擬對(duì)應(yīng)的 宏/微 任務(wù)的實(shí)現(xiàn)集索,用 js 的異步 來執(zhí)行 vue 的異步
- 在下次渲染完成調(diào)用屿愚,可以獲取最新的DOM元素
$set $delete
// 給對(duì)象或者數(shù)組添加一個(gè)響應(yīng)式數(shù)據(jù)
this.$set(obj , name , 'liu'); // 對(duì)象
this.$set(arr , 0 , 'liu') // 數(shù)組
// 刪除一個(gè)響應(yīng)式數(shù)據(jù)
this.$delete(arr , 0 ) // 數(shù)組
this.$delete( obj , name) // 對(duì)象
單頁面應(yīng)用和多頁面
- SPA單頁面:只有一個(gè)主頁面,一開始只用加載一次 css,js 相關(guān)資源务荆,所有內(nèi)容都在主頁面妆距,對(duì)每一個(gè)功能都模塊化,跳轉(zhuǎn)就是切換組件函匕,只刷新局部資源
- MAP 多頁面 :每個(gè)頁面必須重復(fù)加載 js ,css 資源娱据,多頁面跳轉(zhuǎn),需要整個(gè)頁面刷新
對(duì)比項(xiàng)/模式 | SPA | MPA |
---|---|---|
體驗(yàn) | 頁面多盅惜,體驗(yàn)好中剩,首次加載資源多要過調(diào)整 | 頁面切換慢,網(wǎng)速慢抒寂,體驗(yàn)很差 |
資源 | 組件公用資源加載一次 | 每次都要加載自己的 |
場景 | 不利于 SEO優(yōu)化 (用 SSR 優(yōu)化 SEO) | 使用對(duì) SEO 要求高的應(yīng)該 |
更新 | 相關(guān)組件切換 局部更新 | 整個(gè) HTML切換 重復(fù) http請(qǐng)求 |
路由跳轉(zhuǎn) | hash history | 超鏈接 跳轉(zhuǎn) |
數(shù)據(jù)傳遞 | 各種通訊方式 | cookie...url參數(shù) 緩存方案结啼,接口保存 |
相關(guān)成本 | 前期開發(fā)成本高,易維護(hù) | 前期開發(fā)低屈芜,維護(hù)麻煩 |
data 屬性改變郊愧,視圖不會(huì)立即渲染
是按照一定的策略進(jìn)行 DOM的更新, 在更新是異步的沸伏,只要監(jiān)聽到數(shù)據(jù)變化糕珊,開啟一個(gè)隊(duì)列,緩存到事件循環(huán)中毅糟,發(fā)生的所有數(shù)據(jù)更改红选, 重復(fù)觸發(fā)只放入一個(gè)隊(duì)列,防止重復(fù)數(shù)據(jù)姆另,避免不必要的計(jì)算喇肋,
自定義指令 directive
使用場景
- 普通 DOM 元素進(jìn)行底層操作,
- 自定義指令用來操作 DOM 可以定義任何 DOM 操作迹辐,并且可以復(fù)用
使用案例
- 鼠標(biāo)聚焦
- 圖片加載錯(cuò)誤問題蝶防,懶加載
屬性: 第一個(gè)參數(shù):指令名稱 , 第二個(gè)參數(shù):配置對(duì)象明吩,指定指令的鉤子函數(shù)
配置對(duì)象:
- bind 只調(diào)用一次间学,第一次綁定的時(shí)候調(diào)用
- 參數(shù) : el: 綁定的DOM元素
- binding 對(duì)象:
- name 指令名
- value : 指定傳入的值 v-imgerror ='就是他'
- oldValue: 指令綁定的前一個(gè)值
- expression: 字符串形式的指令表達(dá)式 等號(hào)后面的字符串 形式
- arg: 傳給指令的參數(shù), 可選,v-my-directiive:foo 參數(shù) foo
- modifiers: 指令修飾符低葫,例如:v-directive.foo.bar中详羡,修飾符對(duì)象為 { foo: true, bar: true }
- vnode:Vue編譯生成的虛擬節(jié)點(diǎn)
- oldVnode: 上一個(gè)虛擬節(jié)點(diǎn),僅在 update 和 componentUpdated 鉤子中可用嘿悬。
- inserted (el , binding , vnode): 調(diào)用的時(shí)候实柠,元素已經(jīng)插入到頁面,也就是獲取到父節(jié)點(diǎn)
- update (el , binding , vnode , oldVnode ):DOM重新渲染前
- componentUpdated ( el , binding , vnode , oldVnode ):DOM 重新渲染后
- unbind ( el ) : 指令所在的元素在頁面中消失善涨,觸發(fā)窒盐。
簡寫 如果你想在 bind 和 update 時(shí)觸發(fā)相同行為,而不關(guān)心其它的鉤子
- Vue.directive('自定義指令名', function( el, binding ) {})
動(dòng)態(tài)指令
<button @[event]="handleEvent">動(dòng)態(tài)指令</button>
data(){
return {
event:'click'
}
},
mothods:{
handleEvent(){
console.log("事件觸發(fā)");
this.event = "contextmenu"; // 鼠標(biāo)右擊事件,點(diǎn)擊之后就變成了 右擊事件了
}
}
子組件可以修改父組件的數(shù)據(jù)嗎
不可以直接修改钢拧,因?yàn)?vue 是單項(xiàng)數(shù)據(jù)流蟹漓,直接賦值操作,會(huì)破壞數(shù)據(jù)流源内,可以通過 $emit 派發(fā)一個(gè)自定義事件牧牢,父組件收到后,父組件自己修改
assets 和 static
都是存放靜態(tài)文件
assets 要打包姿锭,之后放到 static里面。static 不打包
Vue模版編譯原理
- 解析階段:使用大量正則伯铣,對(duì) template 字符串解析呻此,將 標(biāo)簽,指令腔寡,屬性轉(zhuǎn)為抽象語法樹 AST
- 優(yōu)化階段: 遍歷 AST 找其中的靜態(tài)節(jié)點(diǎn)進(jìn)行標(biāo)記焚鲜,方便在重新渲染的時(shí)候進(jìn)行 diff 比較時(shí) ,跳過一些靜態(tài)節(jié)點(diǎn)
- 生成階段:將 AST 轉(zhuǎn)為 render函數(shù)字符串
SSR的理解
服務(wù)器渲染放前,將 vue 在客戶端標(biāo)簽渲染成 HTML 的工作放在 服務(wù)器忿磅,然后在把 html 返回 客戶端
- 優(yōu)勢(shì): 利于 SEO 搜索,首屏加載速度更快
- 缺點(diǎn):開發(fā)條件收到限制凭语,只支持 beforeCreate 和 created 兩個(gè)鉤子葱她,當(dāng)需要外部庫時(shí)要特殊處理,服務(wù)端渲染 程序似扔,也需要在 node.js 的運(yùn)行環(huán)境 也給給服務(wù)器增加負(fù)載
vue初始化頁面閃動(dòng)
初始化之前 div 不歸 vue 管吨些,寫的代碼 還沒有解析,容易出現(xiàn)花屏 如:{{msg}}
在 css + [v-cloak] { display: none;}
或者根元素 + style="display: none;" :style="{display: 'block'}"
Vue 子組件和父組件執(zhí)行順序
- 加載渲染過程
- 父組件 beforeCreate
- 父組件 created
- 父組件 beforeMount
- 子組件 beforeCreate
- 子組件 created
- 子組件 beforeMount
- 子組件 mounted
- 父組件 mounted
- 更新過程
- 父組件 beforeUpdate
- 子組件 beforeUpdate
- 子組件 updated
- 父組件 updated
- 銷毀過程:
- 父組件 beforeDestroy
- 子組件 beforeDestroy
- 子組件 destroyed
- 父組件 destoryed
組件通訊
- 父子組件
- props / $emit
- ref /refs
- $attrs / $listeners
- 兄弟
- $parent | $refs | $children
- 任意
- eventBus 事件總線
- .Observable 自定義一個(gè)小型的 vuex
- Vuex
路由的 hash 和 history 炒辉,abstract-- 抽象模式 服務(wù)器的
- hash
- 在url 有 # 豪墅, http 請(qǐng)求沒有,對(duì)后端沒影響黔寇,改變 hash 不會(huì)重新加載頁面偶器,對(duì)瀏覽器支持友好,成為 SPA(單頁面)標(biāo)配
- 原理 : 監(jiān)聽 onhashchange() 事件
- history
- 沒有 # 更好看,需要后端配置支持屏轰,不配置好 404
- 分兩狀態(tài) :
- 修改歷史狀態(tài): H5新增颊郎,pushState 和 replaceState
- 切換歷史狀態(tài) : forward, back, go
$router 和 $route
$route 是 路由信息對(duì)象, path hash fullpath matched name
$router 是 路由實(shí)例對(duì)象 包含了 跳轉(zhuǎn)方法鉤子函數(shù)亭枷,push back go
路由聲明周期
- 完成路由導(dǎo)航(沒有其他聲明周期)
- 觸發(fā)進(jìn)入其他路由袭艺。
- 調(diào)用要離開路由的組件守衛(wèi)beforeRouteLeave
- 調(diào)用局前置守衛(wèi)∶ beforeEach
- 在重用的組件里調(diào)用 beforeRouteUpdate
- 調(diào)用路由獨(dú)享守衛(wèi) beforeEnter。
- 解析異步路由組件叨粘。
- 在將要進(jìn)入的路由組件中調(diào)用 beforeRouteEnter
- 調(diào)用全局解析守衛(wèi) beforeResolve
- 導(dǎo)航被確認(rèn)猾编。
- 調(diào)用全局后置鉤子的 afterEach 鉤子。
- 觸發(fā)DOM更新(mounted)升敲。
- 執(zhí)行beforeRouteEnter 守衛(wèi)中傳給 next 的回調(diào)函數(shù)
- 觸發(fā)鉤子的完整順序
- 路由導(dǎo)航答倡、keep-alive、和組件生命周期鉤子結(jié)合起來的驴党,觸發(fā)順序瘪撇,假設(shè)是從a組件離開,第一次進(jìn)入b組件∶
- beforeRouteLeave:路由組件的組件離開路由前鉤子港庄,可取消路由離開倔既。
- beforeEach:路由全局前置守衛(wèi),可用于登錄驗(yàn)證鹏氧、全局路由loading等渤涌。
- beforeEnter:路由獨(dú)享守衛(wèi)
- beforeRouteEnter:路由組件的組件進(jìn)入路由前鉤子。
- beforeResolve:路由全局解析守衛(wèi)
- afterEach:路由全局后置鉤子
- beforeCreate:組件生命周期把还,不能訪問tAis实蓬。
- created;組件生命周期,可以訪問tAis吊履,不能訪問dom安皱。
- beforeMount:組件生命周期
- deactivated:離開緩存組件a,或者觸發(fā)a的beforeDestroy和destroyed組件銷毀鉤子艇炎。
- mounted:訪問/操作dom酌伊。
- activated:進(jìn)入緩存組件,進(jìn)入a的嵌套子組件(如果有的話)缀踪。
- 執(zhí)行beforeRouteEnter回調(diào)函數(shù)next腺晾。
- 導(dǎo)航行為被觸發(fā)到導(dǎo)航完成的整個(gè)過程
- 導(dǎo)航行為被觸發(fā),此時(shí)導(dǎo)航未被確認(rèn)辜贵。
- 在失活的組件里調(diào)用離開守衛(wèi) beforeRouteLeave悯蝉。
- 調(diào)用全局的 beforeEach守衛(wèi)。
- 在重用的組件里調(diào)用 beforeRouteUpdate 守衛(wèi)(2.2+)托慨。
- 在路由配置里調(diào)用 beforeEnter鼻由。
- 解析異步路由組件(如果有)。
- 在被激活的組件里調(diào)用 beforeRouteEnter。
- 調(diào)用全局的 beforeResolve 守衛(wèi)(2.5+)蕉世,標(biāo)示解析階段完成蔼紧。
- 導(dǎo)航被確認(rèn)。
- 調(diào)用全局的 afterEach 鉤子狠轻。
- 非重用組件奸例,開始組件實(shí)例的生命周期:beforeCreate&created、beforeMount&mounted
- 觸發(fā) DOM 更新向楼。
- 用創(chuàng)建好的實(shí)例調(diào)用 beforeRouteEnter守衛(wèi)中傳給 next 的回調(diào)函數(shù)查吊。
- 導(dǎo)航完成
vuex 和 localStorage
vuex 存在 內(nèi)存中, localStorage 以文件的方式存儲(chǔ)在本地,只能存儲(chǔ)字符串
vuex 刷新頁面會(huì)丟失 localStorage 不會(huì)
vue.Observable ()進(jìn)行狀態(tài)管理
vue 2.6.0 版本湖蜕, vuex 如果應(yīng)用不夠大逻卖,最好不要使用,可以使用跟這個(gè) 來進(jìn)行一個(gè)簡單的跨組件的 狀態(tài)管理
// 創(chuàng)建一個(gè) store.js
import Vue from 'vue'
// 導(dǎo)出數(shù)據(jù)模塊
export const store = Vue.observable({
data: {
name: 'liu'
}
})
// 導(dǎo)出 修改數(shù)據(jù)函數(shù) 模塊
export const mutations = {
updata(val) {
store.data.name = val
}
}
// …… 也可以定義 ations getters module
// 使用 在別的文件中使用 操作一樣
<button @click="editName">修改數(shù)據(jù)</button>
<button @click="edit('劉士朋')">修改數(shù)據(jù)</button>
import { store, mutations } from "@/utils/store.js";
editName() {
// 調(diào)用 修改
mutations.updata("劉");
},
// 或者
edit: mutations.updata,
虛擬DOM的理解
- 是對(duì) DOM 的抽象昭抒,無需手動(dòng)操作 DOM 评也,多次修改DOM修改的結(jié)果 一次性的更新到頁面上,減少頁面渲染次數(shù),減少修改DOM的重繪重排(回流), 提高渲染性能
- 解析過程:
- 把要插入 DOM 的結(jié)構(gòu)進(jìn)行分析灭返,使用 js 對(duì)象表示出來盗迟。然后將 js 對(duì)象樹 保存下來,最后將 DOM片段插入到文檔
- 頁面發(fā)生改變 對(duì)頁面重新進(jìn)行調(diào)整 熙含,首先根據(jù)變更狀態(tài) 重新構(gòu)建一棵樹诈乒,和舊樹進(jìn)行比較 ,記錄兩個(gè)樹的差異
- 最后將有差異的地方應(yīng)用到 DOM 樹上婆芦,視圖就更新了
- 為什么使用虛擬DOM :
- 避免不必要的更新,不是立即更新喂饥,通過 diff 算法 來找出不同 只修改不同的部分
diff算法原理
- 對(duì)比節(jié)點(diǎn)本身消约,是否為同一節(jié)點(diǎn),
- 不同:刪除重新創(chuàng)建员帮,替換
- 相同:進(jìn)行判斷或粮,有無子節(jié)點(diǎn),沒有就移除舊的捞高,有就 判斷如何對(duì)老節(jié)點(diǎn)的子節(jié)點(diǎn)操作
- 匹配時(shí)氯材,找到相同的子節(jié)點(diǎn),遞歸比較子節(jié)點(diǎn)硝岗,放棄跨節(jié)點(diǎn)比較 時(shí)間復(fù)雜度從 O(n^3)~O(n) 只有當(dāng)新舊節(jié)點(diǎn)為多個(gè)子節(jié)點(diǎn)時(shí)需要進(jìn)行同層比較
Vue3 有什么更新
- 檢測(cè)機(jī)制
- 基于 Proxy 的 ObServer 實(shí)現(xiàn)氢哮,提供了 全語言覆蓋,接觸了 Vue2 的 Object.defineProperty的很多限制型檀,
- 對(duì)象只能檢測(cè)屬性不能檢測(cè)對(duì)象
- 對(duì)象屬性 添加和刪除
- 數(shù)組 索引和長度修改
- vue3支持了 Set Map WeakSet WeakMap
- 模板
- 作用域插槽變成了函數(shù)方式
- 可以有多個(gè)根節(jié)點(diǎn)
- 對(duì)象的組件聲明方式
- 生命方式改成了 類式的寫法 setup() 和 ts 結(jié)合更容易
- 過濾器刪除冗尤,可以用計(jì)算屬性來代替
處理錯(cuò)誤(和警告)的更好方法
// Vue 3
const app = createApp(App);
app.config.errorHandler = (err) => {
alert(err);
};
// Vue 2
Vue.config.errorHandler = (err) => {
alert(err);
};
Es6
- 默認(rèn)參數(shù)
- 剩余參數(shù)
- 箭頭函數(shù)
- 字符串模板
- symbol
前后端API交互如何保證數(shù)據(jù)安全性
- 使用https通訊
- 請(qǐng)求簽名,防止參數(shù)被篡改
- 身份確認(rèn)機(jī)制,每次請(qǐng)求都要驗(yàn)證合法
- app中使用 ssl , 防止抓包操作
- 對(duì)所有請(qǐng)求響應(yīng)都加密
避免重繪和回流
- 操作DOM時(shí)裂七,盡量在底層的DOM節(jié)點(diǎn)操作皆看,
- 使用 Css表達(dá)式
- 不要頻繁操作元素樣式,直接修改類名背零,不要直接操作樣式
- 頻繁操作可以使用 documentFrament 文檔碎片操作
- 也可以先把樣式 display:none, 然后在顯示
- 把多個(gè)操作放一起腰吟,瀏覽器的渲染隊(duì)列會(huì)將操作放入隊(duì)列 ,然后一個(gè)重回回流完成渲染
常見瀏覽器兼容性問題
*{margin:0;padding:0;}
圖片默認(rèn)有間距 行內(nèi)塊 會(huì)有的 --》 float 或者 父元素 font-size:0 , 轉(zhuǎn)成塊元素
邊距重疊問題徙瓶,兩個(gè)相鄰的都設(shè)置了 margin 邊距 取最大值毛雇,使用 BFC 來清除
火狐瀏覽器不能使用 innerText 可以使用 textContent
超鏈接訪問后 hover 不顯示 解決是 按順序, L-V-H-A 來定義
火狐不支持 cursor:hand, 使用pointer
-
添加瀏覽器前綴
- 谷歌倍啥,蘋果 webkit
- ie -ms-
- 火狐 -moz-
- 歐朋 -o-
-
使用 hock 技術(shù)
<!--[if gte IE 9]> 只有 ie9 可以檢測(cè)到 <link rel="stylesheet" href="style9.css"> <![endif]-->
移動(dòng)端:
ios點(diǎn)擊事件300ms延遲禾乘,是移動(dòng)端區(qū)分 點(diǎn)擊和雙擊的∷渎疲可以用 fastCilck,js 來執(zhí)行始藕。原理:加快事件的響應(yīng)
底部輸入框被鍵盤擋住問題, 判斷瀏覽器高度氮趋,監(jiān)聽 resize 事件伍派,判斷 如果 寬度大于 當(dāng)前, 就把input 輸入框做定位處理剩胁,否則不變
ios 彈出各種操作窗口 webkit-touch-callout:none
-
消除 transition 閃屏:
webkit-transform-style: preserve-3d; /*設(shè)置內(nèi)嵌的元素在 3D 空間如何呈現(xiàn):保留 3D*/ -webkit-backface-visibility: hidden; /*(設(shè)置進(jìn)行轉(zhuǎn)換的元素的背面在面對(duì)用戶時(shí)是否可見:隱藏)*/
audio元素和video元素在無法自動(dòng)播放 應(yīng)對(duì)方案:觸屏即播, 使用觸屏播放 監(jiān)聽觸屏诉植,然后開始播放、
-
fixed定位缺陷
- ios下fixed元素定位容易出錯(cuò)昵观,鍵盤彈出的時(shí)候影響 fixed 元素定位
- 安卓下 不會(huì)影響 fixed 元素定位晾腔。
- 解決: 使用 iScroll插件解決。