<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          當(dāng)面試官問(wèn):為什么 Vue3.0 要重寫(xiě)響應(yīng)式系統(tǒng)?

          共 4034字,需瀏覽 9分鐘

           ·

          2021-01-24 10:39

          嗨,我是你穩(wěn)定更新、精通面試的勾勾。



          以前面試的時(shí)候經(jīng)常被問(wèn)到響應(yīng)式相關(guān)的內(nèi)容,而 Vue3.0 更新后,面試官又有了新的武器來(lái)考核面試者。


          面試官:為什么 Vue3.0 要重寫(xiě)響應(yīng)式系統(tǒng)?



          對(duì)于面試者來(lái)說(shuō),懵逼樹(shù)上懵逼果,懵逼樹(shù)下你和我,面試官在問(wèn)什么,我該怎么回答,完全不知道怎么回事。


          有些經(jīng)驗(yàn)的小伙伴可能會(huì)從解釋 Proxy 的好處開(kāi)始簡(jiǎn)單聊一下,比如,Proxy 是直接代理對(duì)象,而不是劫持對(duì)象的屬性,更好的數(shù)組監(jiān)控等。


          這樣的回答,勉強(qiáng)算是合格吧。


          那到底應(yīng)該怎么答呢,才能順利通過(guò)面試,贏得 offer?


          面試官背后的出題邏輯


          別急,咱們先整理一下思路,孫子兵法有云:“知己知彼,百戰(zhàn)不殆”


          面試就像打仗,你來(lái)我往,所以我們需要換位思考,想一想。


          為什么面試官會(huì)問(wèn)這樣一個(gè)問(wèn)題?

          面試官想從這個(gè)問(wèn)題里得到什么回答?

          這個(gè)問(wèn)題可以考察那些技術(shù)點(diǎn)?


          想清楚這些問(wèn)題,再回到自己身上,去思考這些技術(shù)點(diǎn)自己是否都已經(jīng)掌握。


          說(shuō)的直白一點(diǎn),面試就像考試,你需要先讀題審題才能答好這道題。


          為什么很多人認(rèn)為“面試造火箭,工作擰螺絲”?


          因?yàn)闆](méi)有換位思考,沒(méi)有想清楚面試題背后的邏輯。


          那我們想清楚這個(gè)邏輯之后,需要我們做的就是提取技術(shù)點(diǎn)——整理思路——做出對(duì)應(yīng)解答。


          當(dāng)然,前提是你需要具備這些技術(shù)能力。


          那么接下來(lái),我就嘗試拆解一下這個(gè)面試題了,提取其中的知識(shí)點(diǎn)。對(duì)于你來(lái)說(shuō),就是要看看這些知識(shí)點(diǎn),你都掌握了多少?


          為什么 Vue3.0 要重寫(xiě)響應(yīng)式系統(tǒng)?


          為什么要重寫(xiě)?


          如果之前好好的,重寫(xiě)就沒(méi)有意義。那之前存在什么問(wèn)題,現(xiàn)在是怎么解決的,這就是關(guān)鍵點(diǎn)了。


          不知道你對(duì) Vue2.x 的響應(yīng)式掌握多少,是不是欠下了技術(shù)的債呢?


          沒(méi)關(guān)系,我來(lái)幫你還債,先梳理 Vue2.x 的響應(yīng)式。


          其實(shí)基于這個(gè)面試題,背后還有很多技術(shù)點(diǎn)。上面這些,是與當(dāng)前題目有直接關(guān)系的。在實(shí)際面試中,很有可能基于這些技術(shù)點(diǎn),再進(jìn)行深入交流,這里就不擴(kuò)展了,你能把現(xiàn)在這些問(wèn)題理清楚,就算賺到了!



          Vue2.x 響應(yīng)式


          關(guān)于這一點(diǎn),在 Vue 的官方文檔中,早已經(jīng)有過(guò)說(shuō)明了,而且說(shuō)的非常詳細(xì)。


          官方文檔:

          https://cn.vuejs.org/v2/guide/reactivity.html



          當(dāng)你把一個(gè)普通的 JavaScript 對(duì)象傳入 Vue 實(shí)例作為 data 選項(xiàng),Vue 將遍歷此對(duì)象所有的 property,并使用 Object.defineProperty 把這些 property 全部轉(zhuǎn)為 getter/setter。


          Object.defineProperty 是 ES5 中一個(gè)無(wú)法 shim 的特性,這也就是 Vue 不支持 IE8 以及更低版本瀏覽器的原因。


          這些 getter/setter 對(duì)用戶來(lái)說(shuō)是不可見(jiàn)的,但是在內(nèi)部它們讓 Vue 能夠追蹤依賴(lài),在 property 被訪問(wèn)和修改時(shí)通知變更。


          這里需要注意的是,不同瀏覽器在控制臺(tái)打印數(shù)據(jù)對(duì)象時(shí)對(duì) getter/setter 的格式化并不同,所以建議安裝 vue-devtools 來(lái)獲取對(duì)檢查數(shù)據(jù)更加友好的用戶界面。


          每個(gè)組件實(shí)例都對(duì)應(yīng)一個(gè) watcher 實(shí)例,它會(huì)在組件渲染的過(guò)程中把“接觸”過(guò)的數(shù)據(jù) property 記錄為依賴(lài)。之后當(dāng)依賴(lài)項(xiàng)的 setter 觸發(fā)時(shí),會(huì)通知 watcher,從而使它關(guān)聯(lián)的組件重新渲染。


          我們使用官方給的一張圖示,來(lái)梳理整個(gè)流程。



          先來(lái)看一段代碼:



          響應(yīng)式原理


          data 中的 obj 就是一個(gè)普通的 JavaScript 對(duì)象,通過(guò)點(diǎn)擊 Click 按鈕,將獲取到的隨機(jī)數(shù)賦值給 this.message ,而 this.message 指向的就是 data 中 obj 對(duì)象的 message 屬性。


          當(dāng) message 發(fā)生數(shù)據(jù)改變時(shí),頁(yè)面中 H1 標(biāo)簽的內(nèi)容會(huì)隨之改變,這個(gè)過(guò)程就是就是響應(yīng)式的。


          那么 Vue 是如何實(shí)現(xiàn)的呢?


          首先,Vue 內(nèi)部使用 Object.defineProperty() 將 Data 中的每一個(gè)成員都轉(zhuǎn)換為 getter / setter 的形式。


          getter 用來(lái)依賴(lài)收集,setter 用來(lái)派發(fā)更新。而模板內(nèi)容,最終會(huì)被編譯為 render 函數(shù)。


          在 render 函數(shù)中,我們能發(fā)現(xiàn)?_v(_s(message)) message 被訪問(wèn)了,就會(huì)觸發(fā) getter 來(lái)進(jìn)行依賴(lài)收集。


          而在代碼中的點(diǎn)擊事件中,一旦事件處理程序被觸發(fā)執(zhí)行,那么 message 則會(huì)被修改,就會(huì)觸發(fā) setter 來(lái)進(jìn)行派發(fā)更新。


          雖然流程理清楚了,但是總感覺(jué)少點(diǎn)什么,怎么才能更通透呢?


          我們用代碼來(lái)模擬整個(gè)的實(shí)現(xiàn)過(guò)程。


          defineProperty 模擬代碼


          defineProperty 的基本用法,直接看手冊(cè)就行了:


          https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty


          我們來(lái)看看代碼:

          <div id="app">     hello div> <script>     // 模擬 Vue 中的 data 選項(xiàng)     let data = {       msg: 'hello'     }     // 模擬 Vue 的實(shí)例     let vm = {}     // 數(shù)據(jù)劫持:當(dāng)訪問(wèn)或者設(shè)置 vm 中的成員的時(shí)候,做一些干預(yù)操作     Object.defineProperty(vm, 'msg', {       // 可枚舉(可遍歷)       enumerable: true,       // 可配置(可以使用 delete 刪除,可以通過(guò) defineProperty 重新定義)       configurable: true,       // 當(dāng)獲取值的時(shí)候執(zhí)行       get () {         console.log('get: ', data.msg)         return data.msg       },       // 當(dāng)設(shè)置值的時(shí)候執(zhí)行       set (newValue) {         console.log('set: ', newValue)         if (newValue === data.msg) {           return         }         data.msg = newValue         // 數(shù)據(jù)更改,更新 DOM 的值         document.querySelector('#app').textContent = data.msg       }     })     // 測(cè)試     vm.msg = 'Hello World'     console.log(vm.msg) script>


          你沒(méi)有看錯(cuò),加上注釋?zhuān)还?36行代碼,這就是 Vue2.x 對(duì)響應(yīng)式實(shí)現(xiàn)的整個(gè)流程。


          ?繼續(xù)實(shí)現(xiàn)多個(gè)數(shù)據(jù)的響應(yīng)。

          <body>  <div id="app">    hello  div>  <script>    // 模擬 Vue 中的 data 選項(xiàng)    let data = {      msg: 'hello',      count: 10    }    // 模擬 Vue 的實(shí)例    let vm = {}    proxyData(data)    function proxyData(data) {      // 遍歷 data 對(duì)象的所有屬性      Object.keys(data).forEach(key => {        // 把 data 中的屬性,轉(zhuǎn)換成 vm 的 setter/setter        Object.defineProperty(vm, key, {          enumerable: true,          configurable: true,          get () {            console.log('get: ', key, data[key])            return data[key]          },          set (newValue) {            console.log('set: ', key, newValue)            if (newValue === data[key]) {              return            }            data[key] = newValue            // 數(shù)據(jù)更改,更新 DOM 的值            document.querySelector('#app').textContent = data[key]          }        })      })    }    // 測(cè)試    vm.msg = 'Hello World'    console.log(vm.msg)script>body>


          上面的代碼只是模擬了響應(yīng)式的原理,但 Vue 在實(shí)現(xiàn)中,肯定不會(huì)那么簡(jiǎn)單。


          下周一,我們來(lái)康康源碼(●'?'●)。


          推薦閱讀:

          喜大普奔!Element UI for Vue 3.0 來(lái)了!

          Proxy 代理對(duì)象

          不小心將 Webpack 升級(jí)后我搞定了微前端。

          別覺(jué)得搞前端就不需要懂后臺(tái)知識(shí)。

          騰訊QQ偷我瀏覽記錄到底想干嘛。

          是我 Web 端配不上阿里了。


          點(diǎn)點(diǎn)“”和“在看”,保護(hù)頭發(fā),減少bug。

          瀏覽 81
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产综合久久久777777 | 欧美成人精品欧美一级私黄 | 人人操操人人操操 | 一级黄色影院 | 欧美色图视频网址 |