웹 프론트엔드 JS 튜토리얼 Vue 데이터의 양방향 바인딩 원리를 이해하는 방법

Vue 데이터의 양방향 바인딩 원리를 이해하는 방법

Apr 25, 2019 pm 12:00 PM
vue 데이터 양방향 바인딩

Vue 데이터 양방향 바인딩의 원리는 "게시자-구독자" 모델과 결합된 데이터 하이재킹을 통해 달성됩니다. 먼저 데이터를 모니터링한 다음 모니터링되는 속성이 변경되면 구독자에게 업데이트 여부를 알려줍니다. 업데이트되면 해당 업데이트 기능이 실행되어 뷰를 업데이트합니다.

Vue 데이터의 양방향 바인딩 원리를 이해하는 방법

Vue 데이터 양방향 바인딩 원칙은 게시자-구독자 모델과 결합된 데이터 하이재킹을 통해 구현됩니다. 먼저 데이터를 모니터링한 다음 모니터링되는 속성이 변경되면 구독자에게 업데이트 여부를 알려줍니다. 업데이트되면 해당 업데이트 기능이 실행되어 뷰가 업데이트됩니다

Vue 데이터의 양방향 바인딩 원리를 이해하는 방법

[추천 과정: Vue Tutorial]

MVC 모드

이전 MVC 모드는 단방향 바인딩이므로 Model은 View에 바인딩되어 있으며 JavaScript 코드로 Model을 업데이트하면 View가 자동으로 업데이트됩니다

Vue 데이터의 양방향 바인딩 원리를 이해하는 방법

MVVM 모드

MVVM 모드는 Model–View–ViewModel 모드입니다. View의 변경 사항이 ViewModel에 자동으로 반영되고 그 반대의 경우도 마찬가지라는 것을 인식합니다. 양방향 바인딩에 대한 이해는 사용자가 뷰를 업데이트하면 모델의 데이터가 자동으로 업데이트된다는 것입니다. 이 상황은 양방향 바인딩입니다. 좀 더 자세히 설명하면 단방향 바인딩을 기반으로 입력 요소인 input, textare 등에 변경(입력) 이벤트를 추가하여(변경 이벤트가 발생하고 View의 상태가 업데이트됨) 동적으로 모델을 수정하세요.

Vue 데이터의 양방향 바인딩 원리를 이해하는 방법

양방향 바인딩의 원리

vue 데이터 양방향 바인딩은 게시자-구독자 모델과 결합된 데이터 하이재킹을 통해 달성됩니다.

우리는 이미 데이터의 양방향 바인딩을 달성하려면 다음을 수행해야 한다는 것을 알고 있습니다. 먼저 데이터 바인딩 하이재킹 모니터링을 수행하려면 모든 속성을 모니터링하도록 리스너 관찰자를 설정해야 합니다. 속성이 변경되면 구독자 Watcher에게 업데이트가 필요한지 확인하도록 알려야 합니다. 구독자가 많기 때문에 이러한 구독자를 구체적으로 수집하고 Observer와 Watcher 간에 균일하게 관리하려면 메시지 구독자 Dep가 필요합니다. 다음으로 각 노드 요소를 스캔 및 구문 분석하고 관련 명령어(예: v-model, v-on)를 구독자 Watcher로 초기화하고 템플릿 데이터를 바꾸거나 바인딩하는 명령어 파서 컴파일도 필요합니다. 구독자 Watcher는 해당 속성의 변경 사항을 수신하면 해당 업데이트 기능을 실행하여 뷰를 업데이트합니다.

다음으로 데이터의 양방향 바인딩을 달성하기 위해 다음 3단계를 수행합니다.

(1) 모든 속성을 하이재킹 및 모니터링하고 변경 사항이 있으면 구독자에게 알리는 리스너 관찰자를 구현합니다.

(2) 구독자 감시자를 구현합니다. 각 감시자는 업데이트 기능에 바인딩되어 있으며 속성 변경에 대한 알림을 받고 해당 기능을 실행하여 뷰를 업데이트할 수 있습니다.

(3) 각 노드의 관련 명령어(v-model, v-on 및 기타 명령어)를 스캔하고 구문 분석할 수 있는 파서 컴파일을 구현합니다. 노드에 v-model, v-on 및 기타 명령어가 있는 경우 파서는 컴파일 이 유형의 노드의 템플릿 데이터를 뷰에 표시할 수 있도록 초기화한 후 해당 구독자(Watcher)를 초기화합니다.

Vue 데이터의 양방향 바인딩 원리를 이해하는 방법

Observer 구현

Observer는 데이터 리스너이며 핵심 구현 방법은 Object.defineProperty()입니다. 모든 속성을 모니터링하려면 재귀를 통해 모든 속성 값을 탐색하고 Object.defineProperty()로 처리하면 됩니다.
다음 코드는 Observer를 구현합니다.

function Observer(data) {    this.data = data;    this.walk(data);
}

Observer.prototype = {    walk: function(data) {        
var self = this;        //这里是通过对一个对象进行遍历,对这个对象的所有属性都进行监听
 Object.keys(data).forEach(function(key) {
       self.defineReactive(data, key, data[key]);
        });
    },    defineReactive: function(data, key, val) {        
    var dep = new Dep();      // 递归遍历所有子属性
        var childObj = observe(val);        
        Object.defineProperty(data, key, {            
        enumerable: true,            
        configurable: true,            
        get: function getter () {                
        if (Dep.target) {                  
        // 在这里添加一个订阅者
                  console.log(Dep.target)
                    dep.addSub(Dep.target);
                }                return val;
            },           
            // setter,如果对一个对象属性值改变,就会触发setter中的dep.notify(),
            通知watcher(订阅者)数据变更,执行对应订阅者的更新函数,来更新视图。
            set: function setter (newVal) {                
            if (newVal === val) {                    
            return;
                }
                val = newVal;              
                // 新的值是object的话,进行监听
                childObj = observe(newVal);
                dep.notify();
            }
        });
    }
};function observe(value, vm) {    if (!value || typeof value !== 'object') {        
return;
    }    return new Observer(value);
};// 消息订阅器Dep,订阅器Dep主要负责收集订阅者,然后在属性变化的时候执行对应订阅者的更新函数
function Dep () {    
this.subs = [];
}
Dep.prototype = {  /**
   * [订阅器添加订阅者]
   * @param  {[Watcher]} sub [订阅者]
   */
    addSub: function(sub) {        
    this.subs.push(sub);
    },  // 通知订阅者数据变更
    notify: function() {        
    this.subs.forEach(function(sub) {
            sub.update();
        });
    }
};
Dep.target = null;

Observer에서 다른 사람들의 소스 코드를 볼 때 제가 이해하지 못한 것 중 하나는 Dep.target이 어디서 왔는지였습니다. 저와 같은 질문을 하는 사람들이 있을 것이라고 생각합니다. 여기서는 걱정하지 마세요. Watcher를 작성할 때 이 Dep.target이 Watcher에서 온 것임을 알 수 있습니다. Dep.target是从哪里来的,相信有些人和我会有同样的疑问。这里不着急,当写到Watcher的时候,你就会发现,这个Dep.target是来源于Watcher。

实现一个Watcher

Watcher就是一个订阅者。用于将Observer发来的update消息处理,执行Watcher绑定的更新函数。

如下代码实现了一个Watcher

function Watcher(vm, exp, cb) {    
this.cb = cb;    
this.vm = vm;    
this.exp = exp;    
this.value = this.get();  // 将自己添加到订阅器的操作}

Watcher.prototype = {    update: function() {        
this.run();
    },    run: function() {        
    var value = this.vm.data[this.exp];        
    var oldVal = this.value;        
    if (value !== oldVal) {            
    this.value = value;            
    this.cb.call(this.vm, value, oldVal);
        }
    },    get: function() {
        Dep.target = this;  // 缓存自己
        var value = this.vm.data[this.exp]  // 强制执行监听器里的get函数
        Dep.target = null;  // 释放自己
        return value;
    }
};

在我研究代码的过程中,我觉得最复杂的就是理解这些函数的参数,后来在我输出了这些参数之后,函数的这些功能也容易理解了。vm,就是之后要写的SelfValue对象,相当于Vue中的new Vue的一个对象。exp是node节点的v-model或v-on:click等指令的属性值。

上面的代码中就可以看出来,在Watcher的getter函数中,Dep.target指向了自己,也就是Watcher对象。在getter函数中,

var value = this.vm.data[this.exp]  // 强制执行监听器里的get函数。
这里获取vm.data[this.exp] 时,会调用Observer中Object.defineProperty中的get函数
get: function getter () {                
if (Dep.target) {                  
// 在这里添加一个订阅者                  
console.log(Dep.target)                    
dep.addSub(Dep.target);                
}                
return val;            
},

从而把watcher添加到了订阅器中,也就解决了上面Dep.target

Watcher 구현

Watcher는 구독자입니다. Observer가 보낸 업데이트 메시지를 처리하고 Watcher에 바인딩된 업데이트 기능을 실행하는 데 사용됩니다. 🎜🎜다음 코드는 Watcher를 구현합니다🎜
<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>self-vue</title></head><style>
    #app {        
    text-align: center;
    }</style><body>
    <div id="app">
        <h2>{{title}}</h2>
        <input v-model="name">
        <h1>{{name}}</h1>
        <button v-on:click="clickMe">click me!</button>
    </div></body><script src="js/observer.js"></script>
    <script src="js/watcher.js"></script>
    <script src="js/compile.js"></script>
    <script src="js/mvvm.js"></script>
    <script type="text/javascript">
     var app = new SelfVue({        
     el: &#39;#app&#39;,        
     data: {            
     title: &#39;hello world&#39;,            
     name: &#39;canfoo&#39;
        },        
        methods: {            
        clickMe: function () {                
        this.title = &#39;hello world&#39;;
            }
        },        
        mounted: function () {            
        window.setTimeout(() => {                
        this.title = &#39;你好&#39;;
            }, 1000);
        }
    });</script></html>
🎜코드를 공부하는 과정에서 가장 어려운 것은 이 함수의 매개변수를 이해하는 것이라고 느꼈습니다. 나중에 이 매개변수를 출력하고 나니 함수의 기능이 쉬웠습니다. 이해하다. vm은 나중에 작성할 SelfValue 객체로, Vue의 new Vue 객체와 동일합니다. exp는 노드 노드의 v-model 또는 v-on: click 및 기타 지침의 속성 값입니다. 🎜🎜위 코드에서 볼 수 있듯이 Watcher의 getter 함수에서 Dep.target은 Watcher 개체인 자신을 가리킵니다. getter 함수에서 🎜
observe(this.data);
new Compile(options.el, this);
🎜는 구독자에 감시자를 추가하여 Dep.target의 출처에 대한 문제를 해결합니다. 🎜🎜🎜컴파일 구현🎜🎜

Compile主要的作用是把new SelfVue 绑定的dom节点,(也就是el标签绑定的id)遍历该节点的所有子节点,找出其中所有的v-指令和" {{}} ".
(1)如果子节点含有v-指令,即是元素节点,则对这个元素添加监听事件。(如果是v-on,则node.addEventListener(&#39;click&#39;),如果是v-model,则node.addEventListener(&#39;input&#39;))。接着初始化模板元素,创建一个Watcher绑定这个元素节点。

(2)如果子节点是文本节点,即" {{ data }} ",则用正则表达式取出" {{ data }} "中的data,然后var initText = this.vm[exp],用initText去替代其中的data。

实现一个MVVM

可以说MVVM是Observer,Compile以及Watcher的“boss”了,他需要安排给Observer,Compile以及Watche做的事情如下

(1)Observer实现对MVVM自身model数据劫持,监听数据的属性变更,并在变动时进行notify
(2)Compile实现指令解析,初始化视图,并订阅数据变化,绑定好更新函数
(3)Watcher一方面接收Observer通过dep传递过来的数据变化,一方面通知Compile进行view update。
最后,把这个MVVM抽象出来,就是vue中Vue的构造函数了,可以构造出一个vue实例。

最后写一个html测试一下我们的功能

<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>self-vue</title></head><style>
    #app {        
    text-align: center;
    }</style><body>
    <div id="app">
        <h2>{{title}}</h2>
        <input v-model="name">
        <h1>{{name}}</h1>
        <button v-on:click="clickMe">click me!</button>
    </div></body><script src="js/observer.js"></script>
    <script src="js/watcher.js"></script>
    <script src="js/compile.js"></script>
    <script src="js/mvvm.js"></script>
    <script type="text/javascript">
     var app = new SelfVue({        
     el: &#39;#app&#39;,        
     data: {            
     title: &#39;hello world&#39;,            
     name: &#39;canfoo&#39;
        },        
        methods: {            
        clickMe: function () {                
        this.title = &#39;hello world&#39;;
            }
        },        
        mounted: function () {            
        window.setTimeout(() => {                
        this.title = &#39;你好&#39;;
            }, 1000);
        }
    });</script></html>

先执行mvvm中的new SelfVue(...),在mvvm.js中,

observe(this.data);
new Compile(options.el, this);

先初始化一个监听器Observer,用于监听该对象data属性的值。
然后初始化一个解析器Compile,绑定这个节点,并解析其中的v-," {{}} "指令,(每一个指令对应一个Watcher)并初始化模板数据以及初始化相应的订阅者,并把订阅者添加到订阅器中(Dep)。这样就实现双向绑定了。
如果v-model绑定的元素,

<input v-model="name">

即输入框的值发生变化,就会触发Compile中的

node.addEventListener(&#39;input&#39;, function(e) {            
var newValue = e.target.value;            
if (val === newValue) {                
return;
            }            
            self.vm[exp] = newValue;
            val = newValue;
        });

self.vm[exp] = newValue;这个语句会触发mvvm中SelfValue的setter,以及触发Observer对该对象name属性的监听,即Observer中的Object.defineProperty()中的setter。setter中有通知订阅者的函数dep.notify,Watcher收到通知后就会执行绑定的更新函数。
最后的最后就是效果图啦:

Vue 데이터의 양방향 바인딩 원리를 이해하는 방법

위 내용은 Vue 데이터의 양방향 바인딩 원리를 이해하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Clothoff.io

Clothoff.io

AI 옷 제거제

Video Face Swap

Video Face Swap

완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

뜨거운 주제

VUE의 반응성 변환 (실험, 제거) 및 목표의 중요성은 무엇입니까? VUE의 반응성 변환 (실험, 제거) 및 목표의 중요성은 무엇입니까? Jun 20, 2025 am 01:01 AM

반응성 transforminvue3aimedtosimplify handlingreactivedatabyautomicallytrackingandmaningreactivity withoutequiringmanualref () 또는 valueusage.itsivingtoreduceboilerplateandimprovecodeReadabilitabledevariableletandsconstasmonclicallicallicallicallicallicallicallicallicallicallicallicalliceLerplateNclateMconsconclicallicallicallicallicallicallicallicallicalliceLerplateN

VUE 응용 프로그램에서 국제화 (I18N) 및 현지화 (L10N)를 어떻게 구현할 수 있습니까? VUE 응용 프로그램에서 국제화 (I18N) 및 현지화 (L10N)를 어떻게 구현할 수 있습니까? Jun 20, 2025 am 01:00 AM

국제화 및 국제화 invueAppsareprimally handledusingthevuei18nplugin.1.installvue-i18nvianpmoryarn.2.createlocalejsonfiles (예 : en.json, es.json) fortranslationMessages.3

VUE에서 서버 사이드 렌더링 SSR이란 무엇입니까? VUE에서 서버 사이드 렌더링 SSR이란 무엇입니까? Jun 25, 2025 am 12:49 AM

SPR (Server-SiderEndering)은 초대적으로 성능이 우수한 사람을 초대한다

VUE로 구성 요소 라이브러리를 구축하는 방법? VUE로 구성 요소 라이브러리를 구축하는 방법? Jul 10, 2025 pm 12:14 PM

VUE 구성 요소 라이브러리를 구축하려면 비즈니스 시나리오 주변의 구조를 설계하고 전체 개발, 테스트 및 릴리스 프로세스에 따라야합니다. 1. 구조 설계는 기본 구성 요소, 레이아웃 구성 요소 및 비즈니스 구성 요소를 포함한 기능 모듈에 따라 분류되어야합니다. 2. 주제와 스타일을 통합하기 위해 SCSS 또는 CSS 변수를 사용하십시오. 3. 명명 사양을 통합하고 일관된 코드 스타일을 보장하기 위해 Eslint 및 Pretier를 소개합니다. 4. 지원 문서 사이트에 구성 요소의 사용을 표시합니다. 5. VITE 및 기타 도구를 사용하여 NPM 패키지로 패키지하고 롤 업프를 구성합니다. 6. Semver 사양에 따라 게시 할 때 버전 및 Changelogs를 관리하십시오.

VUE에서 전환 및 애니메이션을 구현하는 방법은 무엇입니까? VUE에서 전환 및 애니메이션을 구현하는 방법은 무엇입니까? Jun 24, 2025 pm 02:17 PM

ToaddtransitionsandanimationsinVue,usebuilt-incomponentslikeand,applyCSSclasses,leveragetransitionhooksforcontrol,andoptimizeperformance.1.WrapelementswithandapplyCSStransitionclasseslikev-enter-activeforbasicfadeorslideeffects.2.Useforanimatingdynam

VUE의 다음 텔릭 함수의 목적은 무엇이며 언제 필요한가요? VUE의 다음 텔릭 함수의 목적은 무엇이며 언제 필요한가요? Jun 19, 2025 am 12:58 AM

NextTick은 VUE에서 DOM 업데이트 후 코드를 실행하는 데 사용됩니다. 데이터가 변경되면 VUE는 즉시 DOM을 업데이트하지 않지만 다음 이벤트 루프 "Tick"에서 DOM에 넣고 처리합니다. 따라서 업데이트 된 DOM에 액세스하거나 작동 해야하는 경우 NextTick을 사용해야합니다. 일반적인 시나리오는 다음과 같습니다. 업데이트 된 DOM 컨텐츠 액세스, DOM 상태에 의존하는 타사 라이브러리와 협력하고 요소 크기를 기준으로 계산합니다. 사용법은 이것을 호출하는 것이 포함됩니다. $ NextTick은 구성 요소 방법으로, 가져온 후 단독으로 사용하고 Async/Await를 결합합니다. 예방 조치에는 다음이 포함됩니다. 과도한 사용을 피하십시오. 대부분의 경우 수동 트리거링이 필요하지 않으며 다음 번에 한 번에 여러 업데이트를 캡처 할 수 있습니다.

PHP를 사용하여 Q & A 커뮤니티 플랫폼을 개발하는 방법 PHP 대화 형 커뮤니티 수익 창출 모델에 대한 자세한 설명 PHP를 사용하여 Q & A 커뮤니티 플랫폼을 개발하는 방법 PHP 대화 형 커뮤니티 수익 창출 모델에 대한 자세한 설명 Jul 23, 2025 pm 07:21 PM

1. PHP 개발 질문 및 답변 커뮤니티에서 Laravel MySQL VUE/React 조합의 첫 번째 선택은 생태계의 성숙과 높은 개발 효율로 인해 Laravel MySQL VUE/React 조합의 첫 번째 선택입니다. 2. 고성능은 캐시 (REDIS), 데이터베이스 최적화, CDN 및 비동기 큐에 의존해야합니다. 3. 입력 필터링, CSRF 보호, HTTPS, 비밀번호 암호화 및 권한 제어로 보안을 수행해야합니다. 4. 돈 선택적 광고, 회원 가입, 보상, 커미션, 지식 지불 및 기타 모델은 핵심은 커뮤니티 톤 및 사용자 요구에 맞는 것입니다.

PHP PHP 지능형 양식 설계 및 분석으로 AI 지능형 양식 시스템을 개발하는 방법 PHP PHP 지능형 양식 설계 및 분석으로 AI 지능형 양식 시스템을 개발하는 방법 Jul 25, 2025 pm 05:54 PM

적절한 PHP 프레임 워크를 선택할 때는 프로젝트 요구에 따라 포괄적으로 고려해야합니다. Laravel은 빠른 개발에 적합하며 엘로라 톰 및 블레이드 템플릿 엔진을 제공하며 데이터베이스 작동 및 동적 형태 렌더링에 편리합니다. Symfony는 더 유연하고 복잡한 시스템에 적합합니다. Codeigniter는 가볍고 고성능 요구 사항을 가진 간단한 응용 프로그램에 적합합니다. 2. AI 모델의 정확성을 보장하려면 고품질 데이터 교육, 합리적인 평가 지표 (예 : 정확도, 리콜, F1 값), 정기적 인 성능 평가 및 모델 튜닝과 같은 합리적인 평가 표시기 선택으로 시작하고 단위 테스트 및 통합 테스트를 통한 코드 품질을 보장하면서 입력 데이터를 지속적으로 모니터링하여 데이터 드리프트를 방지해야합니다. 3. 사용자 개인 정보 보호를위한 많은 조치가 필요합니다. AES와 같은 민감한 데이터를 암호화하고 저장합니다.

See all articles