国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 語言 > JavaScript > 正文

vue雙向綁定及觀察者模式詳解

2024-05-06 15:41:32
字體:
來源:轉載
供稿:網友

在Vue中,使用了Object.defineProterty()這個函數來實現雙向綁定,這也就是為什么Vue不兼容IE8

1 響應式原理

讓我們先從相應式原理開始。我們可以通過Object.defineProterty()來自定義Object的getter和setter 從而達到我們的目的。

代碼如下

function observe(value, cb) { Object.keys(value).forEach((key) => defineReactive(value, key, value[key] , cb))}function defineReactive (obj, key, val, cb) { Object.defineProperty(obj, key, {  enumerable: true,  configurable: true,  get: ()=>{   /*....依賴收集等....*/   /*Github:https://github.com/answershuto*/   return val  },  set:newVal=> {   val = newVal;   cb();/*訂閱者收到消息的回調*/  } })}class Vue { constructor(options) {  this._data = options.data;  observe(this._data, options.render) }}let app = new Vue({ el: '#app', data: {  text: 'text',  text2: 'text2' }, render(){  console.log("render"); }})

通過observe函數對app.data上的每一個key和value都設定getter和setter。當value改變的時候觸發setter,就會觸發render這個函數。響應式的目的就達成,如果是視圖更新的話我們通過監聽dom的input事件來觸發數據更新
但是現在我們只有在改變vue._data.text的時候才會觸發他們的setter,但是我想偷懶,只改變vue.text就能觸發到setter怎么做呢?

我們使用代理的方法

_proxy.call(this, options.data);/*構造函數中*//*代理*/function _proxy (data) { const that = this; Object.keys(data).forEach(key => {  Object.defineProperty(that, key, {   configurable: true,   enumerable: true,   get: function proxyGetter () {    return that._data[key];   },   set: function proxySetter (val) {    that._data[key] = val;   }  }) });}

依賴收集

讓我們再來看看下面的代碼

new Vue({ template:   `<div>   <span>text1:</span> {{text1}}   <span>text2:</span> {{text2}}  <div>`, data: {  text1: 'text1',  text2: 'text2',  text3: 'text3' }});

當你的text3變化的時候,實際上text3并沒有被渲染,但是也會觸發一次render函數,這顯然是不對的。所以我們需要收集依賴。

我們只需要在初始化的時候渲染一遍,那所有渲染所依賴的數據都會被觸發getter,這時候我們只要把這個數據放到一個列表里就好啦!

我們先來認識一下Dep(dependencies)這個類,下圖是一個最簡單的Dep類。我們可以把他理解為發布者(這點很重要?。。?br />

class Dep { constructor () {  this.subs = []; } addSub (sub: Watcher) {  this.subs.push(sub) } removeSub (sub: Watcher) {  remove(this.subs, sub) } /*Github:https://github.com/answershuto*/ notify () {  // stabilize the subscriber list first  const subs = this.subs.slice()  for (let i = 0, l = subs.length; i < l; i++) {   subs[i].update()  } }}function remove (arr, item) { if (arr.length) {  const index = arr.indexOf(item)  if (index > -1) {   return arr.splice(index, 1) }}            
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

主站蜘蛛池模板: 黎平县| 临高县| 建湖县| 义乌市| 伊春市| 桃源县| 兴国县| 子洲县| 舒兰市| 彭山县| 汪清县| 阳春市| 视频| 峨山| 西贡区| 新竹县| 凤台县| 云和县| 时尚| 玉龙| 泰宁县| 崇文区| 郎溪县| 名山县| 泰州市| 肃北| 定南县| 沁源县| 朝阳市| 德江县| 汉阴县| 涿鹿县| 隆尧县| 西丰县| 台湾省| 绥江县| 牙克石市| 盘山县| 思南县| 襄汾县| 海安县|