前端雙向繫結的簡單實現

2021-10-08 02:35:22 字數 4344 閱讀 2540

本文學習了完整的**在最下面會展示

有關於圖形化的程式設計,我們往往會採用mvvm的模式來進行程式設計,將頁面抽象成資料可以讓程式設計變得更好把握,網頁前端也是如此,頻繁的dom操作勢必造成邏輯上的混亂,當專案特別龐大的時候,比如開發前端excel時,乙個單元格合併操作會造成大量dom元素的變更,刪除行和新增行也會造成dom的大量變更,造成邏輯上的混亂,維護和開發就會變得非常困難,因此,我們程式設計師只要修改和頁面ui繫結的資料 (物件,陣列,list一類的存在於記憶體中的資料結構),然後通過程式去對映在介面上,這樣的開發才能更好的維護。

首先先看個案例。

var student = ;

observe(student);

student.age = 24;

console.log('student.age is '+student.age);

我們定義了乙個物件,呼叫了乙個js函式,並且修改了age的值,但是在列印時並沒有改變,這證明js是通過get,set方法來修改值的,js提供了一層包裝,而提供編寫get,set函式的方法我這裡採用object.defineproperty(data, item , ;object.defineproperty(student,"proxyname",,

mdn解釋

object.defineproperty()方法會直接在乙個物件上定義乙個新屬性,或者修改乙個物件的現有屬性,並返回此物件。

這樣我們就知道在set的時候是可以呼叫我們自定義方法的,這就為 js 物件的值改變時去更改介面樣式提供了支援。

當然,使用者是不會用proxyname來操作name的,使用者的寫法肯定還是student.name = newvalue;但如果把object.defineproperty的第二個引數換成name,是會造成棧溢位的,**如下。

原因是無限遞迴了。

我們的目標自然也不是給某乙個特定的物件的特定的值加set,而是任意物件的全部object屬性新增set。(function屬性是不需要新增set的。)

**如下

function observe(data) ,

set: function(newval)

})})

}var student = ;

var cat = ;

observe(student);

observe(cat);

student.name = "newname";

cat.color = "black";

這樣使用者在用自己的物件時不會有任何的不一樣,但是在修改時可以加入我們的邏輯,我們可以在set時做髒值檢查來修改前端的ui介面。

接下來我們思考使用者至少需要提供給我們什麼資料,經過思考得知使用者至少給乙個dom元素和乙個值,這就夠了。如下所示

function mymvvm(options)

new mymvvm()

接下來編寫髒值檢查邏輯,髒值的儲存應該是乙個陣列,陣列中放著乙個物件的全部屬性的髒值,也就是乙個鍵值對的形式來表示髒值。髒值就是dom元素的value,新值就是js物件的值。watch就是用於髒值檢查的物件。

option就是使用者傳遞給我們的資料物件,也就是上面的new mymvv(),nodevalue就是繫結的值這裡是val,node就是和nodevalue繫結的dom元素了就是上面的

function watcher(option, nodevalue ,node)

watcher.prototype.dirtyvaluecheck = function(newval)

}

function sub()

sub.prototype = ,

trigger: function(newval) )

}};sub.target = null;

sub就是容器,迴圈遍歷檢查髒值,這個邏輯應該在observe中去呼叫,並且是在set中去使用。

function observe(data) 

return val;

},set: function(newval)

})})

}

總的來說就是當使用者傳遞的資料發生了修改會呼叫set,set呼叫sub的trigger然後遍歷裡面的watch,如果出現髒值就要利用dom去修改ui介面,這就完成了模型繫結view的能力。

那麼接下來就是如何新增watch了,watch就是提供node和value的乙個容器,node的**自然是html中的document,而value的**就是使用者提供的乙個物件了。那就需要去遍歷dom樹了,然後把和使用者提供的資料有繫結關係的node新增到sub中就可以了。對於插值表示式來說也是一樣的。

//compile

function compile(option)

compile.prototype.init = function ()

let childnodes = fragment.childnodes;

array.from(childnodes).foreach(node => })}

//實現插值表示式

interpolationrender(node,this);

})//經過轉化後的介面新增到節點下面就可以了

}function bingmodelview(node,attr,binddata)

})}function interpolationrender(node,binddata)\}/;

let text = node.textcontent;

if (reg.test(text))

}

這樣就完成了雙向繫結最為基礎的功能,還有很多功能沒有實現,也有非常多的細節沒有考慮到,以後會逐漸的完善。

下面附上完整的**

mvvm.html

winston_mvvm.js

function sub()

sub.prototype = ,

trigger: function(newval) )

}};sub.target = null;

function observe(data)

return val;

},set: function(newval)

})})

}//watcher

function watcher(option, nodevalue ,node)

watcher.prototype.dirtyvaluecheck = function(newval)

}//compile

function compile(option)

compile.prototype.init = function ()

let childnodes = fragment.childnodes;

array.from(childnodes).foreach(node => })}

//實現插值表示式

interpolationrender(node,this);

})//經過轉化後的介面新增到節點下面就可以了

vue資料雙向繫結的簡單實現

對資料雙向繫結一直都是半知半解,今天就打算自己寫個簡單的實現。可能有理解不到位甚至是錯誤的地方,如果有人發現的話可以指正 謝謝 資料的雙向繫結,即檢視和資料之間 html js var oinput document.getelementbyid input var ooutput document...

實現雙向繫結

ng和vue都有雙向資料繫結。vue是資料劫持,ng是藏之檢測 一 vue雙向資料繫結 訪問器屬性是物件中的一種特殊屬性,它不能直接在物件中設定,而必須通過 defineproperty 方法單獨定義。此例實現的效果是 隨文字框輸入文字的變化,span 中會同步顯示相同的文字內容 在js或控制台顯式...

前端主流框架雙向繫結實現原理簡述

angular的屬性繫結語法為 attr porperty,事件繫結語法為 event fn。雙向繫結的使用存在兩種場景 1 在表單中雙向繫結使用 ngmodel porperty,但同時得設定name屬性。其等價於繫結屬性 value property 繫結事件 input porperty.va...