フロントエンドMVVMの原理
6154 ワード
author:
email: [email protected]
date: 2018/3/1
MVVM背景
怠惰は人を進歩させると言われていますが、MVVMの進化史は、開発者を怠惰にするより簡単な歴史であることを証明しています.
ダイレクトDOMアクション->MVC->MVP->MVVM
最初のフロントエンドインタラクションは、直接的なDOM操作であり、最も有名なこれらのライブラリはjQueryであり、DOM APIをカプセル化し、すべてのDOM操作を簡単にする.
しかし、ページデータとインタラクションが多いと、散乱したコードがプロジェクトを維持しにくくなり、狂ってしまいます.だからMV*モードの発展がありました.
MV*モード
MVC&MVP&MVVMの3つの比較擬似コード:点我
MVC
MVVM
次に、不思議なDirectiveを重点的に紹介します.
データ変更検出方式(Directive)
(一)手動でバインドをトリガする
ページを変更する必要がある場合は、検出を手動でトリガーし、modelデータを変更し、要素をスキャンし、特殊なタグのある要素を変更します.
let data = {
value: 'hello'
};
let directive = {
html: function (html) {
this.innerHTML = html;
},
value: function (html) {
this.setAttribute('value', value);
}
};
ViewModelSet('value', 'hello world');
function ViewModelSet(key, value) {
data[key] = value;
scan();
}
function scan() {
for (let elem of elems) {
elem.directive = [];
for (let attr of elem.attributes) {
if (attr.nodeName.indexOf('v-') >= 0) {
directive[attr.nodeName.slice(2)].call(elem, data[attr.nodeValue]);
}
}
}
}
(二)汚れ検出メカニズム
手動バインドの最適化では、変更されたデータのみが要素を更新します.
function scan(elems, val) {
let list = document.querySelectorAll(`[v-bind=${val}]`); //
for (let elem of elems) {
for (let attr of elem.attributes) {
let dataKey = elem.getAttribute('v-bind');
if (elem.directive[attr.nodeValue] !== data[dataKey]) { // ,
directive[attr.nodeValue].call(elem, data[dataKey]);
elem.directive[attr.nodeValue] = data[dataKey]; //
}
}
}
}
(三)フロントエンドデータオブジェクトハイジャック(Hijacking)
以上の基礎をさらに進めるにはObjectを用いる.definePropertyはデータをget&setリスニングし、データが変化した場合、scanスキャンを自動的に実行し、要素を更新します.
データを変更するときに手動scanが必要だったのか.データを直接変更するだけで、自動的にscanし、要素を更新します.
defineGetAndSet(data, 'value');
data.value = 'hello world';
function defineGetAndSet(obj, propName) {
Object.efineProperty(obj, propName, {
get: function () {
return this.bVal;
},
set: function (newVal) {
this.bVal = newVal;
scan();
},
enumerable: true,
configurable: true
});
}
(四)ECMAScript 6 Proxy
方法3と同様に書き方を変え,ここではES 6のProxyを適用した.
let data = new Proxy({
get: function (obj, key) {
return obj[key];
},
set: function (obj, key, val) {
obj[key] = val;
scan();
return obj[key];
}
});
以上です.
参考資料