mvvm 양방향 귀속 메커니즘의 원리와 코드 실현

5510 단어
mvvm 프레임워크의 양방향 연결은 대상이 바뀔 때 관련dom 요소의 값을 자동으로 바꾸는 것이다. 반대로dom 요소가 바뀔 때 대상의 값을 자동으로 업데이트할 수 있다. 물론dom 요소는 출력할 수 있는 input 요소를 가리킨다.
1. 먼저 단방향 귀속을 실현하고 지정된 대상의 속성 값이 바뀔 때callback 함수를 터치합니다.2. 단방향 귀속은 ES5에 추가된 defineProperty를 사용하여 실현할 수 있다. (또는 defineProperties) ES5를 사용하면 IE9 이하를 지원하지 않을 것이다. 귀속사 순환 문제를 방지하기 위해 원래의 속성은 하나의 개인 속성에 잘라서 저장해야 한다.3. defineProperty 정의 클립을 순환적으로 호출할 때 역할 영역의 문제가 발생합니다. 역할 영역 변수 대상의 값이 마지막 실행 값으로 이동하는 문제를 해결하기 위해 즉시 호출되는 클립 함수를 한 층 더 정의하여 값을 전달합니다.4. getFN과 setFN 함수를 속성 get과 set을 터치할 때 사용하도록 정의합니다. 이 함수는 개인 속성private의 읽기와 쓰기 및 리셋 함수를 트리거하여 UI 레이어 업데이트 인터페이스를 알립니다.5. 단방향 귀속이 완성된 후에 역방향 귀속을 실현한다. 즉, UI층 onchange 이후에 업데이트 데이터를 터치하면 비교적 쉽다. 이것은dom에서 사용자 정의 속성bindKey 관련 모델의 값 변화를 통해oninput 이벤트를 감청하고 onchange의 장점에 비해 실시간으로 변화하지 않고 초점을 잃지 않으며 오른쪽 키에 붙이거나 메뉴에 붙이거나 텍스트를 드래그하여 텍스트 상자에 넣는 등 방식으로 터치할 수 있어 사각지대가 전혀 없다.단점은 IE9 이상만 지원하지만 IE9 이하의 등가가 있는 onpropertychange는 사용할 수 있고 호환할 수 있다는 것이다.6. 총괄적으로 말하면 쌍방향 귀속의 원리는 복잡하지 않고 전체 코드는 50줄을 넘지 않으며 매우 간단하다. 그러나 기술적 함량이 있다. 다음은 완전한 코드이다. 만약에 방대한 구조를 사용하고 싶지 않으면 한번 사용할 수 있다.ie9 이하는 지원되지 않습니다. 만약 ie9 이하를 지원하려면avalon을 사용할 수 있습니다. 이것은 vbs로 get을 만들었고 set 액세서리의 봉인을 했습니다. 이 점은 비교적 강력합니다.
html:
<div id="container">
   <p>
   name:<input type="text" bindkey="userName">
   </p>
   <p>
   age:<input type="text" bindkey="age">
   </p>
<div>

js:
 <script type="text/javascript">
    window.Model={
        userName:"windy",
        age:34,
        skill:["javascript","html","css","jquery","node"],
        
    }
    function bindingModel(model,changeCallback){
        var propertiesMap={};
        model.__private={};
        function getFn(name){
            var result=this.__private[name]
            console.log("get value:"+name+"="+ result);
            return result;
        };
        function setFn(name,val){
            if(this.__private[name]!=val){
                console.log("set value:"+name+"="+val);
             
                this.__private[name]=val;

                if(changeCallback){
                    changeCallback(name,val);
                }
            }
        };
        for(elem in model){
            if(model.hasOwnProperty(elem) && elem!="__private" && typeof(model[elem])!="function"){
                (function(propName,propValue){
                    model.__private[propName]=propValue;// init value
                    propertiesMap[propName]={
                        get:function(){ return getFn.call(this,propName)},
                        set:function(v){ return setFn.call(this,propName,v)},
                        //value:model[elem],
                        //writable: true,
                        enumerable: true,
                        configurable: true
                    }
                })(elem,model[elem]);
            }
        }
        Object.defineProperties(model,propertiesMap)
        
    }
    function bindingBoth(model,dom){
        dom.find("[bindkey]").each(function(item){
            var key=$(this).attr("bindkey");
            $(this).val(model[key]);
            $(this).bind("input",function(){
               model[key]=$(this).val();
            })
        });
        bindingModel(model,function(name,val){
            var el=dom.find("[bindkey="+name+"]");
            if(el.val()!=val){
                el.val(val);
            }
            
        });
    }
    bindingBoth(window.Model,$("#container"))
    </script>

좋은 웹페이지 즐겨찾기