vue 的双向绑定原理
目錄
一、一句話描述 vue 的雙向綁定原理
二、細說?vue 的雙向綁定原理
1、vue 2.x?的雙向綁定
2、vue 3.x 的雙向綁定
3、一個完整的案例
一、一句話描述 vue 的雙向綁定原理(vue 的響應式原理)
vue 在實例化的時候,使用 Object.definePropety() 方法或 Proxy 構造函數,對 data 進行 getter 和 setter 的處理。在組件渲染時,若用到 data 里的某個數據,這個數據就會被依賴收集進 watcher 里。當數據更新,如果這個數據在 watcher 里,就會收到通知并更新,否則不會更新——vue 采用“數據劫持”+“觀察者模式(發布者-訂閱者模式)”相結合的方式實現了雙向綁定——vue 的響應式原理。
【拓展】
“數據劫持”+“觀察者模式(發布者-訂閱者模式)”:通過 Object.defineProperty() 方法(Vue 2.x)或 ES6 的 Proxy 構造函數(Vue 3.x)來劫持各個屬性的 setter、getter,在數據變動時發布消息給訂閱者,觸發相應的監聽回調。
二、細說?vue 的雙向綁定原理(vue 的響應式原理)
- 第一步,“數據劫持”:vue 2.x 用 Object.defineProperty() 方法來實現數據劫持,為每個屬性分配一個訂閱者集合的管理數組 dep;vue 3.x 用 ES6 的 Proxy 構造函數來實現數據劫持。
- 第二步,“添加訂閱者”:在編譯的時候在該屬性的數組 dep 中添加訂閱者,添加方式包括:v-model 會添加一個訂閱者,{{}} 也會,v-bind 也會,只要用到該屬性的指令理論上都會。
- 第三步,“為 input 添加監聽事件”:為 input 添加監聽事件,修改值就會為該屬性賦值,觸發該屬性的 set() 方法,在 set() 方法內通知訂閱者數組 dep,訂閱者數組循環調用各訂閱者的 update() 方法更新視圖。
1、vue 2.x?的雙向綁定
--> 發布者-訂閱者模式:
// 訂閱者(觀察者) let uid = 0; class Dep {constructor(){this.id = uid++;this.subs = [];}addSub(sub){this.subs.push(sub);}removeSub(sub){const arr = this.subs,item = sub;if(arr.length){const index = arr.indexOf(item);if(index > -1){return arr.splice(index, 1);}}}depend(){if(window.target){window.target.addDep(this);}}notify(){const subs = this.subs.slice();for(let i = 0, len = subs.lengths; i < len; i++){subs[i].update();}} }// 發布者(被觀察者)(不考慮深度監聽) class Watcher {constructor(vm, expOrFn, cb) {this.vm = vm;this.deps = [];this.depIds = new Set();this.getter = expOrFn;this.cb = cb;this.value = this.get();}get() {window.target = this;var value = this.getter.call(this.vm, this.vm);window.target = undefined;return value;}addDep() {const id = dep.id;if(!this.depIds.has(id)){this.depIds.add(id);this.deps.push(dep);dep.addSub(this);}}update() {console.log("更新, value:", this.value);} }/* “發布者-訂閱者模式”的使用示例 */ // 創建 發布者 實例 var watcher = new Watcher({ x: 1 }, (val) => val); watcher.get();// 創建 訂閱者 實例 var dep = new Dep();// 訂閱者 監聽 發布者 對象 dep.depend(); dep.notify();--> 數據劫持:?
// 數據劫持 function defineReactive(obj, key, val){let dep = new Dep();Object.defineProperty(obj, key, {enumerable: true,configurable: true,get: function reactiveGetter() {dep.depend();return value;},set: function reactiveSetter(newVal) {if(val === newVal){return;}val = newVal;dep.notify();}}); }2、vue 3.x 的雙向綁定
vue 3.x 的雙向綁定與 vue 2.x?的雙向綁定,都采用?發布者-訂閱者模式,不同的是 數據劫持 的實現,vue 3.x 采用的是 ES6 的 Proxy 構造函數實現的。
Proxy(data, {get(target, key) {return target[key];},set(target, key, value) {let val = Reflect.set(target, key, value);_that.$dep[key].forEach(item => item.update());return val;} })3、一個完整的案例
<body><div id="demo"></div><input type="text" id="inp"> </body> <script type="text/javascript">var obj = {};var demo = document.querySelector('#demo')var inp = document.querySelector('#inp')Object.defineProperty(obj, 'name', {get: function() {return val;},set: function(newVal) { //當該屬性被賦值的時候觸發inp.value = newVal;demo.innerHTML = newVal;}})inp.addEventListener('input', function(e) {// 給obj的name屬性賦值,進而觸發該屬性的set方法obj.name = e.target.value;});obj.name = 'fei'; //在給obj設置name屬性的時候,觸發了set這個方法 </script>參考文件:
使用Proxy實現Vue數據劫持:使用Proxy實現Vue數據劫持 - 知乎
用一句話說明 Vuex工作原理:用一句話說明 Vuex工作原理 - 知乎
總結
以上是生活随笔為你收集整理的vue 的双向绑定原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 昆明理工大学计算机技术英语翻译,昆明理工
- 下一篇: 探索入门云计算风向标Amazon的ECS