前端Vue架構

1

理解:

  • 創建視圖的函數(render)和數據之間的關聯;

  • 當數據發生變化的時候,希望render重新執行;

  • 監聽數據的讀取和修改;

    • defineProperty:監聽范圍比較窄,只能通過屬性描述符去監聽已有屬性的讀取和賦值;兼容性更好;(要求監聽數據是對象)
    • proxy:監聽范圍更廣;兼容性較差,只能兼容支持ES6 的瀏覽器(要求監聽數據是對象)

如何知曉數據對應的函數;

function track(target, key) {console.log(`依賴收集:${key}`, 'color: #f00');
}function trigger(target, key) {console.log(`派發更新:${key}`, 'color: #f00');
}function isObject(value) {return typeof value === 'object' && value !== null;
}
const handlers = {get(target, key) {// 依賴收集track(target, key);return target[key]; // 返回對象的相應屬性值},set(target, key, value) {// 派發更新trigger(target, key);// target[key] = value; // 設置對象的相應屬性值// return true;// 賦值成功返回true,賦值失敗返回false;這里可以使用try catchreturn Reflect.set(target, key, value)// 也可以使用Reflect.set(target, key, value)。它會直接返回true或者false},
}
// 同一個對象,調用兩次reactive,會生成不一樣的Proxy對象,沒有意義
const targetMap = new WeakMap();
function reactive(target) {if (!isObject(target)) {return target; // 如果不是對象,直接返回}if (targetMap.has(target)) {return targetMap.get(target);// 如果已經代理過了,直接返回;}const proxy = new Proxy(target, handlers);targetMap.set(target, proxy);return proxy;
}
const state = reactive({a: 1,b: 2,
});// fn函數中用到了state數據
function fn() {state.a;state.b;
}fn();
state.a++; // 先讀取,再賦值

依賴收集:a color: #f00
依賴收集:b color: #f00
依賴收集:a color: #f00
派發更新:a color: #f00

const obj = {a: 1,b: 2,get c() {return this.a + this.b;}
};const state = reactive(obj);
state.c;

這樣寫的話,依賴收集只能收集到屬性c;因為this指向obj;
可以這樣操作:

get(target, key, receiver) {// 依賴收集track(target, key);// receiver指的是代理對象return Reflect.get(target, key, receiver) ; // 改變this指向,將this指向為代理對象// return target[key]; // 返回對象的相應屬性值
},

下面的用法,只能收集到c,收集不到c1

const obj = {a: 1,b: 2,c: {c1: 1,},
};const state = reactive(obj);
state.c.c1;

可以這樣操作
如果訪問的屬性值還是一個對象,對屬性值再次進行代理;

const obj = {
includes: () => {},
indexOf: () => {},
};
const handlers = {get(target, key, receiver) {// 依賴收集track(target, key);// 對于數組來說,無法在代理對象中找到時,去原始數組中重新找一次// const obj = {};// const arr = [1, obj, 3];// const state = reactive(arr);// state.includes(obj);if ((obj.hasOwnProperty(key) && Array.isArray(target)) {return obj[key];}// receiver指的是代理對象const result = Reflect.get(target, key, receiver) ; if (isObject(result)) {return reactive(result);}},
}

簡易的模型已經寫好;

2 讀信息 進行依賴升級

Object.keys和let i in obj用的都是ownKeys;
‘a’ in obj; 用的是has;
obj.a 用的是get;

這里的讀不光是通過state.a來讀取a屬性
還可能通過’e’ in state;來查看’e’屬性在不在state中;

const obj = {};
const state = reactive(obj);
'e' in state;

解決辦法:新增has方法

const TrackOpTypes = {GET: 'get', // 讀取屬性值HAS: 'has', // 判斷屬性是否存在ITERATE: 'iterate', // 迭代對象
};function track(target, trackOpType, key) {console.log(`依賴收集:${key},收集方法:${trackOpType}`, 'color: #f00');
}
const handlers = {get(target, key, receiver) {// 依賴收集track(target, TrackOpTypes.GET, key);// ...},set(target, key, value, receiver) {},has(target, key) {track(target, TrackOpTypes.HAS, key);return Reflect.has(target, key); // 判斷對象是否有key屬性}
}

在這里插入圖片描述

同理

const TriggerOpTypes = {SET: 'set', // 設置屬性值ADD: 'add', // 添加屬性值DELETE: 'delete', // 刪除屬性
}function trigger(target, triggerOpType, key) {console.log(`派發更新:${key}, 更改方法:${triggerOpType}`, 'color: #f00');
}

還有一種情況

const handlers = {get,set,has,ownKeys(target) {track(target, TrackOpTypes.ITERATE);return Reflect.ownKeys(target); // 返回對象的所有屬性名},
}
function track(target, trackOpType, key) {if (trackOpType === TrackOpTypes.ITERATE) {console.log(`依賴收集方法:${trackOpType}`, 'color: #f00');return;}console.log(`依賴收集:${key},收集方法:${trackOpType}`, 'color: #f00');
}
const obj = { a: '1'};
const obj2 = {}
const state = reactive(obj);
const state2 = reactive(obj2);
for (let i in state) {}
Object.keys(state2);

Object.keys和let i in obj用的都是ownKeys;

依賴收集方法:iterate color: #f00
依賴收集方法:iterate color: #f00

3 新增屬性

 set(target, key, value, receiver) {// 派發更新const type = target.hasOwnProperty(key)? TriggerOpTypes.SET: TriggerOpTypes.ADD;trigger(target, type, key);return Reflect.set(target, key, value, receiver);},

在這里插入圖片描述

4 刪除屬性

 deleteProperty(target, key) {trigger(target, TriggerOpTypes.DELETE, key);return Reflect.deleteProperty(target, key); // 刪除對象的相應屬性}
delete state.a;

5 數據和函數的內在聯系

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/10995.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/10995.shtml
英文地址,請注明出處:http://en.pswp.cn/web/10995.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Docker 直接運行一個 Alpine 鏡像

由于鏡像很小,下載時間往往很短,讀者可以直接使用 docker run 指令直接運行一個 Alpine 容器,并指定運行的 Linux 指令,例如: PS C:\Users\yhu> docker run alpine echo 123 Unable to find image alpine:latest lo…

Commit failed (details follow):is out of date

Commit failed (details follow):is out of date 關于SVN提交時報out-of-date錯誤的解決方法 提交項目文件時,報如下的信息: Item is out-of-date svn: Commit failed (details follow): svn: Item ‘/xxx/xxx/xxx/xxx/xxx/xxx’ is out of date 原因&…

手寫Spring5【筆記】

Spring5【筆記】 前言前言推薦Spring5【筆記】1介紹2手寫 最后 前言 這是陳舊已久的草稿2022-12-01 23:32:59 這個是刷B站的時候,看到一個手寫Spring的課程。 最后我自己好像運行不了,就沒寫。 現在2024-5-12 22:22:46,發布到[筆記]專欄中…

隊列(詳解)

一.隊列的概念 隊列(Queue)是一種常見的數據結構,它按照先進先出的原則管理數據。這意味著最先進入隊列的元素將被最先移出隊列,類似于現實生活中排隊的場景。 在隊列中,數據項被添加到隊列的一端,稱為隊尾…

cmu15445 2023fall project3 詳細過程(下)QUERY EXECUTION

QUERY EXECUTION task3/task4 Task #3 - HashJoin Executor and Optimization1、HashJoin1.1 思路1.2 代碼 2 NestedLoopJoin優化為HashJoin2.1 思路2.2 代碼 Task #4 Sort Limit Executors Top-N Optimization Window Functions1、Sort1.1 思路1.2 代碼 2、Limit Executors2…

數據可視化第五天(讀取文件獲得男生女生身高信息,并且可視化在一個圖像)

文件 需要學生文件的可以私信我 過程 利用numpy的loadtxt文件讀取學號,性別,和身高。 import numpy as np import matplotlib.pyplot as pltfilename/Users/oommnn/Desktop/python學習/數據分析/網課資料/第04天/student-data.txtuser_infonp.dtype(…

文獻閱讀——LPPLS(2)

A study on the bursting point of Bitcoin based on the BSADF and LPPLS methods 文獻來源[2] Yao, Can-Zhong, and Hong-Yu Li. “A study on the bursting point of Bitcoin based on the BSADF and LPPLS methods.” The North American Journal of Economics and Financ…

貓頭虎分享已解決Bug || **Vue.js腳手架安裝失敗** Error: unable to fetch template`

貓頭虎分享已解決Bug 🐯 || Vue.js腳手架安裝失敗 🚫Error: unable to fetch template 博主貓頭虎的技術世界 🌟 歡迎來到貓頭虎的博客 — 探索技術的無限可能! 專欄鏈接: 🔗 精選專欄: 《面試題…

CodeTop 高頻筆試題總結(持續更新)

🏆 頻率從高到低排序 👨?🏫 參考的頻率數據:CodeTop 👨?🏫 力扣hot100 無重復字符的最長子串 雙指針 滑動窗口 哈希👨?🏫 力扣hot100 反轉鏈表 指針 遞歸 一題多解👨?…

7. path路徑繪制:使用path繪制曲線

曲線在SVG中通常是通過貝塞爾曲線命令來繪制的,包括二次貝塞爾曲線(Q)和三次貝塞爾曲線(C)。這些命令允許我們創建平滑的曲線路徑。 貝塞爾曲線的原理 貝塞爾曲線的基本原理是通過控制點和錨點來定義一條曲線的形狀。…

命名規范總結Java

小駝峰命名 主要用于變量和方法的命名,當標識符是一個單詞時首字母小寫,當標識符為多個單詞時第一個單詞首字母小寫,其他單詞首字母大寫 大駝峰命名 主要用于類(Class)名等。標識符各個單詞首字母大寫。 全部大寫命名 常量名 全部小寫命…

持續總結中!2024年面試必問 100 道 Java基礎面試題(四十一)

上一篇地址:持續總結中!2024年面試必問 100 道 Java基礎面試題(四十)-CSDN博客 八十一、Java內存模型是什么? Java內存模型(Java Memory Model, JMM)是Java虛擬機(JVM)…

海豚知道知識付費平臺,大V都在用,新手也能做,網絡營銷是什么?如何向銷售轉化?

我國的市場營銷已經全面步入互聯網時代,教育行業也逐漸網絡化,通過互聯網發家壯大的機構比比皆是,然而仍舊有很多中小型教育培訓機構,沒有從事網絡營銷推廣,或者從事了效果非常不理想。網絡營銷是什么,如何…

流暢的python-學習筆記_對象引用、可變性、垃圾回收

變量不是盒子 即變量是引用,而不是實際內存,多個標識賦值相同變量時,多余標識是引用 標識、相等性、別名 比較對象的值,is比較對象的id。實際調用對象的__eq__方法。is速度比快,因為is不能重載,省去了尋…

UNIT6,NFS網絡文件系統的應用

實驗要求: 1.配置2臺服務器要求如下: a)服務器1: 主機名:user-server.timinglee.org ip地址: 172.25.254.100 配置好軟件倉庫 b)服務器2: 主機名:storage-server.timing…

力扣 300. 最長遞增子序列 python AC

動態規劃 dp[i]表示到當前位置為止最多個數的遞增子序列 簡單的對每個位置從頭遍歷 class Solution:def lengthOfLIS(self, nums):size len(nums)dp [1] * sizefor i in range(1, size):for j in range(i):if nums[i] > nums[j]:dp[i] max(dp[i], dp[j] 1)return max…

數據結構與算法學習筆記之線性表二---順序表的靜態存儲表示和實現(C++)

目錄 前言 1.什么是順序表 2.順序表的靜態存儲表示 1.初始化 2.長度 3.數據元素 4.長度 5.獲取元素下標 6.前驅節點 7.后繼節點 8.插入 9.刪除 10.遍歷 11.測試代碼 前言 這篇文章講的是順序表的兩種實現方式。 1.什么是順序表 線性表的順序表示指的是用一組地址…

Double 4 VR情景智能互動教學系統在商務旅行課堂中的應用

一、提高學生的學習興趣 傳統的商務旅行課堂教學方式往往是教師講授理論知識,學生被動接受。這種方式很難激發學生的學習興趣,而Double 4 VR情景智能互動教學系統則可以通過虛擬現實技術,將商務旅行的場景生動地展示給學生,讓學生…

醫院如何做好漏費管理?什么是控費系統?控費系統現在成熟嗎?

在中國深厚的人情土壤之中,某些醫院里的醫技科室,宛如隱秘的灰色地帶,悄然滋生著利用職務之便謀取私利的暗流。這些科室的醫務人員,以低于醫院明文規定的收費標準,私下里為熟識的患者提供檢查服務,仿佛形成…

【碎碎念4】向上社交

好久沒寫碎碎念系列了,最近關注到身邊一些社交關系,想要和大家聊聊向上社交這件事情。首先小田認為向上社交或者僅僅是社交本身是無論什么年紀都需要關注的,因為處理好關系不僅僅會幫助我們把握好機會,同時也能讓我們更好的建立自…