從 0.5 開始造輪子 仿 vue 的 mvvm(二)

替換數(shù)據(jù)劫持對象

??上一篇實現(xiàn)了 mvvm 實現(xiàn)思路获洲,可是不夠優(yōu)雅還有很多問題,我先解決這個問題數(shù)據(jù)劫持的問題豪嚎。

之前的數(shù)據(jù)劫持

之前數(shù)據(jù)的劫持試是這么做的

// 重寫data 的 get set  更改數(shù)據(jù)的時候,觸發(fā)watch 更新視圖
myVue.prototype._observer = function (obj) {
    var _this = this;
    for (key in obj){  // 遍歷數(shù)據(jù)
        //訂閱池
        // _this._watcherTpl.a = [];
        // _this._watcherTpl.b = [];
        _this._watcherTpl[key] = {
            _directives: []
        };
        let value = obj[key]; // 獲取屬`性值
        let watcherTpl = _this._watcherTpl[key]; // 數(shù)據(jù)的訂閱池
        Object.defineProperty(_this._data, key, { // 數(shù)據(jù)劫持
            configurable: true,  // 可以刪除
            enumerable: true, // 可以遍歷
            get() {
                console.log(`${key}獲取值:${value}`);
                return value; // 獲取值的時候 直接返回
            },
            set(newVal) { // 改變值的時候 觸發(fā)set
                console.log(`${key}更新:${newVal}`);
                if (value !== newVal) {
                    value = newVal;
                    //_this._watcherTpl.xxx.forEach(item)
                    //[{update:function(){}}]
                    watcherTpl._directives.forEach((item) => { // 遍歷訂閱池
                        item.update();
                        // 遍歷所有訂閱的地方(v-model+v-bind+{{}}) 觸發(fā)this._compile()中發(fā)布的訂閱Watcher 更新視圖
                    });
                }
            }
        })
    };
};

這么做是可以實現(xiàn)可是,可以看到有這么一些缺點(diǎn):

  • 對象必須是存在的蚊锹。
  • 循環(huán)耗費(fèi)性能。
  • 代碼可讀性可拓展性不是很好
  • 等等..
    那么我們能不能換一種方式去解決數(shù)據(jù)的劫持問題稚瘾?

Proxy 橫空出世

Proxy 是 ECMAScript 2015 的新特性牡昆,唯一的 缺點(diǎn)是 兼容性不是非常好。但我們要團(tuán)結(jié)啊摊欠,哈哈哈丢烘。 廢棄 IE。些椒。播瞳。
下面我們將使用 Proxy 實現(xiàn)數(shù)據(jù)的劫持 和 代理。關(guān)于 Proxy 可以看這么兩篇文章免糕,一個是 阮一峰老師 的,不管阮一峰怎么樣赢乓,當(dāng)初竟然幫助過我們,我覺得就可以稱之為老師 ,還有一篇 抱歉石窑,學(xué)會 Proxy 真的可以為所欲為

// 重寫data 的 get set  更改數(shù)據(jù)的時候牌芋,觸發(fā)watch 更新視圖
myVue.prototype._observer = function (obj) {
    const _this = this;
    this._data = new Proxy(obj, { // 數(shù)據(jù)劫持
        get(target, key, receiver) {
            return Reflect.get(target, key, receiver); // 獲取值的時候 直接返回
        },
        set(target, key, newVal) { // 改變值的時候 觸發(fā)set
            if (_this.value !== newVal) {
                _this.value = newVal;
                //先將數(shù)據(jù)更新完成后
                let res =  Reflect.set(target,key,newVal);
                _this._watcherTpl[key]._directives.forEach((item) => { // 遍歷訂閱池
                    item.update();
                });
                return res
            }
        }
    });
};

看到代碼不用說了,量級的差距尼斧,簡潔多了姜贡,這里直接將 VUE 的data 變成了一個 Proxy 對象。進(jìn)行數(shù)據(jù)的操作棺棵。
既然這里更改了楼咳,那么我們之前的訂閱池其實是廢除了熄捍,因為沒有循環(huán)了不存在 key:

   _this._watcherTpl[key] = {
            _directives: []
        };

所以我這里單獨(dú)在_compile 處理了訂閱池。

 const attrVal = node.getAttribute('v-model'); // 獲取綁定的data
                _this.hasDirectives(attrVal);
//工具類判斷是否有訂閱池
myVue.prototype.hasDirectives = function (attr) {
    const _this = this;
    // 沒有事件池 創(chuàng)建事件池
    if (!_this._watcherTpl[attr]) {
        _this._watcherTpl[attr] =  {};
        _this._watcherTpl[attr]._directives = [];
    } else {
        if (!_this._watcherTpl[attr]._directives) {
            _this._watcherTpl[attr]._directives = []
        }
    }
};

這樣就解決了連接池的問題 母怜,這里的連接池使用的是數(shù)組余耽,后面我們將會替換為map

結(jié)語

github完整實現(xiàn)

在線地址,需要翻墻

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市苹熏,隨后出現(xiàn)的幾起案子碟贾,更是在濱河造成了極大的恐慌,老刑警劉巖轨域,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件袱耽,死亡現(xiàn)場離奇詭異,居然都是意外死亡干发,警方通過查閱死者的電腦和手機(jī)朱巨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來枉长,“玉大人冀续,你說我怎么就攤上這事”胤澹” “怎么了洪唐?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長吼蚁。 經(jīng)常有香客問我凭需,道長,這世上最難降的妖魔是什么肝匆? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任功炮,我火速辦了婚禮,結(jié)果婚禮上术唬,老公的妹妹穿的比我還像新娘。我一直安慰自己滚澜,他們只是感情好粗仓,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著设捐,像睡著了一般借浊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上萝招,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天蚂斤,我揣著相機(jī)與錄音,去河邊找鬼槐沼。 笑死曙蒸,一個胖子當(dāng)著我的面吹牛捌治,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播纽窟,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼肖油,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了臂港?” 一聲冷哼從身側(cè)響起森枪,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎审孽,沒想到半個月后县袱,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡佑力,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年式散,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片搓萧。...
    茶點(diǎn)故事閱讀 40,117評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡杂数,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出瘸洛,到底是詐尸還是另有隱情揍移,我是刑警寧澤,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布反肋,位于F島的核電站那伐,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏石蔗。R本人自食惡果不足惜罕邀,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望养距。 院中可真熱鬧诉探,春花似錦、人聲如沸棍厌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽耘纱。三九已至敬肚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間束析,已是汗流浹背艳馒。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留员寇,地道東北人弄慰。 一個月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓第美,卻偏偏與公主長得像,于是被迫代替她去往敵國和親曹动。 傳聞我的和親對象是個殘疾皇子斋日,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容