您好,登錄后才能下訂單哦!
這篇文章主要講解了“vue3響應式原理和api編寫的方法是什么”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“vue3響應式原理和api編寫的方法是什么”吧!
vue3響應式原理加api編寫,快速明白vue3響應式原理
vue3響應式原理實現
先寫一段代碼看下
實現effect
var name = 'sl', age = 22; effect1 = () => `我叫${name},今年${age}歲` effect2 = () => `我叫${name},今年${age+1}歲` console.log(effect1()) //我叫sl,今年22歲 console.log(effect2()) //我叫sl,今年23歲 age = 30; console.log(effect1()) //我叫sl,今年30歲 console.log(effect2()) //我叫sl,今年31歲
看看有什么可以優化的點呢?
首先:多個函數,在age發生變化后需要手動再次調用多個函數才可以獲取最新信息
期望可以修改信息以后自動調用多個函數
如何實現呢
可以想到將多個函數存放到一起存放到gather函數,并且讓age發生變化時可以將多個函數調用trigger調用
實現gather及trigger
var name = "sl", age = 22; var tom, joy; effect1 = () => (tom = `我叫${name},今年${age}歲`); effect2 = () => (joy = `我叫${name},今年${age + 1}歲`); var dep = new Set(); function gather() { dep.add(effect1); dep.add(effect2); } function trigger() { dep.forEach((effect) => effect()); } gather(); effect1() effect2() console.log(tom); //我叫sl,今年22歲 console.log(joy); //我叫sl,今年23歲 age = 30; trigger() console.log(tom); //我叫sl,今年30歲 console.log(joy); //我叫sl,今年31歲
再繼續看下還是有什么可以優化的點
如果變量是一個對象或多個對象的話該怎么處理呢
變量為原始類型時Set存儲
變量為對象時可以用map存儲
多個對象時用weakMap存儲
var obj1 = { name: "tom", age: 22 }; var obj2 = { name: "joy", age: 23 }; var tom, joy; effect1 = () => (tom = `我叫${obj1.name},今年${obj1.age}歲`); effect2 = () => (joy = `我叫${obj2.name},今年${obj2.age}歲`); var depsMap = new WeakMap(); function gather(target, key) { let depMap = depsMap.get(target); if (!depMap) { depsMap.set(target, (depMap = new Map())); } let dep = depMap.get(key); if (!dep) { depMap.set(key, (dep = new Set())); } if (target === obj1) { dep.add(effect1); } else { dep.add(effect2); } } function trigger(target, key) { let depMap = depsMap.get(target); if (depMap) { const dep = depMap.get(key); if (dep) { dep.forEach((effect) => effect()); } } } gather(obj1, "age");//收集依賴 gather(obj2, "age");//收集依賴 effect1(); effect2(); console.log(tom); //我叫sl,今年22歲 console.log(joy); //我叫sl,今年23歲 obj1.age = 30; obj2.age = 10; trigger(obj1, "age"); trigger(obj2, "age"); console.log(tom); //我叫sl,今年30歲 console.log(joy); //我叫sl,今年31歲
在繼續看看有哪些可以優化的點
上邊依賴的收集gather以及函數的更新通知trigger每次都是手動收集手動觸發更新,那有什么方法可以自動收集及觸發嗎
Proxy
實現reactive
先寫一個reactive函數
function reactive(target) { const handle = { set(target, key, value, receiver) { Reflect.set(target, key, value, receiver); trigger(receiver,key) // 設置值時觸發自動更新 }, get(target, key, receiver) { gather(receiver, key); // 訪問時收集依賴 return Reflect.get(target, key, receiver); }, }; return new Proxy(target, handle); }
然后將reactive函數應用到之前代碼
var obj1 = reactive({ name: "tom", age: 22 }); var obj2 = reactive({ name: "joy", age: 23 }); var tom, joy; effect1 = () => (tom = `我叫${obj1.name},今年${obj1.age}歲`); effect2 = () => (joy = `我叫${obj2.name},今年${obj2.age}歲`); var depsMap = new WeakMap(); function gather(target, key) { let depMap = depsMap.get(target); if (!depMap) { depsMap.set(target, (depMap = new Map())); } let dep = depMap.get(key); if (!dep) { depMap.set(key, (dep = new Set())); } if (target === obj1) { dep.add(effect1); } else { dep.add(effect2); } } function trigger(target, key) { let depMap = depsMap.get(target); if (depMap) { const dep = depMap.get(key); if (dep) { dep.forEach((effect) => effect()); } } } effect1(); effect2(); console.log(tom); //我叫sl,今年22歲 console.log(joy); //我叫sl,今年23歲 obj1.age = 30; obj2.age = 10; console.log(tom); //我叫sl,今年30歲 console.log(joy); //我叫sl,今年31歲
然后還有個問題,就是gather函數中有寫死dep添加函數
如何解決呢 重寫effect函數
let activeEffect = null function effect(fn) { activeEffect = fn; activeEffect(); activeEffect = null; // 執行后立馬變成null } var depsMap = new WeakMap(); function gather(target, key) { // 避免例如console.log(obj1.name)而觸發gather if (!activeEffect) return; let depMap = depsMap.get(target); if (!depMap) { depsMap.set(target, (depMap = new Map())); } let dep = depMap.get(key); if (!dep) { depMap.set(key, (dep = new Set())); } dep.add(activeEffect) //將函數添加到依賴 } effect(effect1); effect(effect2);
reactive也已經實現了,那么還有ref也實現下
ref
在vue3中ref怎么使用呢
var name = ref('tom') console.log(name.value) // tom
需要使用.value的方式獲取值
function ref(name){ return reactive( { value: name } ) } const name = ref('tom'); console.log(name.value) //tom
完整代碼
var activeEffect = null; function effect(fn) { activeEffect = fn; activeEffect(); activeEffect = null; } var depsMap = new WeakMap(); function gather(target, key) { // 避免例如console.log(obj1.name)而觸發gather if (!activeEffect) return; let depMap = depsMap.get(target); if (!depMap) { depsMap.set(target, (depMap = new Map())); } let dep = depMap.get(key); if (!dep) { depMap.set(key, (dep = new Set())); } dep.add(activeEffect) } function trigger(target, key) { let depMap = depsMap.get(target); if (depMap) { const dep = depMap.get(key); if (dep) { dep.forEach((effect) => effect()); } } } function reactive(target) { const handle = { set(target, key, value, receiver) { Reflect.set(target, key, value, receiver); trigger(receiver, key); // 設置值時觸發自動更新 }, get(target, key, receiver) { gather(receiver, key); // 訪問時收集依賴 return Reflect.get(target, key, receiver); }, }; return new Proxy(target, handle); } function ref(name){ return reactive( { value: name } ) }
感謝各位的閱讀,以上就是“vue3響應式原理和api編寫的方法是什么”的內容了,經過本文的學習后,相信大家對vue3響應式原理和api編寫的方法是什么這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。