日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > vue >内容正文

vue

vue openlayer单击地图事件循环多次执行_12道vue高频原理面试题,你能答出几道?

發(fā)布時間:2023/12/10 vue 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 vue openlayer单击地图事件循环多次执行_12道vue高频原理面试题,你能答出几道? 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前言

本文分享 12 道 vue 高頻原理面試題,覆蓋了 vue 核心實現(xiàn)原理,其實一個框架的實現(xiàn)原理一篇文章是不可能說完的,希望通過這 12 道問題,讓讀者對自己的 Vue 掌握程度有一定的認識(B 數(shù)),從而彌補自己的不足,更好的掌握 Vue ??

1. Vue 響應(yīng)式原理

vue-reactive

核心實現(xiàn)類:

Observer : 它的作用是給對象的屬性添加 getter 和 setter,用于依賴收集和派發(fā)更新

Dep : 用于收集當前響應(yīng)式對象的依賴關(guān)系,每個響應(yīng)式對象包括子對象都擁有一個 Dep 實例(里面 subs 是 Watcher 實例數(shù)組),當數(shù)據(jù)有變更時,會通過 dep.notify()通知各個 watcher。

Watcher : 觀察者對象 , 實例分為渲染 watcher (render watcher),計算屬性 watcher (computed watcher),偵聽器 watcher(user watcher)三種

Watcher 和 Dep 的關(guān)系

watcher 中實例化了 dep 并向 dep.subs 中添加了訂閱者,dep 通過 notify 遍歷了 dep.subs 通知每個 watcher 更新。

依賴收集

  • initState 時,對 computed 屬性初始化時,觸發(fā) computed watcher 依賴收集

  • initState 時,對偵聽屬性初始化時,觸發(fā) user watcher 依賴收集

  • render()的過程,觸發(fā) render watcher 依賴收集

  • re-render 時,vm.render()再次執(zhí)行,會移除所有 subs 中的 watcer 的訂閱,重新賦值。

  • 派發(fā)更新

  • 組件中對響應(yīng)的數(shù)據(jù)進行了修改,觸發(fā) setter 的邏輯

  • 調(diào)用 dep.notify()

  • 遍歷所有的 subs(Watcher 實例),調(diào)用每一個 watcher 的 update 方法。

  • 原理

    當創(chuàng)建 Vue 實例時,vue 會遍歷 data 選項的屬性,利用 Object.defineProperty 為屬性添加 getter 和 setter 對數(shù)據(jù)的讀取進行劫持(getter 用來依賴收集,setter 用來派發(fā)更新),并且在內(nèi)部追蹤依賴,在屬性被訪問和修改時通知變化。

    每個組件實例會有相應(yīng)的 watcher 實例,會在組件渲染的過程中記錄依賴的所有數(shù)據(jù)屬性(進行依賴收集,還有 computed watcher,user watcher 實例),之后依賴項被改動時,setter 方法會通知依賴與此 data 的 watcher 實例重新計算(派發(fā)更新),從而使它關(guān)聯(lián)的組件重新渲染。

    一句話總結(jié):

    vue.js 采用數(shù)據(jù)劫持結(jié)合發(fā)布-訂閱模式,通過 Object.defineproperty 來劫持各個屬性的 setter,getter,在數(shù)據(jù)變動時發(fā)布消息給訂閱者,觸發(fā)響應(yīng)的監(jiān)聽回調(diào)

    2. computed 的實現(xiàn)原理

    computed 本質(zhì)是一個惰性求值的觀察者。

    computed 內(nèi)部實現(xiàn)了一個惰性的 watcher,也就是 computed watcher,computed watcher 不會立刻求值,同時持有一個 dep 實例。

    其內(nèi)部通過 this.dirty 屬性標記計算屬性是否需要重新求值。

    當 computed 的依賴狀態(tài)發(fā)生改變時,就會通知這個惰性的 watcher,

    computed watcher 通過 this.dep.subs.length 判斷有沒有訂閱者,

    有的話,會重新計算,然后對比新舊值,如果變化了,會重新渲染。(Vue 想確保不僅僅是計算屬性依賴的值發(fā)生變化,而是當計算屬性最終計算的值發(fā)生變化時才會觸發(fā)渲染 watcher 重新渲染,本質(zhì)上是一種優(yōu)化。)

    沒有的話,僅僅把 this.dirty = true。(當計算屬性依賴于其他數(shù)據(jù)時,屬性并不會立即重新計算,只有之后其他地方需要讀取屬性的時候,它才會真正計算,即具備 lazy(懶計算)特性。)

    3. computed 和 watch 有什么區(qū)別及運用場景?

    區(qū)別

    computed 計算屬性 : 依賴其它屬性值,并且 computed 的值有緩存,只有它依賴的屬性值發(fā)生改變,下一次獲取 computed 的值時才會重新計算 computed 的值。

    watch 偵聽器 : 更多的是「觀察」的作用,無緩存性,類似于某些數(shù)據(jù)的監(jiān)聽回調(diào),每當監(jiān)聽的數(shù)據(jù)變化時都會執(zhí)行回調(diào)進行后續(xù)操作。

    運用場景

    運用場景:

    當我們需要進行數(shù)值計算,并且依賴于其它數(shù)據(jù)時,應(yīng)該使用 computed,因為可以利用 computed 的緩存特性,避免每次獲取值時,都要重新計算。

    當我們需要在數(shù)據(jù)變化時執(zhí)行異步或開銷較大的操作時,應(yīng)該使用 watch,使用 watch 選項允許我們執(zhí)行異步操作 ( 訪問一個 API ),限制我們執(zhí)行該操作的頻率,并在我們得到最終結(jié)果前,設(shè)置中間狀態(tài)。這些都是計算屬性無法做到的。

    4. 為什么在 Vue3.0 采用了 Proxy,拋棄了 Object.defineProperty?

    Object.defineProperty 本身有一定的監(jiān)控到數(shù)組下標變化的能力,但是在 Vue 中,從性能/體驗的性價比考慮,尤大大就棄用了這個特性(Vue 為什么不能檢測數(shù)組變動 )。為了解決這個問題,經(jīng)過 vue 內(nèi)部處理后可以使用以下幾種方法來監(jiān)聽數(shù)組

    push();
    pop();
    shift();
    unshift();
    splice();
    sort();
    reverse();

    由于只針對了以上 7 種方法進行了 hack 處理,所以其他數(shù)組的屬性也是檢測不到的,還是具有一定的局限性。

    Object.defineProperty 只能劫持對象的屬性,因此我們需要對每個對象的每個屬性進行遍歷。Vue 2.x 里,是通過 遞歸 + 遍歷 data 對象來實現(xiàn)對數(shù)據(jù)的監(jiān)控的,如果屬性值也是對象那么需要深度遍歷,顯然如果能劫持一個完整的對象是才是更好的選擇。

    Proxy 可以劫持整個對象,并返回一個新的對象。Proxy 不僅可以代理對象,還可以代理數(shù)組。還可以代理動態(tài)增加的屬性。

    5. Vue 中的 key 到底有什么用?

    key 是給每一個 vnode 的唯一 id,依靠 key,我們的 diff 操作可以更準確、更快速 (對于簡單列表頁渲染來說 diff 節(jié)點也更快,但會產(chǎn)生一些隱藏的副作用,比如可能不會產(chǎn)生過渡效果,或者在某些節(jié)點有綁定數(shù)據(jù)(表單)狀態(tài),會出現(xiàn)狀態(tài)錯位。)

    diff 算法的過程中,先會進行新舊節(jié)點的首尾交叉對比,當無法匹配的時候會用新節(jié)點的 key 與舊節(jié)點進行比對,從而找到相應(yīng)舊節(jié)點.

    更準確 : 因為帶 key 就不是就地復用了,在 sameNode 函數(shù) a.key === b.key 對比中可以避免就地復用的情況。所以會更加準確,如果不加 key,會導致之前節(jié)點的狀態(tài)被保留下來,會產(chǎn)生一系列的 bug。

    更快速 : key 的唯一性可以被 Map 數(shù)據(jù)結(jié)構(gòu)充分利用,相比于遍歷查找的時間復雜度 O(n),Map 的時間復雜度僅僅為 O(1),源碼如下:

    function?createKeyToOldIdx(children,?beginIdx,?endIdx)?{
    ??let?i,?key;
    ??const?map?=?{};
    ??for?(i?=?beginIdx;?i?<=?endIdx;?++i)?{
    ????key?=?children[i].key;
    ????if?(isDef(key))?map[key]?=?i;
    ??}
    ??return?map;
    }

    6. 談一談 nextTick 的原理

    JS 運行機制

    JS 執(zhí)行是單線程的,它是基于事件循環(huán)的。事件循環(huán)大致分為以下幾個步驟:

  • 所有同步任務(wù)都在主線程上執(zhí)行,形成一個執(zhí)行棧(execution context stack)。

  • 主線程之外,還存在一個"任務(wù)隊列"(task queue)。只要異步任務(wù)有了運行結(jié)果,就在"任務(wù)隊列"之中放置一個事件。

  • 一旦"執(zhí)行棧"中的所有同步任務(wù)執(zhí)行完畢,系統(tǒng)就會讀取"任務(wù)隊列",看看里面有哪些事件。那些對應(yīng)的異步任務(wù),于是結(jié)束等待狀態(tài),進入執(zhí)行棧,開始執(zhí)行。

  • 主線程不斷重復上面的第三步。

  • event-loop

    主線程的執(zhí)行過程就是一個 tick,而所有的異步結(jié)果都是通過 “任務(wù)隊列” 來調(diào)度。消息隊列中存放的是一個個的任務(wù)(task)。規(guī)范中規(guī)定 task 分為兩大類,分別是 macro task 和 micro task,并且每個 macro task 結(jié)束后,都要清空所有的 micro task。

    for?(macroTask?of?macroTaskQueue)?{
    ??//?1.?Handle?current?MACRO-TASK
    ??handleMacroTask();

    ??//?2.?Handle?all?MICRO-TASK
    ??for?(microTask?of?microTaskQueue)?{
    ????handleMicroTask(microTask);
    ??}
    }

    在瀏覽器環(huán)境中 :

    常見的 macro task 有 setTimeout、MessageChannel、postMessage、setImmediate

    常見的 micro task 有 MutationObsever 和 Promise.then

    異步更新隊列

    可能你還沒有注意到,Vue 在更新 DOM 時是異步執(zhí)行的。只要偵聽到數(shù)據(jù)變化,Vue 將開啟一個隊列,并緩沖在同一事件循環(huán)中發(fā)生的所有數(shù)據(jù)變更。

    如果同一個 watcher 被多次觸發(fā),只會被推入到隊列中一次。這種在緩沖時去除重復數(shù)據(jù)對于避免不必要的計算和 DOM 操作是非常重要的。

    然后,在下一個的事件循環(huán)“tick”中,Vue 刷新隊列并執(zhí)行實際 (已去重的) 工作。

    Vue 在內(nèi)部對異步隊列嘗試使用原生的 Promise.then、MutationObserver 和 setImmediate,如果執(zhí)行環(huán)境不支持,則會采用 setTimeout(fn, 0) 代替。

    在 vue2.5 的源碼中,macrotask 降級的方案依次是:setImmediate、MessageChannel、setTimeout

    vue 的 nextTick 方法的實現(xiàn)原理:

  • vue 用異步隊列的方式來控制 DOM 更新和 nextTick 回調(diào)先后執(zhí)行

  • microtask 因為其高優(yōu)先級特性,能確保隊列中的微任務(wù)在一次事件循環(huán)前被執(zhí)行完畢

  • microtask 因為其高優(yōu)先級特性,能確保隊列中的微任務(wù)在一次事件循環(huán)前被執(zhí)行完畢

  • 考慮兼容問題,vue 做了 microtask 向 macrotask 的降級方案

  • 7. vue 是如何對數(shù)組方法進行變異的 ?

    我們先來看看源碼

    const?arrayProto?=?Array.prototype;
    export?const?arrayMethods?=?Object.create(arrayProto);
    const?methodsToPatch?=?[
    ??"push",
    ??"pop",
    ??"shift",
    ??"unshift",
    ??"splice",
    ??"sort",
    ??"reverse"
    ];

    /**?*?Intercept?mutating?methods?and?emit?events?*/
    methodsToPatch.forEach(function(method)?{
    ??//?cache?original?method
    ??const?original?=?arrayProto[method];
    ??def(arrayMethods,?method,?function?mutator(...args)?{
    ????const?result?=?original.apply(this,?args);
    ????const?ob?=?this.__ob__;
    ????let?inserted;
    ????switch?(method)?{
    ??????case?"push":
    ??????case?"unshift":
    ????????inserted?=?args;
    ????????break;
    ??????case?"splice":
    ????????inserted?=?args.slice(2);
    ????????break;
    ????}
    ????if?(inserted)?ob.observeArray(inserted);
    ????//?notify?change
    ????ob.dep.notify();
    ????return?result;
    ??});
    });

    /**?*?Observe?a?list?of?Array?items.?*/
    Observer.prototype.observeArray?=?function?observeArray(items)?{
    ??for?(var?i?=?0,?l?=?items.length;?i?<?l;?i++)?{
    ????observe(items[i]);
    ??}
    };

    簡單來說,Vue 通過原型攔截的方式重寫了數(shù)組的 7 個方法,首先獲取到這個數(shù)組的ob,也就是它的 Observer 對象,如果有新的值,就調(diào)用 observeArray 對新的值進行監(jiān)聽,然后手動調(diào)用 notify,通知 render watcher,執(zhí)行 update

    8. Vue 組件 data 為什么必須是函數(shù) ?

    new Vue()實例中,data 可以直接是一個對象,為什么在 vue 組件中,data 必須是一個函數(shù)呢?

    因為組件是可以復用的,JS 里對象是引用關(guān)系,如果組件 data 是一個對象,那么子組件中的 data 屬性值會互相污染,產(chǎn)生副作用。

    所以一個組件的 data 選項必須是一個函數(shù),因此每個實例可以維護一份被返回對象的獨立的拷貝。new Vue 的實例是不會被復用的,因此不存在以上問題。

    9. 談?wù)?Vue 事件機制,手寫$on,$off,$emit,$once

    Vue 事件機制 本質(zhì)上就是 一個 發(fā)布-訂閱 模式的實現(xiàn)。

    class?Vue?{
    ??constructor()?{
    ????//??事件通道調(diào)度中心
    ????this._events?=?Object.create(null);
    ??}
    ??$on(event,?fn)?{
    ????if?(Array.isArray(event))?{
    ??????event.map(item?=>?{
    ????????this.$on(item,?fn);
    ??????});
    ????}?else?{
    ??????(this._events[event]?||?(this._events[event]?=?[])).push(fn);
    ????}
    ????return?this;
    ??}
    ??$once(event,?fn)?{
    ????function?on()?{
    ??????this.$off(event,?on);
    ??????fn.apply(this,?arguments);
    ????}
    ????on.fn?=?fn;
    ????this.$on(event,?on);
    ????return?this;
    ??}
    ??$off(event,?fn)?{
    ????if?(!arguments.length)?{
    ??????this._events?=?Object.create(null);
    ??????return?this;
    ????}
    ????if?(Array.isArray(event))?{
    ??????event.map(item?=>?{
    ????????this.$off(item,?fn);
    ??????});
    ??????return?this;
    ????}
    ????const?cbs?=?this._events[event];
    ????if?(!cbs)?{
    ??????return?this;
    ????}
    ????if?(!fn)?{
    ??????this._events[event]?=?null;
    ??????return?this;
    ????}
    ????let?cb;
    ????let?i?=?cbs.length;
    ????while?(i--)?{
    ??????cb?=?cbs[i];
    ??????if?(cb?===?fn?||?cb.fn?===?fn)?{
    ????????cbs.splice(i,?1);
    ????????break;
    ??????}
    ????}
    ????return?this;
    ??}
    ??$emit(event)?{
    ????let?cbs?=?this._events[event];
    ????if?(cbs)?{
    ??????const?args?=?[].slice.call(arguments,?1);
    ??????cbs.map(item?=>?{
    ????????args???item.apply(this,?args)?:?item.call(this);
    ??????});
    ????}
    ????return?this;
    ??}
    }

    10. 說說 Vue 的渲染過程

    render
  • 調(diào)用 compile 函數(shù),生成 render 函數(shù)字符串 ,編譯過程如下:

  • parse 函數(shù)解析 template,生成 ast(抽象語法樹)

  • optimize 函數(shù)優(yōu)化靜態(tài)節(jié)點 (標記不需要每次都更新的內(nèi)容,diff 算法會直接跳過靜態(tài)節(jié)點,從而減少比較的過程,優(yōu)化了 patch 的性能)

  • generate 函數(shù)生成 render 函數(shù)字符串

  • 調(diào)用 new Watcher 函數(shù),監(jiān)聽數(shù)據(jù)的變化,當數(shù)據(jù)發(fā)生變化時,Render 函數(shù)執(zhí)行生成 vnode 對象

  • 調(diào)用 patch 方法,對比新舊 vnode 對象,通過 DOM diff 算法,添加、修改、刪除真正的 DOM 元素

  • 11. 聊聊 keep-alive 的實現(xiàn)原理和緩存策略

    export?default?{
    ??name:?"keep-alive",
    ??abstract:?true,?//?抽象組件屬性?,它在組件實例建立父子關(guān)系的時候會被忽略,發(fā)生在?initLifecycle?的過程中
    ??props:?{
    ????include:?patternTypes,?//?被緩存組件
    ????exclude:?patternTypes,?//?不被緩存組件
    ????max:?[String,?Number]?//?指定緩存大小
    ??},

    ??created()?{
    ????this.cache?=?Object.create(null);?//?緩存
    ????this.keys?=?[];?//?緩存的VNode的鍵
    ??},

    ??destroyed()?{
    ????for?(const?key?in?this.cache)?{
    ??????//?刪除所有緩存
    ??????pruneCacheEntry(this.cache,?key,?this.keys);
    ????}
    ??},

    ??mounted()?{
    ????//?監(jiān)聽緩存/不緩存組件
    ????this.$watch("include",?val?=>?{
    ??????pruneCache(this,?name?=>?matches(val,?name));
    ????});
    ????this.$watch("exclude",?val?=>?{
    ??????pruneCache(this,?name?=>?!matches(val,?name));
    ????});
    ??},

    ??render()?{
    ????//?獲取第一個子元素的?vnode
    ????const?slot?=?this.$slots.default;
    ????const?vnode:?VNode?=?getFirstComponentChild(slot);
    ????const?componentOptions:??VNodeComponentOptions?=
    ??????vnode?&&?vnode.componentOptions;
    ????if?(componentOptions)?{
    ??????//?name不在inlcude中或者在exlude中?直接返回vnode
    ??????//?check?pattern
    ??????const?name:??string?=?getComponentName(componentOptions);
    ??????const?{?include,?exclude?}?=?this;
    ??????if?(
    ????????//?not?included
    ????????(include?&&?(!name?||?!matches(include,?name)))?||
    ????????//?excluded
    ????????(exclude?&&?name?&&?matches(exclude,?name))
    ??????)?{
    ????????return?vnode;
    ??????}

    ??????const?{?cache,?keys?}?=?this;
    ??????//?獲取鍵,優(yōu)先獲取組件的name字段,否則是組件的tag
    ??????const?key:??string?=
    ????????vnode.key?==?null
    ????????????//?same?constructor?may?get?registered?as?different?local?components
    ????????????//?so?cid?alone?is?not?enough?(#3269)
    ????????????componentOptions.Ctor.cid?+
    ????????????(componentOptions.tag???`::${componentOptions.tag}`?:?"")
    ??????????:?vnode.key;
    ??????//?命中緩存,直接從緩存拿vnode?的組件實例,并且重新調(diào)整了?key?的順序放在了最后一個
    ??????if?(cache[key])?{
    ????????vnode.componentInstance?=?cache[key].componentInstance;
    ????????//?make?current?key?freshest
    ????????remove(keys,?key);
    ????????keys.push(key);
    ??????}
    ??????//?不命中緩存,把?vnode?設(shè)置進緩存
    ??????else?{
    ????????cache[key]?=?vnode;
    ????????keys.push(key);
    ????????//?prune?oldest?entry
    ????????//?如果配置了?max?并且緩存的長度超過了?this.max,還要從緩存中刪除第一個
    ????????if?(this.max?&&?keys.length?>?parseInt(this.max))?{
    ??????????pruneCacheEntry(cache,?keys[0],?keys,?this._vnode);
    ????????}
    ??????}
    ??????//?keepAlive標記位
    ??????vnode.data.keepAlive?=?true;
    ????}
    ????return?vnode?||?(slot?&&?slot[0]);
    ??}
    };

    原理

  • 獲取 keep-alive 包裹著的第一個子組件對象及其組件名

  • 根據(jù)設(shè)定的 include/exclude(如果有)進行條件匹配,決定是否緩存。不匹配,直接返回組件實例

  • 根據(jù)組件 ID 和 tag 生成緩存 Key,并在緩存對象中查找是否已緩存過該組件實例。如果存在,直接取出緩存值并更新該 key 在 this.keys 中的位置(更新 key 的位置是實現(xiàn) LRU 置換策略的關(guān)鍵)

  • 在 this.cache 對象中存儲該組件實例并保存 key 值,之后檢查緩存的實例數(shù)量是否超過 max 的設(shè)置值,超過則根據(jù) LRU 置換策略刪除最近最久未使用的實例(即是下標為 0 的那個 key)

  • 最后組件實例的 keepAlive 屬性設(shè)置為 true,這個在渲染和執(zhí)行被包裹組件的鉤子函數(shù)會用到,這里不細說

  • LRU 緩存淘汰算法

    LRU(Least recently used)算法根據(jù)數(shù)據(jù)的歷史訪問記錄來進行淘汰數(shù)據(jù),其核心思想是“如果數(shù)據(jù)最近被訪問過,那么將來被訪問的幾率也更高”。

    LRU

    keep-alive 的實現(xiàn)正是用到了 LRU 策略,將最近訪問的組件 push 到 this.keys 最后面,this.keys[0]也就是最久沒被訪問的組件,當緩存實例超過 max 設(shè)置值,刪除 this.keys[0]

    12. vm.$set()實現(xiàn)原理是什么?

    受現(xiàn)代 JavaScript 的限制 (而且 Object.observe 也已經(jīng)被廢棄),Vue 無法檢測到對象屬性的添加或刪除。

    由于 Vue 會在初始化實例時對屬性執(zhí)行 getter/setter 轉(zhuǎn)化,所以屬性必須在 data 對象上存在才能讓 Vue 將它轉(zhuǎn)換為響應(yīng)式的。

    對于已經(jīng)創(chuàng)建的實例,Vue 不允許動態(tài)添加根級別的響應(yīng)式屬性。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套對象添加響應(yīng)式屬性。

    那么 Vue 內(nèi)部是如何解決對象新增屬性不能響應(yīng)的問題的呢?

    export?function?set(target:?Array<any>?|?Object,?key:?any,?val:?any):?any?{
    ??//?target?為數(shù)組
    ??if?(Array.isArray(target)?&&?isValidArrayIndex(key))?{
    ????//?修改數(shù)組的長度,?避免索引>數(shù)組長度導致splcie()執(zhí)行有誤
    ????target.length?=?Math.max(target.length,?key);
    ????//?利用數(shù)組的splice變異方法觸發(fā)響應(yīng)式
    ????target.splice(key,?1,?val);
    ????return?val;
    ??}
    ??//?target為對象,?key在target或者target.prototype上?且必須不能在?Object.prototype?上,直接賦值
    ??if?(key?in?target?&&?!(key?in?Object.prototype))?{
    ????target[key]?=?val;
    ????return?val;
    ??}
    ??//?以上都不成立,?即開始給target創(chuàng)建一個全新的屬性
    ??//?獲取Observer實例
    ??const?ob?=?(target:?any).__ob__;
    ??//?target?本身就不是響應(yīng)式數(shù)據(jù),?直接賦值
    ??if?(!ob)?{
    ????target[key]?=?val;
    ????return?val;
    ??}
    ??//?進行響應(yīng)式處理
    ??defineReactive(ob.value,?key,?val);
    ??ob.dep.notify();
    ??return?val;
    }

  • 如果目標是數(shù)組,使用 vue 實現(xiàn)的變異方法 splice 實現(xiàn)響應(yīng)式

  • 如果目標是對象,判斷屬性存在,即為響應(yīng)式,直接賦值

  • 如果 target 本身就不是響應(yīng)式,直接賦值

  • 如果屬性不是響應(yīng)式,則調(diào)用 defineReactive 方法進行響應(yīng)式處理

  • ?? 看完三件事

    如果你覺得這篇內(nèi)容對你挺有啟發(fā),我想邀請你幫我三個小忙:

    • 點個【在看】,或者分享轉(zhuǎn)發(fā),讓更多的人也能看到這篇內(nèi)容

    • 關(guān)注公眾號【全棧前端精選】,不定期分享原創(chuàng)&精品技術(shù)文章。

    • 公眾號內(nèi)回復:【 1 】。加入全棧前端精選公眾號交流群。

    歡迎評論區(qū)留下你的精彩評論~

    覺得文章不錯可以分享到朋友圈讓更多的小伙伴看到哦~

    客官!在看一下唄

    總結(jié)

    以上是生活随笔為你收集整理的vue openlayer单击地图事件循环多次执行_12道vue高频原理面试题,你能答出几道?的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。