国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

學(xué)習(xí)MVVM及框架的雙向綁定筆記

VioletJack / 1088人閱讀

摘要:的數(shù)據(jù)劫持版本內(nèi)部使用了來實(shí)現(xiàn)數(shù)據(jù)與視圖的雙向綁定,體現(xiàn)在對數(shù)據(jù)的讀寫處理過程中。這樣就形成了數(shù)據(jù)的雙向綁定。

MVVM由以下三個(gè)內(nèi)容組成

View:視圖模板

Model:數(shù)據(jù)模型

ViewModel:作為橋梁負(fù)責(zé)溝通ViewModel,自動渲染模板

JQuery時(shí)期,如果需要刷新UI時(shí),需要先取到對應(yīng)的DOM再更新UI,這樣數(shù)據(jù)和業(yè)務(wù)的邏輯就和頁面有強(qiáng)耦合。

MVVM中,UI是挺數(shù)據(jù)驅(qū)動的,數(shù)據(jù)一旦改變就會刷新相應(yīng)的UIUI變化也會改變相應(yīng)的數(shù)據(jù)。這種方式在開發(fā)中只需要關(guān)心數(shù)據(jù)的變化,不用直接去操作DOM。并且可以將一些可復(fù)用的邏輯放在一個(gè)ViewModel中,多個(gè)View復(fù)用這個(gè)ViewModel

MVVM 中,最核心的也就是數(shù)據(jù)雙向綁定,例如 Angluar 的臟數(shù)據(jù)檢測Vue 的數(shù)據(jù)劫持React的數(shù)據(jù)綁定

Angluar 的臟數(shù)據(jù)檢測

當(dāng)觸發(fā)了指定事件后進(jìn)入臟數(shù)據(jù)檢測,這時(shí)期會調(diào)用$digest循環(huán)遍歷所有的數(shù)據(jù)觀察者,判斷當(dāng)前值是否和先前的值有區(qū)別,如果檢測到變化的話,會調(diào)用$watch函數(shù),然后再次調(diào)用$digest循環(huán)直到發(fā)現(xiàn)沒有變化。所以這個(gè)過程可能會循環(huán)幾次,一直到不再有數(shù)據(jù)變化發(fā)生后,將變更的數(shù)據(jù)發(fā)送到視圖,更新頁面展現(xiàn)。如果是手動對 ViewModel 的數(shù)據(jù)進(jìn)行變更,為確保變更同步到視圖,需要手動觸發(fā)一次“臟值檢測”。

臟數(shù)據(jù)檢測雖然需要每次去循環(huán)遍歷查看是否有數(shù)據(jù)變化,存在低效的問題,與Vue的雙向綁定原理不同,但是臟數(shù)據(jù)檢測能夠同時(shí)檢測出要更新的值,再去統(tǒng)一更新UI,這樣也可以減少操作DOM的次數(shù)。

Vue 的數(shù)據(jù)劫持

Vue2.0版本內(nèi)部使用了Object.defineProperty()來實(shí)現(xiàn)數(shù)據(jù)與視圖的雙向綁定,體現(xiàn)在對數(shù)據(jù)的讀寫處理過程中。即Object.defineProperty()中定義的數(shù)據(jù)setget函數(shù)。

使用Object.defineProperty()實(shí)現(xiàn)Vue2.0雙向綁定的小demo

 
---------------------------------------------------------------------- var obj = {}; Object.defineProperty(obj, "prop", { get: function() { return val; }, set: function(newVal) { val = newVal; document.getElementById("input").value = val; document.getElementById("text").innerHTML = val; } }); document.addEventListener("keyup", function(e) { obj.prop = e.target.value; });

如上所述,vue.js通過Object.defineProperty()來劫持各個(gè)屬性的settergetter。再結(jié)合發(fā)布者-訂閱者的方式,發(fā)布消息給訂閱者,觸發(fā)相應(yīng)的監(jiān)聽回調(diào)。通過Directives指令去對DOM做封裝,當(dāng)數(shù)據(jù)發(fā)生變化,會通知指令去修改對應(yīng)的DOM,數(shù)據(jù)驅(qū)動DOM的變化。vue.js還會對操作做一些監(jiān)聽(DOM Listener),當(dāng)我們修改視圖的時(shí)候,vue.js監(jiān)聽到這些變化,從而改變數(shù)據(jù)。這樣就形成了數(shù)據(jù)的雙向綁定。

在對數(shù)據(jù)進(jìn)行讀取時(shí),如果當(dāng)前有 Watcher(對數(shù)據(jù)的觀察者,watcher 會負(fù)責(zé)將獲取的新數(shù)據(jù)發(fā)送給視圖),那將該 Watcher 綁定到當(dāng)前的數(shù)據(jù)上(dep.depend(),dep 關(guān)聯(lián)當(dāng)前數(shù)據(jù)和所有的 watcher 的依賴關(guān)系),是一個(gè)檢查并記錄依賴的過程。而在對數(shù)據(jù)進(jìn)行賦值時(shí),如果數(shù)據(jù)發(fā)生改變,則通知所有的 watcher(借助 dep.notify())。這樣,即便是我們手動改變了數(shù)據(jù),框架也能夠自動將數(shù)據(jù)同步到視圖。
完整的簡易雙向綁定代碼如下:

var data = { name: "yck" }
observe(data)
let name = data.name // -> get value
data.name = "yyy" // -> change value

function observe(obj) {
  // 判斷類型
  if (!obj || typeof obj !== "object") {
    return
  }
  Object.keys(obj).forEach(key => {
    defineReactive(obj, key, obj[key])
  })
}

function defineReactive(obj, key, val) {
  // 遞歸子屬性
  observe(val)
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter() {
      console.log("get value")
      return val
    },
    set: function reactiveSetter(newVal) {
      console.log("change value")
      val = newVal
    }
  })
}

以上代碼簡單的實(shí)現(xiàn)了如何監(jiān)聽數(shù)據(jù)的setget,下面再給屬性添加發(fā)布訂閱

{{name}}

在解析模板的時(shí)候遇到{{ name }}就給屬性name添加發(fā)布訂閱

// 通過 Dep 解耦
class Dep {
  constructor() {
    this.subs = []
  }
  addSub(sub) {
    // sub 是 Watcher 實(shí)例
    this.subs.push(sub)
  }
  notify() {
    this.subs.forEach(sub => {
      sub.update()
    })
  }
}
// 全局屬性,通過該屬性配置 Watcher
Dep.target = null

function update(value) {
  document.querySelector("div").innerText = value
}

class Watcher {
  constructor(obj, key, cb) {
    // 將 Dep.target 指向自己
    // 然后觸發(fā)屬性的 getter 添加監(jiān)聽
    // 最后將 Dep.target 置空
    Dep.target = this
    this.cb = cb
    this.obj = obj
    this.key = key
    this.value = obj[key]
    Dep.target = null
  }
  update() {
    // 獲得新值
    this.value = this.obj[this.key]
    // 調(diào)用 update 方法更新 Dom
    this.cb(this.value)
  }
}
var data = { name: "yck" }
observe(data)
// 模擬解析到 `{{name}}` 觸發(fā)的操作
new Watcher(data, "name", update)
// update Dom innerText
data.name = "yyy"

下面對defineReactive函數(shù)進(jìn)行改造:

function defineReactive(obj, key, val) {
  // 遞歸子屬性
  observe(val)
  let dp = new Dep()
  Object.defineProperty(obj, key, {
    enumerable: true,
    configurable: true,
    get: function reactiveGetter() {
      console.log("get value")
      // 將 Watcher 添加到訂閱
      if (Dep.target) {
        dp.addSub(Dep.target)
      }
      return val
    },
    set: function reactiveSetter(newVal) {
      console.log("change value")
      val = newVal
      // 執(zhí)行 watcher 的 update 方法
      dp.notify()
    }
  })
}

核心思路就是手動觸發(fā)一次屬性的 getter 來實(shí)現(xiàn)發(fā)布訂閱的添加。

Vue3.0將用proxy代替Object.defineProperty()

Object.defineProperty()的缺陷:

1.只能對屬性進(jìn)行數(shù)據(jù)劫持,所以需要深度遍歷整個(gè)對象

2.對于數(shù)組不能監(jiān)聽到數(shù)據(jù)的變化

雖然 Vue 2.0中能檢測到數(shù)組數(shù)據(jù)的變化,但是其實(shí)是使用了 hack 的辦法,并且也是有缺陷的

const arrayProto = Array.prototype
export const arrayMethods = Object.create(arrayProto)
// hack 以下幾個(gè)函數(shù)
const methodsToPatch = [
  "push",
  "pop",
  "shift",
  "unshift",
  "splice",
  "sort",
  "reverse"
]
methodsToPatch.forEach(function(method) {
  // 獲得原生函數(shù)
  const original = arrayProto[method]
  def(arrayMethods, method, function mutator(...args) {
    // 調(diào)用原生函數(shù)
    const result = original.apply(this, args)
    const ob = this.__ob__
    let inserted
    switch (method) {
      case "push":
      case "unshift":
        inserted = args
        break
      case "splice":
        inserted = args.slice(2)
        break
    }
    if (inserted) ob.observeArray(inserted)
    // 觸發(fā)更新
    ob.dep.notify()
    return result
  })
})

Proxy原生支持監(jiān)聽數(shù)組變化,并且可以直接對整個(gè)對象進(jìn)行攔截,所以Vue3.0使用 Proxy 替換 Object.defineProperty

let onWatch = (obj, setBind, getLogger) => {
  let handler = {
    get(target, property, receiver) {
      getLogger(target, property)
      return Reflect.get(target, property, receiver)
    },
    set(target, property, value, receiver) {
      setBind(value)
      return Reflect.set(target, property, value)
    }
  }
  return new Proxy(obj, handler)
}

let obj = { a: 1 }
let value
let p = onWatch(
  obj,
  v => {
    value = v
  },
  (target, property) => {
    console.log(`Get "${property}" = ${target[property]}`)
  }
)
p.a = 2 // bind `value` to `2`
p.a // -> Get "a" = 2
React的數(shù)據(jù)綁定

React的數(shù)據(jù)綁定是虛擬DOM樹的更新相關(guān):
屬性更新,組件自己處理

結(jié)構(gòu)更新,重新“渲染”子樹(虛擬DOM),找出最小改動步驟,打包DOM操作,給真實(shí)DOM樹打補(bǔ)丁

單純從數(shù)據(jù)綁定來看,React虛擬DOM沒有數(shù)據(jù)綁定,因?yàn)?b>setState()不維護(hù)上一個(gè)狀態(tài)(狀態(tài)丟棄)

從數(shù)據(jù)更新機(jī)制來看,React類似于提供數(shù)據(jù)模型的方式(必須通過state更新)

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/101461.html

相關(guān)文章

  • 基于VueMVVM學(xué)習(xí)筆記

    摘要:發(fā)布訂閱現(xiàn)在每個(gè)人應(yīng)該都用微信吧,一個(gè)人可以關(guān)注多個(gè)公眾號,多個(gè)人可以同時(shí)關(guān)注相同的公眾號。公眾號每周都會更新內(nèi)容,并推送給我們,把寫好的文章在微信管理平臺更新就好了,點(diǎn)擊推送,就相當(dāng)于發(fā)布。 什么是MVVM MVVM——Model-View-ViewModle的縮寫,MVC設(shè)計(jì)模式的改進(jìn)版。Model是我們應(yīng)用中的數(shù)據(jù)模型,View是我們的UI層,通過ViewModle,可以把我們M...

    Alan 評論0 收藏0
  • JS中雙向數(shù)據(jù)綁定Object.defineProperty方法

    摘要:,而且每種框架雙向數(shù)據(jù)綁定的實(shí)現(xiàn)方式都不太一致,比如內(nèi)部使用的是臟檢查,而內(nèi)部實(shí)現(xiàn)方式的本質(zhì)是設(shè)置屬性訪問器。在中也有類似的概念,不過不叫魔術(shù)方法,而是叫做訪問器。 緣起前幾天在看一些流行的迷你mvvm框架(比如avalon.js、 vue.js 這種較輕的框架,而非Angularjs、Emberjs這種較重的框架)的實(shí)現(xiàn)。現(xiàn)代流行的mvvm框架一般都會將數(shù)據(jù)雙向綁定(two-ways...

    szysky 評論0 收藏0
  • JS中雙向數(shù)據(jù)綁定Object.defineProperty方法

    摘要:,而且每種框架雙向數(shù)據(jù)綁定的實(shí)現(xiàn)方式都不太一致,比如內(nèi)部使用的是臟檢查,而內(nèi)部實(shí)現(xiàn)方式的本質(zhì)是設(shè)置屬性訪問器。在中也有類似的概念,不過不叫魔術(shù)方法,而是叫做訪問器。 緣起前幾天在看一些流行的迷你mvvm框架(比如avalon.js、 vue.js 這種較輕的框架,而非Angularjs、Emberjs這種較重的框架)的實(shí)現(xiàn)。現(xiàn)代流行的mvvm框架一般都會將數(shù)據(jù)雙向綁定(two-ways...

    蘇丹 評論0 收藏0
  • JavaScript 進(jìn)階之深入理解數(shù)據(jù)雙向綁定

    摘要:當(dāng)我們的視圖和數(shù)據(jù)任何一方發(fā)生變化的時(shí)候,我們希望能夠通知對方也更新,這就是所謂的數(shù)據(jù)雙向綁定。返回值返回傳入函數(shù)的對象,即第一個(gè)參數(shù)該方法重點(diǎn)是描述,對象里目前存在的屬性描述符有兩種主要形式數(shù)據(jù)描述符和存取描述符。 前言 談起當(dāng)前前端最熱門的 js 框架,必少不了 Vue、React、Angular,對于大多數(shù)人來說,我們更多的是在使用框架,對于框架解決痛點(diǎn)背后使用的基本原理往往關(guān)注...

    sarva 評論0 收藏0

發(fā)表評論

0條評論

VioletJack

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<