Vue 面試

Vue是什么

是一套漸進(jìn)式框架澡屡,與其他框架不同的是,Vue可以自底向上逐層應(yīng)用咐旧,vue核心只關(guān)注視圖層驶鹉,容易上手,方便與第三方庫整合铣墨,可以完成復(fù)雜的單頁面應(yīng)該提供驅(qū)動(dòng)

Vue的優(yōu)點(diǎn)

  1. 輕量級(jí)框架:只關(guān)注視圖室埋,構(gòu)建視圖的集合
  2. 簡單易學(xué),中文文檔沒有語言障礙
  3. 雙向數(shù)據(jù)綁定伊约,操作數(shù)據(jù)簡單
  4. 組件化姚淆,構(gòu)建單頁面應(yīng)該有優(yōu)勢(shì)
  5. 視圖數(shù)據(jù)分離,使用數(shù)據(jù)更方便
  6. 虛擬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

  1. mvc 通過 model , view 和 controller 的方式組織代碼結(jié)構(gòu)巾乳,view負(fù)責(zé)頁面顯示您没,model負(fù)責(zé)存儲(chǔ)業(yè)務(wù)數(shù)據(jù)和相應(yīng)數(shù)據(jù)操作,并且view和model 使用了觀察者模式
  2. 當(dāng) model 改變時(shí) 通知 有關(guān) view 更新頁面胆绊,controller 是view 和 model的紐帶,通過 view 來 對(duì) model 更改欧募,然后 model 再去通知 view 更新压状,過程都是單向的

MVVM

  1. model 代表數(shù)據(jù)模型,view 代表UI視圖跟继, view,model 負(fù)責(zé) 監(jiān)聽model的變化控制視圖种冬,視圖變化 通知數(shù)據(jù),
  2. view 和 model 沒有關(guān)系舔糖,是通過viewmodel 來進(jìn)行聯(lián)系的
  3. 缺點(diǎn)
    • 難調(diào)試娱两,大模塊,使用方便和保證數(shù)據(jù)的一致性金吗,但不釋放內(nèi)存造成很多開銷
    • 大的圖形應(yīng)用程序 十兢, 視圖裝太多,viewmodel構(gòu)架維護(hù)成本高

MVP

  1. 和 MVC 唯一不同的 在于 Presenter 和 Controller 摇庙,MVC在model 發(fā)生變化的時(shí)候旱物,通知 view ,view 和 model 偶合在一起卫袒,邏輯復(fù)雜的時(shí)候宵呛,代碼可能造成混亂,并對(duì)復(fù)用造成一些問題
  2. 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)化

  1. 編碼階段
    • 盡量減少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ū)再加載
    • 圖片懶加載
  2. SEO 優(yōu)化
  • 服務(wù)端 渲染 SSR
  1. 打包優(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ò)
  1. 用戶優(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)用首屏加載速度

  1. 減小入口文件
  2. 靜態(tài)資源本地緩存
  3. 圖片資源壓縮综看,合并(精靈圖)
  4. 開啟 gzip 壓縮包
  5. 品腹、使用服務(wù)器渲染

Vue 初次渲染

  1. 步驟 :
    1. $mount () : 初始化 Vue
    2. mountComponent : (渲染的入口函數(shù))
    3. _render:(執(zhí)行render函數(shù),獲得虛擬DOM)
    4. __update:(將虛擬DOM轉(zhuǎn)真實(shí)DOM并渲染)

Computed 和 Watch

computed

  1. 支持緩存红碑,依賴的數(shù)據(jù)發(fā)生變化才會(huì)重新計(jì)算
  2. 不支持異步舞吭,當(dāng)有計(jì)算屬性的時(shí)候,無法監(jiān)聽數(shù)據(jù)變化
  3. 默認(rèn)走緩存析珊,基于依賴的響應(yīng)式進(jìn)行緩存羡鸥,或者 父組件傳遞過來的props 的數(shù)據(jù)進(jìn)行計(jì)算
  4. 可以使用 getter 和 setter 方法更靈活

watch

  1. 不支持緩存,數(shù)據(jù)變化 會(huì)觸發(fā)響應(yīng)的操作
  2. 支持異步監(jiān)聽忠寻,兩個(gè)參數(shù)惧浴,一個(gè)是最新的值,第二個(gè)是舊值
  3. 當(dāng)一個(gè)屬性發(fā)生變化就做像一個(gè)的操作
  4. immediate: 立即監(jiān)視奕剃, deep : 深度監(jiān)視 衷旅, handle: 監(jiān)聽函數(shù)

使用場景:

  1. 計(jì)算 當(dāng)進(jìn)行計(jì)算,可以依賴緩存特性祭饭,避免每次都要計(jì)算
  2. 當(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)插槽,具名插槽和作用域插槽

  1. 默認(rèn): 匿名插槽凉驻,slot 沒有 name 屬性值的時(shí)候顯示 默認(rèn)的腻要,一個(gè)組件只能有一個(gè)匿名
  2. 具名:帶有名字的插槽,可以有多個(gè)
  3. 作用域: 可以有名字也可以無涝登,不同點(diǎn)雄家,在子組件渲染時(shí),可以將子組件內(nèi)部的數(shù)據(jù)傳遞給父組件胀滚,父組件根據(jù)子組件的數(shù)據(jù)決定如何渲染

vue 的 hook 使用

  1. 清除定時(shí)器

     // 清除定時(shí)器
     const timer = setInterval(() => {
     console.log(1);
     }, 1000);
    // $once 監(jiān)聽趟济,只觸發(fā)一次 
    // 使用 hook 調(diào)用 銷毀前的生命周期函數(shù) 清空定時(shí)器
     this.$once("hook:beforeDestroy", () => {
     clearInterval(timer);
     });
    
  2. 父組件監(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ì)被卸載

卸載
  1. 將狀態(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不好控制,容易失效
  2. 路由傳值:通過路由傳參其监,可以實(shí)現(xiàn)簡單的路由傳值
    • 優(yōu)點(diǎn):簡單萌腿,不污染localstorage... 可以傳遞Date正則(彌補(bǔ)上面)
    • 缺點(diǎn):跳轉(zhuǎn)別的組件也帶著數(shù)據(jù)
不被卸載
  1. 要切換的組件是子組件,父組件中正常存儲(chǔ)頁面狀態(tài) 抖苦,可以用 <keep-alive> 來緩存頁面 組件在切換 調(diào)用 activateddeactivated 聲明周期函數(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ā)

常用的事件修飾符

  1. .stop ==> event.stopPropagation() 阻止事件冒泡
  2. .prevent ==> event.preventDefault() 取消默認(rèn)事件泥技,不停止傳播
  3. .capture ==> 事件捕獲
  4. .self ==> 只觸發(fā)自己范圍內(nèi)的事件钧汹, 不包含子元素
  5. .once ==> 只會(huì)觸發(fā)一次

v-if聊疲、v-show济榨、v-html

  1. v-if 懶惰的克婶, 第一次是 false 就不加載扇丛,切換時(shí) 標(biāo)簽創(chuàng)建銷毀术吗, 在虛擬 dom 操作,開銷比 v-show 大 原理: VNode 不會(huì)生成
  2. v-show 直接創(chuàng)建 顯示和隱藏都是用 css display 來控制的帆精,直接生成较屿,在用 display:none隱藏
  3. 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)用和多頁面

  1. SPA單頁面:只有一個(gè)主頁面,一開始只用加載一次 css,js 相關(guān)資源务荆,所有內(nèi)容都在主頁面妆距,對(duì)每一個(gè)功能都模塊化,跳轉(zhuǎn)就是切換組件函匕,只刷新局部資源
  2. 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

  1. 使用場景

    • 普通 DOM 元素進(jìn)行底層操作,
    • 自定義指令用來操作 DOM 可以定義任何 DOM 操作迹辐,并且可以復(fù)用
  2. 使用案例

    • 鼠標(biāo)聚焦
    • 圖片加載錯(cuò)誤問題蝶防,懶加載
  3. 屬性: 第一個(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ā)窒盐。
  4. 簡寫 如果你想在 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模版編譯原理

  1. 解析階段:使用大量正則伯铣,對(duì) template 字符串解析呻此,將 標(biāo)簽,指令腔寡,屬性轉(zhuǎn)為抽象語法樹 AST
  2. 優(yōu)化階段: 遍歷 AST 找其中的靜態(tài)節(jié)點(diǎn)進(jìn)行標(biāo)記焚鲜,方便在重新渲染的時(shí)候進(jìn)行 diff 比較時(shí) ,跳過一些靜態(tài)節(jié)點(diǎn)
  3. 生成階段:將 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í)行順序

  1. 加載渲染過程
    • 父組件 beforeCreate
    • 父組件 created
    • 父組件 beforeMount
    • 子組件 beforeCreate
    • 子組件 created
    • 子組件 beforeMount
    • 子組件 mounted
    • 父組件 mounted
  2. 更新過程
    • 父組件 beforeUpdate
    • 子組件 beforeUpdate
    • 子組件 updated
    • 父組件 updated
  3. 銷毀過程:
    • 父組件 beforeDestroy
    • 子組件 beforeDestroy
    • 子組件 destroyed
    • 父組件 destoryed

組件通訊

  1. 父子組件
    • props / $emit
    • ref /refs
    • $attrs / $listeners
  2. 兄弟
    • $parent | $refs | $children
  3. 任意
    • eventBus 事件總線
    • .Observable 自定義一個(gè)小型的 vuex
    • Vuex

路由的 hash 和 history 炒辉,abstract-- 抽象模式 服務(wù)器的

  1. hash
    • 在url 有 # 豪墅, http 請(qǐng)求沒有,對(duì)后端沒影響黔寇,改變 hash 不會(huì)重新加載頁面偶器,對(duì)瀏覽器支持友好,成為 SPA(單頁面)標(biāo)配
    • 原理 : 監(jiān)聽 onhashchange() 事件
  2. 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

路由聲明周期

  1. 完成路由導(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ù)
  2. 觸發(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腺晾。
  3. 導(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的理解

  1. 是對(duì) DOM 的抽象昭抒,無需手動(dòng)操作 DOM 评也,多次修改DOM修改的結(jié)果 一次性的更新到頁面上,減少頁面渲染次數(shù),減少修改DOM的重繪重排(回流), 提高渲染性能
  2. 解析過程:
    • 把要插入 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 樹上婆芦,視圖就更新了
  3. 為什么使用虛擬DOM :
    • 避免不必要的更新,不是立即更新喂饥,通過 diff 算法 來找出不同 只修改不同的部分

diff算法原理

  1. 對(duì)比節(jié)點(diǎn)本身消约,是否為同一節(jié)點(diǎn),
    • 不同:刪除重新創(chuàng)建员帮,替換
    • 相同:進(jìn)行判斷或粮,有無子節(jié)點(diǎn),沒有就移除舊的捞高,有就 判斷如何對(duì)老節(jié)點(diǎn)的子節(jié)點(diǎn)操作
  2. 匹配時(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 有什么更新

  1. 檢測(cè)機(jī)制
    • 基于 Proxy 的 ObServer 實(shí)現(xiàn)氢哮,提供了 全語言覆蓋,接觸了 Vue2 的 Object.defineProperty的很多限制型檀,
  2. 對(duì)象只能檢測(cè)屬性不能檢測(cè)對(duì)象
    • 對(duì)象屬性 添加和刪除
    • 數(shù)組 索引和長度修改
    • vue3支持了 Set Map WeakSet WeakMap
  3. 模板
    • 作用域插槽變成了函數(shù)方式
    • 可以有多個(gè)根節(jié)點(diǎn)
  4. 對(duì)象的組件聲明方式
    • 生命方式改成了 類式的寫法 setup() 和 ts 結(jié)合更容易
  5. 過濾器刪除冗尤,可以用計(jì)算屬性來代替

處理錯(cuò)誤(和警告)的更好方法

// Vue 3
const app = createApp(App);
app.config.errorHandler = (err) => {
  alert(err);
};

// Vue 2
Vue.config.errorHandler = (err) => {
  alert(err);
};

Es6

  1. 默認(rèn)參數(shù)
  2. 剩余參數(shù)
  3. 箭頭函數(shù)
  4. 字符串模板
  5. symbol

前后端API交互如何保證數(shù)據(jù)安全性

  1. 使用https通訊
  2. 請(qǐng)求簽名,防止參數(shù)被篡改
  3. 身份確認(rèn)機(jī)制,每次請(qǐng)求都要驗(yàn)證合法
  4. app中使用 ssl , 防止抓包操作
  5. 對(duì)所有請(qǐng)求響應(yīng)都加密

避免重繪和回流

  1. 操作DOM時(shí)裂七,盡量在底層的DOM節(jié)點(diǎn)操作皆看,
  2. 使用 Css表達(dá)式
  3. 不要頻繁操作元素樣式,直接修改類名背零,不要直接操作樣式
  4. 頻繁操作可以使用 documentFrament 文檔碎片操作
  5. 也可以先把樣式 display:none, 然后在顯示
  6. 把多個(gè)操作放一起腰吟,瀏覽器的渲染隊(duì)列會(huì)將操作放入隊(duì)列 ,然后一個(gè)重回回流完成渲染

常見瀏覽器兼容性問題

  1. *{margin:0;padding:0;}

  2. 圖片默認(rèn)有間距 行內(nèi)塊 會(huì)有的 --》 float 或者 父元素 font-size:0 , 轉(zhuǎn)成塊元素

  3. 邊距重疊問題徙瓶,兩個(gè)相鄰的都設(shè)置了 margin 邊距 取最大值毛雇,使用 BFC 來清除

  4. 火狐瀏覽器不能使用 innerText 可以使用 textContent

  5. 超鏈接訪問后 hover 不顯示 解決是 按順序, L-V-H-A 來定義

  6. 火狐不支持 cursor:hand, 使用pointer

  7. 添加瀏覽器前綴

    • 谷歌倍啥,蘋果 webkit
    • ie -ms-
    • 火狐 -moz-
    • 歐朋 -o-
  8. 使用 hock 技術(shù)

    <!--[if gte IE 9]>  只有 ie9 可以檢測(cè)到
         <link rel="stylesheet" href="style9.css">
    <![endif]-->
    

    移動(dòng)端:

    1. ios點(diǎn)擊事件300ms延遲禾乘,是移動(dòng)端區(qū)分 點(diǎn)擊和雙擊的∷渎疲可以用 fastCilck,js 來執(zhí)行始藕。原理:加快事件的響應(yīng)

    2. 底部輸入框被鍵盤擋住問題, 判斷瀏覽器高度氮趋,監(jiān)聽 resize 事件伍派,判斷 如果 寬度大于 當(dāng)前, 就把input 輸入框做定位處理剩胁,否則不變

    3. ios 彈出各種操作窗口 webkit-touch-callout:none

    4. 消除 transition 閃屏:

      webkit-transform-style: preserve-3d;     /*設(shè)置內(nèi)嵌的元素在 3D 空間如何呈現(xiàn):保留 3D*/
      -webkit-backface-visibility: hidden;      /*(設(shè)置進(jìn)行轉(zhuǎn)換的元素的背面在面對(duì)用戶時(shí)是否可見:隱藏)*/
      
    5. audio元素和video元素在無法自動(dòng)播放 應(yīng)對(duì)方案:觸屏即播, 使用觸屏播放 監(jiān)聽觸屏诉植,然后開始播放、

    6. fixed定位缺陷

      1. ios下fixed元素定位容易出錯(cuò)昵观,鍵盤彈出的時(shí)候影響 fixed 元素定位
      2. 安卓下 不會(huì)影響 fixed 元素定位晾腔。
      3. 解決: 使用 iScroll插件解決。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末啊犬,一起剝皮案震驚了整個(gè)濱河市灼擂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌觉至,老刑警劉巖剔应,帶你破解...
    沈念sama閱讀 216,324評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異语御,居然都是意外死亡峻贮,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,356評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門应闯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來纤控,“玉大人,你說我怎么就攤上這事碉纺〗狼” “怎么了细层?”我有些...
    開封第一講書人閱讀 162,328評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長唬涧。 經(jīng)常有香客問我疫赎,道長,這世上最難降的妖魔是什么碎节? 我笑而不...
    開封第一講書人閱讀 58,147評(píng)論 1 292
  • 正文 為了忘掉前任捧搞,我火速辦了婚禮,結(jié)果婚禮上狮荔,老公的妹妹穿的比我還像新娘胎撇。我一直安慰自己,他們只是感情好殖氏,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,160評(píng)論 6 388
  • 文/花漫 我一把揭開白布晚树。 她就那樣靜靜地躺著,像睡著了一般雅采。 火紅的嫁衣襯著肌膚如雪爵憎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,115評(píng)論 1 296
  • 那天婚瓜,我揣著相機(jī)與錄音宝鼓,去河邊找鬼。 笑死巴刻,一個(gè)胖子當(dāng)著我的面吹牛愚铡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播胡陪,決...
    沈念sama閱讀 40,025評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼沥寥,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了柠座?” 一聲冷哼從身側(cè)響起邑雅,我...
    開封第一講書人閱讀 38,867評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎愚隧,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體锻全,經(jīng)...
    沈念sama閱讀 45,307評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡狂塘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,528評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鳄厌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片荞胡。...
    茶點(diǎn)故事閱讀 39,688評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖了嚎,靈堂內(nèi)的尸體忽然破棺而出泪漂,到底是詐尸還是另有隱情廊营,我是刑警寧澤,帶...
    沈念sama閱讀 35,409評(píng)論 5 343
  • 正文 年R本政府宣布萝勤,位于F島的核電站露筒,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏敌卓。R本人自食惡果不足惜慎式,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,001評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望趟径。 院中可真熱鬧瘪吏,春花似錦、人聲如沸蜗巧。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,657評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽幕屹。三九已至蓝丙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間香嗓,已是汗流浹背迅腔。 一陣腳步聲響...
    開封第一講書人閱讀 32,811評(píng)論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留靠娱,地道東北人沧烈。 一個(gè)月前我還...
    沈念sama閱讀 47,685評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像像云,于是被迫代替她去往敵國和親锌雀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,573評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容