권장 독서 :
매우 간단한 JS 양방향 데이터 바인딩을 구현하십시오
MVVM은 웹 프론트 엔드에 매우 인기있는 개발 모델입니다. MVVM을 사용하면 코드가 DOM 운영을 돌보는 대신 비즈니스 로직을 다루는 데 더 집중할 수 있습니다. 현재 유명한 MVVM 프레임 워크에는 VUE, Avalon, React 등이 포함됩니다. 이러한 프레임 워크에는 고유 한 장점이 있지만 구현 아이디어는 거의 동일합니다. Data Binding + View View Refresh. 호기심과 투쟁에 대한 의지에서, 나는 또한이 방향을 따라 가장 간단한 MVVM 라이브러리 (MVVM.JS)를 총 2,000 줄 이상의 코드를 썼습니다. 지침의 이름과 사용은 VUE와 유사합니다. 여기서는 구현 원칙과 코드 조직 아이디어를 공유 할 것입니다.
아이디어 분류
MVVM은 개념적으로 뷰를 데이터 로직에서 진정으로 분리하는 패턴이며, ViewModel은 전체 패턴의 초점입니다. ViewModel을 구현하려면 데이터 모델 (모델)과보기 (보기)를 연관시켜야합니다. 전체 구현 아이디어는 간단히 5 점으로 요약 될 수 있습니다.
요소의 각 노드에 대한 지침을 스캔하고 추출 할 컴파일러를 구현합니다.
요소에 대한 지침을 구문 분석 할 파서를 구현하는데, 이는 새로 고침 함수를 통해 명령의 의도를 DOM으로 업데이트 할 수 있습니다 (중간에 새로 고침이 필요할 수있는 모듈이 필요할 수 있음). 예를 들어, 노드 <p v-show = "isshow"> </p>를 구문 분석 할 때 먼저 모델에서 iSshow의 값을 얻은 다음 iSshow에 따라 Node.style.display를 변경하여 디스플레이를 제어하고 요소의 숨기기를 변경합니다.
감시자 구현은 파서의 각 명령어의 새로 고침 기능을 모델에 해당하는 필드와 연결할 수 있습니다.
객체의 모든 필드의 값 변경을 모니터링하기 위해 관찰자를 구현하고, 일단 변경이 발생하면 최신 값을 얻을 수 있고 알림 콜백을 트리거 할 수 있습니다.
관찰자를 사용하여 감시자에서 모델 모니터링을 설정하십시오. 모델의 값이 변경되면 모니터링이 트리거됩니다. 감시자가 새로운 값을 얻은 후, 2 단계와 관련된 새로 고침 함수를 호출하여 데이터가 변경되는 동안보기를 새로 고칠 수 있습니다.
효과 예
먼저, 다른 MVVM 프레임 워크의 인스턴스화와 유사한 최종 사용 예제를 살펴 보겠습니다.
<div id = "mobile-list"> <h1 v-text = "title"> </h1> <ul> <li v-for = "브랜드의 항목"> <b v- 텍스트 = "item.name"> </b> <span v-show = "showrank"> rank : {{item.rank}} </li> </var election = </val> document.querySelector ( '#mobile-list'); var vm = new mvvm (요소, { 'title': 'mobile list', 'showrank': true, 'brands': [{ 'name': 'apple', 'rank': 1}, { 'name': 'galaxy', 'rank': 2}, ''rank ':'rank ': 3}]}); vm.set ( 'Title', 'Top 3 Mobile Rank List'); // => <H1> TOP 3 Mobile Rank List </h1>모듈 부서
MVVM을 5 가지 모듈로 나누어 컴파일 모듈 컴파일러, 파서, 새로 고침 모듈 업데이터보기, 데이터 구독 모듈 감시자 및 데이터 청취 모듈 관찰자보기. 프로세스는 다음과 같이 간단히 설명 할 수 있습니다. 컴파일러가 명령을 컴파일 한 후 명령 정보는 구문 분석을 위해 구문 분석기에 양도됩니다. 파서는 초기 값을 업데이트하고 데이터 변경 사항을 감시자에게 가입합니다. 관찰자는 데이터 변경을 모니터링 한 다음 감시자에게 다시 공급합니다. Watcher는 변경 결과를 업데이트에 알리고 해당 새로 고침 기능을 찾아보기를 새로 고칩니다.
위의 과정은 그림에 나와 있습니다.
다음은이 5 가지 모듈의 구현의 기본 원칙에 대한 설명입니다 (코드는 주요 부분에만 게시되며 전체 구현을 위해 내 Github로 이동하십시오).
1. 컴파일 모듈 컴파일러
컴파일러의 책임은 주로 요소의 각 노드에 대한 지침을 스캔하고 추출하는 것입니다. 컴파일 및 구문 분석 프로세스는 컴파일 효율을 향상시키기 위해 전체 노드 트리를 여러 번 통과하기 때문에 MVVM 생성자에서 먼저 요소를 문서 조각의 사본으로 변환합니다. 컴파일 객체는이 문서 조각이며 대상 요소가되어서는 안됩니다. 모든 노드가 컴파일되면 문서 조각이 원래 실제 노드에 다시 추가됩니다.
vm.complieelement는 요소의 모든 노드의 스캔 및 지시 추출을 구현합니다.
vm.comPileElement = function (fragment, root) {var node, childnodes = fragment.childnodes; // (var i = 0; i <childnodes.length; i ++)를 스캔합니다. 자식 노드 if (node.childnodes.length) {this.comPileElement (node, false);}} // if (root) if (root) if (root) {this.compileallnodes ();}}을 스캔합니다.vm.compileallnodes 메소드는 다음과 같이 각 노드를 컴파일합니다. $ uncompilenodes (명령어 정보를 파서에 둡니다). 노드를 컴파일하면 캐시 큐에서 제거됩니다. 동시에, 이것을 확인하십시오. $ uncompilenodes.length 길이 === 0 인 경우 모든 편집이 완료되었음을 의미합니다. 문서 조각을 실제 노드에 추가 할 수 있습니다.
2. 지시 구문 분석 모듈 파서
컴파일러 컴파일러가 각 노드에서 지침을 추출하면 구문 분석을 위해 구문 분석기로 전송 될 수 있습니다. 각 명령어에는 다른 구문 분석 방법이 있습니다. 모든 지침은 두 가지만 수행하면됩니다. 하나는 데이터 값을보기 (초기 상태)로 업데이트하는 것입니다. 다른 하나는 모델의 변경 모니터링에 새로 고침 함수를 구독하는 것입니다. 여기서 우리는 지침의 일반적인 분석 방법을 설명하기 위해 v-text를 구문 분석합니다.
parser.parsevtext = function (node, model) {// 모델 var text = this. $ model [model]에 정의 된 초기 값을 가져옵니다. // 텍스트 node.textContent = text; // 해당 새로 고침 기능 : // updater.updatenodetextContent (node, text); {node.textContent = last; // updater.updatenodetextContent (node, text);});}3. 데이터 구독 모듈 감시자
이전 예에서 Watcher는 데이터 변경 사항을 구독하는 시계 방법을 제공합니다. 하나의 매개 변수는 모델 필드 모델이고 다른 매개 변수는 콜백 함수입니다. 콜백 함수는 관찰자를 통해 트리거됩니다. 오래된 값과 오래된 값은 매개 변수에 전달됩니다. 감시자가 새로운 값을 얻은 후에는 뷰를 업데이트하기 위해 모델의 해당 콜백 (새로 고침 함수)을 찾을 수 있습니다. 모델 및 새로 고침 함수는 일대일 관계입니다. 즉, 모델은 v-rext = "title"및 v-html = "Title"지침과 같은 많은 콜백 함수 (새로 고침 함수)를 가질 수 있습니다.
Watcher.watch 구현 방법에 데이터 구독 추가 :
Watcher.Watch = 함수 (필드, 콜백, 컨텍스트) {var 콜백 = this. $ watchCallbacks; if (! 객체. [];} // 캐시 콜백 [필드] .push ([Callback, Context]);}데이터 모델의 필드 필드가 변경되면 Watcher는 필드에 가입 한 캐시 어레이의 모든 콜백을 트리거합니다.
4. 데이터 모니터링 모듈 옵저버
관찰자는 전체 MVVM 구현의 핵심 기초입니다. 나는 OO (Object.Observe)가 데이터 바인딩 혁명을 발화시키고 프론트 엔드에 큰 영향을 미칠 것이라는 기사를 읽었습니다. 불행히도, ES7 초안은 OO를 버렸다! 현재 브라우저 지원이 없습니다! 다행히도, 객체 속성의 액세스 디스크립터 (get and set)를 가로 채서 간단한 관찰자를 시뮬레이션 할 수있는 Object.DefineProperty도 있습니다.
// 오브젝트 객체의 소품 속성의 get and set 메소드를 가로 채기. defineProperty (Object, prop, {get : get : wort : return this.getValue (object, prop);}, set : function (newValue) {var OldValue = this.getValue (object, prop); if (newvalue) (newsetvalue) prop); // 변경 콜백 트리거 this.triggerChange (prop, newValue, OldValue);}});그렇다면 다른 질문이 있습니다 : 어레이 작업 (푸시, 시프트 등)을 모니터링하는 방법은 무엇입니까? 모든 MVVM 프레임 워크는 배열의 프로토 타입을 다시 작성하여 구현됩니다.
Observer.rewriteArraymethods = function (array) {var self = this; var arrayproto = array.prototype; var arraymethods = object.create (arrayproto); var method = 'push | pop | shift | Unshift | splice | sort'.split ('| '); methods.foreach (function (method) {object.defineProperty (arraymethods, method, function () {var i = arguments.length; var original = arrayproto [method]; var args = new Array (i); while (i--) {args [i]; var renuct = atrince.apply (args, args); 메소드); return result;});}); array .__ proto__ = arraymethods;}이 구현 방법은 VUE에서 참조됩니다. 나는 그것이 매우 잘 사용된다고 생각하지만 배열의 길이 속성은들을 수 없으므로 mvvm에서는 배열을 피해야합니다.
5. 새로 고침 모듈 업데이터를보십시오
Updater는 5 개의 모듈 중에서 가장 쉽고 각 명령어에 해당하는 새로 고침 기능에 대해서만 책임을 져야합니다. 예를 들어 V-Text의 새로 고침 기능과 같은 일련의 던지기 및 최종 결과를 업데이트에게 봅시다.
updater.updatenodetextContent = function (node, text) {node.textContent = text;}v-bind의 기능을 새로 고침 : 스타일 :
updater.updatenodestyle = 함수 (노드, 속성, 값) {node.style [propperty] = value;}양방향 데이터 바인딩의 구현
형태 요소의 양방향 데이터 바인딩은 MVVM의 가장 큰 기능 중 하나입니다.
실제로이 마법 기능의 구현 원리도 매우 간단합니다. 해야 할 일은 두 가지뿐입니다. 하나는 데이터가 변경 될 때 양식 값을 업데이트하는 것입니다. 다른 하나는 양식 값이 변경 될 때 데이터를 업데이트하여 데이터 값이 양식 값에 바인딩되도록하는 것입니다.
위에서 언급 한 감시자 모듈을 사용하여 양식 값을 업데이트하기위한 데이터 변경을 쉽게 수행 할 수 있습니다.
Watcher.Watch (Model, function (Last, Old) {input.value = last;}); '양식 변경으로 데이터를 업데이트하려면 폼의 가치가있는 이벤트의 가치가있는 이벤트를 실시간으로 듣고 데이터 모델의 해당 필드를 업데이트하면됩니다.
var model = this. $ model; input.addeventListenr ( 'change', function () {model [field] = this.value;}); '다른 양식 라디오, 확인란 및 선택은 동일한 원칙입니다.
위의 전체 프로세스 및 각 모듈의 기본 구현 아이디어가 설명되었습니다. 커뮤니티에 기사를 처음 게시했을 때 언어 표현 기술은 그리 좋지 않습니다. 잘못된 말과 나쁜 것들이 있다면, 나는 모든 사람들이 비판하고 수정할 수 있기를 바랍니다!
결론
프레임 워크 프로젝트에서 vue.js를 사용했기 때문에이 간단한 MVVM.JS를 시도하고 있지만 방금 지침 시스템을 사용했습니다. 많은 기능이 약 1/4 만 사용되었습니다. 데이터 바인딩과 뷰 레프레시를 구현하는 것으로 충분하다고 생각했습니다. 결과적으로, 나는 그런 JavaScript 라이브러리를 찾지 못했기 때문에 그런 바퀴를 직접 만들었습니다.
기능과 안정성은 VUE와 같은 인기있는 MVVM 프레임 워크보다 훨씬 적지 만 코드 구현은 비교적 거칠 수 있지만,이 휠을 구축하여 많은 지식이 추가되었습니다 ~ 진행 상황에 있습니다!
현재 MVVM.JS는 가장 기본적인 기능만을 구현합니다. 앞으로도 계속 개선하고 강화할 것입니다. 관심이 있으시면 함께 토론하고 개선하십시오 ~