<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>

          Vue 3.0 中的響應(yīng)式是如何實(shí)現(xiàn)的?

          共 3425字,需瀏覽 7分鐘

           ·

          2021-01-25 19:33

          (????)??嗨,我是你穩(wěn)定更新、持續(xù)輸出的勾勾。



          在上篇《當(dāng)面試官問:為什么 Vue3.0 要重寫響應(yīng)式系統(tǒng)?》中,我們梳理了響應(yīng)式原理的相關(guān)內(nèi)容。本篇,來看看源碼。


          Vue2 源碼解讀


          首先找到響應(yīng)式代碼的處理位置:



          看完Vue2.x 響應(yīng)式的代碼,我們?cè)倩剡^頭來思考最開始的問題,為什么 Vue3.0 要重寫響應(yīng)式系統(tǒng)?


          為什么重寫?如果之前好好的,重寫就沒有意義。


          那之前存在什么問題,換句話問就是 defineProperty 有什么問題?


          Object.defineProperty 的問題


          其實(shí), defineProperty 的問題,在 Vue2.x 的手冊(cè)中已經(jīng)說過了。


          “哎,很多人就是不看文檔啊”


          https://cn.vuejs.org/v2/guide/reactivity.html#%E5%AF%B9%E4%BA%8E%E6%95%B0%E7%BB%84


          下面分別使用 Vue2 和 Vue3 實(shí)現(xiàn)了一個(gè)小功能,代碼一模一樣,功能當(dāng)然也一樣,但是,在 Vue2 中就會(huì)有 Bug,而運(yùn)行在 vue3 中的,則沒有任何問題。


          Vue2:

          <template>  <div class="about">    <h1>This is an about pageh1>    <p v-for="(v, k) in users">      {{ v.names }}    p>    <button @click="changes">更新button>  div>template>
          <script>export default { data() { return { users: [ { id: 1, names: "路飛-v2" }, { id: 2, names: "鳴人-v2" }, ], }; },
          methods: { changes() { // this.users[0] = {id:'0',names:'liuneng'} // this.users[1].names = 'lnsdsdfg' this.users[1] = { id: "1", names: "劉能-v2" }; }, },};script>
          <style lang="stylus" scoped>style>


          Vue3:

          <template>  <div class="about">    <h1>This is an about pageh1>    <p v-for="(v, k) in users">      {{ v.names }}    p>
          <button @click="changes">更新button> div>template>
          <script>export default { data() { return { users: [ { id: 1, names: "路飛-v3" }, { id: 2, names: "鳴人-v3" }, ], }; },
          methods: { changes() { // this.users[0] = {id:'0',names:'liuneng'} // this.users[1].names = 'lnsdsdfg' this.users[1] = { id: "1", names: "劉能-v3" }; }, },};script>


          其核心點(diǎn)在于 defineProperty 不能很好的實(shí)現(xiàn)對(duì)數(shù)組下標(biāo)的監(jiān)控,而在 Vue2 的實(shí)現(xiàn)代碼中,沒有更好的方案對(duì)此進(jìn)行改善,尤大索性直接放棄了實(shí)現(xiàn)。


          關(guān)于這個(gè)問題,尤大也在 github 做過回應(yīng),截個(gè)圖給大家看看。



          那么,Vue 目前還沒有解決的問題,Vue3 中顯然是已經(jīng)解決了。


          問題是,Vue3 是如何解決的呢?


          前面在 Vue3 的代碼中我們使用的是傳統(tǒng)的 Options Api 來實(shí)現(xiàn)數(shù)據(jù)響應(yīng)式,而在 Vue3 中全新的 Composition Api 也實(shí)現(xiàn)了響應(yīng)式系統(tǒng)。


          我們先來感受一下 Composition Api 的基礎(chǔ)用法.


          Composition API 的響應(yīng)式系統(tǒng)


          ref 響應(yīng)式

          <template>    <button @click="addNu"> Composition API: {{nu}}button>template>
          <script>// 引入 ref import {ref} from "vue"export default { setup() { // 定義 ref 響應(yīng)式數(shù)據(jù) const nu = ref(1); // 定義函數(shù) function addNu(){ nu.value++; }
          // 將數(shù)據(jù)和方法返回,即可在模板中直接使用 return { nu, addNu }; },};script>


          reactive 響應(yīng)式

          <template>    <button @click="addNu"> Composition API: {{nu}}button>    <h2>{{revData.name}}h2>  <h3 @click="ageAdd">年齡:{{revData.age}}h3>  <p v-for="(v,k) in revData.skill"> {{v}} p> template>
          <script>// 引入 ref import {reactive, ref} from "vue"export default { setup() { // 定義 ref 響應(yīng)式數(shù)據(jù) const nu = ref(1);
          // reactive 響應(yīng)式數(shù)據(jù) const revData = reactive({ name: '路飛', age: 22, skill:['橡膠機(jī)關(guān)槍','吃雞腿'], })
          function ageAdd(){ revData.age++ }
          // 定義函數(shù) function addNu(){ nu.value++; }
          // 將數(shù)據(jù)和方法返回,即可在模板中直接使用 return { nu, addNu, revData, ageAdd }; },};script>


          Vue3 中的響應(yīng)式是如何實(shí)現(xiàn)的呢?


          關(guān)鍵點(diǎn)在于 Proxy 函數(shù)。


          Proxy 實(shí)現(xiàn)原理


          使用 Proxy 實(shí)現(xiàn)的響應(yīng)式代碼,要比使用 defineProperty 的代碼簡(jiǎn)單得多。


          因?yàn)?Proxy 天然地能夠?qū)φ麄€(gè)對(duì)象做監(jiān)聽,而不需要對(duì)數(shù)據(jù)行遍歷后做監(jiān)聽,同時(shí)也就解決了數(shù)組下標(biāo)的問題。


          我們來一段模擬代碼看一下:

          <div id="app">    hello  div>  <script>    // 模擬 Vue 中的 data 選項(xiàng)    let data = {      msg: 'hello',      count: 0    }
          // 模擬 Vue 實(shí)例 const vm = new Proxy(data, { // 執(zhí)行代理行為的函數(shù) // 當(dāng)訪問 vm 的成員會(huì)執(zhí)行 get (target, key) { console.log('get, key: ', key, target[key]) return target[key] }, // 當(dāng)設(shè)置 vm 的成員會(huì)執(zhí)行 set (target, key, newValue) { console.log('set, key: ', key, newValue) if (target[key] === newValue) { return } target[key] = newValue document.querySelector('#app').textContent = target[key] } })
          // 測(cè)試 vm.msg = 'Hello World' console.log(vm.msg)script>


          好了,如果面試官再問你“為什么 Vue3.0 要重寫響應(yīng)式系統(tǒng)”,你該知道怎么回答了叭(●'?'●)。


          推薦閱讀:

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

          喜大普奔!Element UI for Vue 3.0 來了!

          Proxy 代理對(duì)象

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

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

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

          是我 Web 端配不上阿里了。


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

          瀏覽 80
          點(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>
                  囯产精品久久久久久久 | 19日韩福利视频 | 特级西西444Ww高清大胆 | 亚洲天堂精品视频 | 澳门久久 |