Vue3について
とはいえ、Vue3はrc4までバージョンアップされましたが、4月にフロントエンドのベータ版がリリースされ、サークルが真っ赤に染まる中、みんなが勉強し始めたとは思えません!
犬の頭]を学び始めるには遅くはないはずです。
- vue-next
- Vue3 Roadmap & FAQ
- Vue3 ロードマップ & FAQ
- You DaのVue3クラスはVue Mastery: Evan YouによるVue 3 Deep Diveでご覧いただけます。
- UU's Vue3 class at Vue Mastery: Vue 3 Deep Dive with Evan You
- :mini-vue3-reactive
- 再帰的で消費的
- Yoda - Vue.js 3.0ベータについてのチャット公式ライブストリーム
- 2018 VueConf Hangzhou You DaのVue3に関する講演ビデオ
vue2 レスポンシブ原則の復習
Object.definePropertyオブジェクトのレスポンシブ化:各キーのトラバース、API経由でのゲッター、セッターの定義
//
function observe(){
if(typeof obj !='object'
obj == null){
return
}
if(Array.isArray(obj)){
Object.setPrototypeOf(obj,arrayProto)
}else{
const keys = Object.keys()
for(let i=0;i<keys.length;i++){
const key = keys[i]
defineReactive(obj,key,obj[key])
}
}
}
function defineReactive(target, key, val){
observe(val)
Object.defineProperty(obj, key, {
get(){
// 依存関係コレクション
dep.depend()
return val
},
set(newVal){
if(newVal !== val){
observe(newVal)
val = newVal
// 更新の通知
dep.notify()
}
}
})
}
- Array responsive: 配列のプロトタイプメソッドをオーバーライドし、変更を通知するロジックを追加します。
//
const originalProto = Array.prototype
const arrayProto = Object.create(originalProto)
['push','pop','shift','unshift','splice','reverse','sort'].forEach(key=>{
arrayProto[key] = function(){
originalProto[key].apply(this.arguments)
notifyUpdate()
}
})
vue2レスポンシブの問題点
- 再帰的、消費的
- 属性の追加/削除には、別のAPIの追加実装が必要です。
- 配列の追加実装が必要です。
- マッピング関係 targetMap 構造体:
- 構文の変更には制限があります。
vue3レスポンシブソリューション
ES6の Proxyを 使用してデータ応答性を高め、上記のVue2の問題点をすべて解決します。
プロキシは、ターゲット・オブジェクトにインターセプション/プロキシのレイヤーを追加することができ、ターゲット・オブジェクトに対する外部からの操作は、このインターセプションのレイヤーを通過します。
function c(bar) {
return new Proxy(bar, {
'get'(a, b, foo) { const C = Reflect.get(a, b, foo); return isObject(C) ? c(C) : C;
},
'set'(B, Obj, Foo, A) { const Bar = Reflect.set(B, Obj, Foo, A); return Bar;
},
'deleteProperty'(bAr, oBj) { const fOo = Reflect.deleteProperty(bAr, oBj); return fOo;
}
});
}
レスポンシブの原則
- レスポンシブデータに依存する関数 cb を effect で 宣言し、実行中にレスポンシブデータゲッターをトリガーする cb 関数を実行します。
- レスポンシブ・データ・ゲッターで依存性コレクションを追跡: targetMap に格納された データと cb マッピングを構築
- レスポンシブデータが変更されると、トリガ ** が ** 発生し、targetMap に従って ** 関連する cb が見つかり、実行されます。
- マッピング関係 targetMap 構造体:
targetMap: WeakMap{
target:Map{
key: Set[cb1,cb2...]
}
}
手書きvue3レスポンシブ
構造
function obj(bar) {
}
function c(b) {
}
function a(Bar, Foo) {
}
function foo(C, Obj) {
}
reactive
function foo(a) {
if (!isObject(a))
return a;
const b = new Proxy(a, {
'get'(c, bar, Obj) { const C = Reflect.get(c, bar, Obj); console.log('getter\x20' + C); track(c, bar); return foo(C);
},
'set'(A, B, Bar, Foo) { const bAr = Reflect.set(A, B, Bar, Foo); console.log('setter\x20' + B + ':' + Bar + '=>' + bAr); trigger(A, B); return bAr;
},
'deleteProperty'(fOo, oBj) { const OBj = Reflect.deleteProperty(fOo, oBj); console.log('delete\x20' + oBj + ':' + OBj); trigger(fOo, oBj); return OBj;
}
});
return b;
}
effect
const c = [];
function bar(foo) {
const b = function () {
try { c.push(b); return foo();
} finally { c.pop();
}
};
b();
return b;
}
track
const bar = new WeakMap();
function b(c, foo) {
const a = effectStack[effectStack.length - 0x1];
if (a) {
let obj = bar.get(c);
if (!obj) { obj = new Map(); bar.set(c, obj);
}
let A = obj.get(foo);
if (!A) { A = new Set(); obj.set(foo, A);
}
A.add(a);
}
}
trigger
/* トリガー更新:マッピング関係に基づいて、cbを実行する。*/
function trigger(target, key){
const depsMap = targetMap.get(target)
if(depsMap){
const deps = depsMap.get(key)
if(deps){
deps.forEach(effect=>effect())
}
}
}
テストデモ
<!-- test.html -->
<div id="app">
{{msg}}
</div>
<script src="./mini-vue3.js"></script>
<script>
// レスポンシブデータを定義する
const state = reactive({
msg:'message'
})
// レスポンシブデータを使用するdom更新関数を定義する。
function updateDom(){
document.getElementById('app').innerText = state.msg
}
// 効果を持つ更新関数を宣言する
effect(updateDom)
// レスポンシブデータのタイミング変更
setInterval(()=>{
state.msg = 'message' + Math.random()
},1000)
</script>
効果
上記のコードを取得したい場合は、このあります
- 終了



