成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

使用ES6新特性實現(xiàn)簡單的MVVM(1)--數(shù)據(jù)驅(qū)動

cloud / 1728人閱讀

摘要:嘗試使用新特性,自己來實現(xiàn)一個及的各種特性。我們可以利用這個特性來實現(xiàn)對數(shù)據(jù)的監(jiān)聽結(jié)果簡單的操作我們已經(jīng)可以對簡單的數(shù)據(jù)操作進行監(jiān)聽雖然還有各種問題,接下來,我們只要在監(jiān)聽到后進行數(shù)據(jù)操作即可。

嘗試使用es6新特性,自己來實現(xiàn)一個mvvm及vue的各種特性。
相關(guān)代碼放在github,會持續(xù)更新,歡迎賞個star。
本篇文章為系列文章的第一篇,會比較容易理解,后續(xù)會持續(xù)更新后面的記錄。
文章首發(fā)于本人博客

最簡單的watcher

從開始接觸Vue開始,我們便對它的“數(shù)據(jù)響應(yīng)”贊嘆不絕,那么我們首先,來實現(xiàn)一個最簡單的watcher,來監(jiān)聽數(shù)據(jù),以進行對應(yīng)的操作,類似后續(xù)會涉及的dom操作等。

Proxy

我們都知道,Vue使用Object.defineProperty來進行數(shù)據(jù)監(jiān)聽,監(jiān)聽obj的get和set方法。在ES6中,Proxy可以攔截某些操作的默認行為,也就是對目標(biāo)對象的訪問進行攔截,過濾和改寫。我們可以利用這個特性來實現(xiàn)對數(shù)據(jù)的監(jiān)聽:

const watcher = (obj, fn) => {
  return new Proxy(obj, {
    get (target, prop, receiver) {
      return Reflect.get(target, prop, receiver)
    },

    set (target, prop, value) {
      const oldValue = Reflect.get(target, prop, receiver)
      const result = Reflect.set(target, prop, value)

      fn(value, oldValue)

      return result
    }
  })
}

結(jié)果:

let obj = watcher({ a: 1 }, (val, oldVal) => {
  console.log("old =>> ", oldVal)
  console.log("new =>> ", val)
})

obj.a = 2
// old =>> , 1
// new =>> , 2
簡單的Dom操作

我們已經(jīng)可以對簡單的數(shù)據(jù)操作進行監(jiān)聽(雖然還有各種問題),接下來,我們只要在監(jiān)聽到dom后進行數(shù)據(jù)操作即可。解析模板什么的我們就先不做了,我們可以繼續(xù)利用Proxy實現(xiàn)一個dom輔助函數(shù):

const dom = new Proxy({}, {
  get (target, tagName) {
    return (attrs = {}, ...childrens) => {
      // 創(chuàng)建節(jié)點
      const elem = document.createElement(tagName)

      // 添加attribute
      attrs.forEach(attr => elem.addAttribute(attr, attrs[attr])

      // 添加子元素
      childrens.forEach(child => {
        const child = typeof child === "string"
          ? document.createTextNode(child) 
          : child

        elem.appendChild(child)
      })

      return elem
    }
  }
})

也就是說,我們?yōu)閐om的各屬性進行監(jiān)聽,當(dāng)訪問對應(yīng)的節(jié)點時,我們創(chuàng)建并且為他添加各種屬性等:

dom.div(
  {class: "wrap"}, 
  "helloworld",
  dom.a({
    href: "https://www.#"
  }, "welcome to 360")
)

// 輸出
helloworld welcome to 360
拼接基礎(chǔ)框架

我們在這里給我們的這個小架子起名為"W",讓它可以真正的運行起來。類似Vue的語法,我們需要在進行實例化的時候,watch我們的data,并且更新dom。類似這樣:

const vm = new W({
  el: "body",
  data () {
    return {
      msg: "hello world"
    }
  },
  render () {
    return dom.div({
      class: "wrap"
    },
      dom.a({
        href: "http://www.#"
      }, this.msg)
    )
  }
})

因此,我們需要實現(xiàn)這樣一個類,來處理我們的參數(shù),并進行實例的初始化,監(jiān)聽,以及渲染控制等。

export default class W {
  constructor (config) {}

  /**
   * observe data
   */
  _initData () {}

  /**
   * 渲染節(jié)點
   */
  _renderDom () {}
}
初始化數(shù)據(jù)

首先,我們進行數(shù)據(jù)初始化,將數(shù)據(jù)置為observable,在對其修改的時候進行監(jiān)聽:

import watcher from "./data.js"

class W {
  constructor (config) {
    const { data = () => {} } = config

    this._config = config
    this._initData(data)

    return this._vm
  }
}

_initData (data) {
  this._vm = watcher(Object.assign({}, this, data()), this._renderDom.bind(this))
}

在這里我們需要注意兩點:

我們的data參數(shù)為一個function
這個原因在vue官方文檔已經(jīng)說過,當(dāng)我們直接使用對象的時候,不同的實例間會共享同一個對象,導(dǎo)致出現(xiàn)對一個組件進行修改,另一個組件也進行修改的問題。具體可以查看data-必須是函數(shù)

我們返回的是this._vm而不是this
我們這里做了兩步操作,首先將this與data進行合并,再將整個對象進行監(jiān)聽,并賦值到_vm屬性上。

這樣,我們通過new W()初始化的實例,則可以訪問到我們的data屬性及方法,并且具有數(shù)據(jù)驅(qū)動的特性了。

更新DOM

我們已經(jīng)為watcher的回調(diào)添加了dom更新的事件,我們只要在這里執(zhí)行render函數(shù),并掛載到對應(yīng)的el上即可:

const { render, el } = this._config
const targetEl = document.querySelector(el)
const renderDom = render()

targetEl.innerHTML = ""
targetEl.appendChild(renderDom)
綁定this

我們會發(fā)現(xiàn),我們在config的render函數(shù)中,使用了this.msg來訪問data的msg屬性,因此我們需要實現(xiàn)在各組件中,通過this可以訪問到本實例的特性。我猜你已經(jīng)想到了,我們可以使用bind,call和apply來實現(xiàn)它:

/**
 * 為所有的函數(shù)綁定this
 */
bindVM () {
  const { _config } = this

  for(let key of Object.keys(_config)) {
    const val = _config[key]
    if (typeof(val) === "function") {
      _config[key] = val.bind(this._vm)
    }
  }
}
測試

簡單的架子拼接完成,我們來進行測試下我們的成果,我們需要實現(xiàn)兩點功能:

可以按照我們的render函數(shù)正常掛載,并可訪問到data上的數(shù)據(jù)

通過對實例進行修改,修改會自動更新到節(jié)點上

代碼:

const vm = new W({
  el: "body",
  data () {
    return {
      msg: "hello world"
    }
  },
  render () {
    return dom.div({
      class: "wrap"
    },
      dom.a({
        href: "http://www.#"
      }, this.msg)
    )
  }
})

// 測試修改vm
setInterval(_ => {
  vm.msg = "hello world =>>>" + new Date()
}, 1000)

結(jié)果:

最基本的功能已經(jīng)實現(xiàn)啦!

結(jié)語

本次我們只實現(xiàn)了最最最簡單的數(shù)據(jù)驅(qū)動功能,后續(xù)還有很多需要進行處理,我們也會對其一一進行梳理和實現(xiàn),大家可以持續(xù)關(guān)注下,例如:

數(shù)組變動監(jiān)聽

object深度監(jiān)聽

更新隊列

render過程中記錄僅相關(guān)的屬性

模板渲染

v-model

...等等

相關(guān)代碼放在github,會持續(xù)更新,歡迎賞個star。

敬請期待!

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

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/51052.html

相關(guān)文章

  • 使用ES6特性實現(xiàn)簡單MVVM1)--數(shù)據(jù)驅(qū)動

    摘要:嘗試使用新特性,自己來實現(xiàn)一個及的各種特性。我們可以利用這個特性來實現(xiàn)對數(shù)據(jù)的監(jiān)聽結(jié)果簡單的操作我們已經(jīng)可以對簡單的數(shù)據(jù)操作進行監(jiān)聽雖然還有各種問題,接下來,我們只要在監(jiān)聽到后進行數(shù)據(jù)操作即可。 嘗試使用es6新特性,自己來實現(xiàn)一個mvvm及vue的各種特性。相關(guān)代碼放在github,會持續(xù)更新,歡迎賞個star。本篇文章為系列文章的第一篇,會比較容易理解,后續(xù)會持續(xù)更新后面的記錄。文...

    ispring 評論0 收藏0
  • Vue面試中,經(jīng)常會被問到面試題/Vue知識點整理

    摘要:可以在該鉤子中進一步地更改狀態(tài),不會觸發(fā)附加的重渲染過程。我工作中只用到,對和不怎么熟與的區(qū)別相同點都支持指令內(nèi)置指令和自定義指令都支持過濾器內(nèi)置過濾器和自定義過濾器都支持雙向數(shù)據(jù)綁定都不支持低端瀏覽器。 看看面試題,只是為了查漏補缺,看看自己那些方面還不懂。切記不要以為背了面試題,就萬事大吉了,最好是理解背后的原理,這樣面試的時候才能侃侃而談。不然,稍微有水平的面試官一看就能看出,是...

    mengbo 評論0 收藏0
  • Regularjs是什么

    摘要:目前已經(jīng)在大大小小多個線上產(chǎn)品中使用了,也收集了一些有效的建議好了,該看下一個最簡單的組件長什么樣吧免費領(lǐng)取驗證碼內(nèi)容安全短信發(fā)送直播點播體驗包及云服務(wù)器等套餐更多網(wǎng)易技術(shù)產(chǎn)品運營經(jīng)驗分享請訪問網(wǎng)易云社區(qū)。文章來源網(wǎng)易云社區(qū) 本文由作者鄭海波授權(quán)網(wǎng)易云社區(qū)發(fā)布。 此文摘自regularjs的指南, 目前指南正在全面更新, 把老文檔的【接口/語法部分】統(tǒng)一放到了獨立的 Reference...

    seal_de 評論0 收藏0
  • 前端發(fā)展歷程

    摘要:前端的發(fā)展歷程什么是前端前端針對瀏覽器的開發(fā),代碼在瀏覽器運行后端針對服務(wù)器的開發(fā),代碼在服務(wù)器運行前端三劍客超文本標(biāo)記語言是構(gòu)成世界的基石。 前端的發(fā)展歷程 什么是前端 前端:針對瀏覽器的開發(fā),代碼在瀏覽器運行 后端:針對服務(wù)器的開發(fā),代碼在服務(wù)器運行 前端三劍客 HTML CSS JavaScript HTML HTML(超文本標(biāo)記語言——HyperText Markup ...

    劉明 評論0 收藏0
  • 前端面試題總結(jié)——VUE(持續(xù)更中)

    摘要:前端面試題總結(jié)持續(xù)更新中是哪個組件的屬性模塊的組件。都提供合理的鉤子函數(shù),可以讓開發(fā)者定制化地去處理需求。 前端面試題總結(jié)——VUE(持續(xù)更新中) 1.active-class是哪個組件的屬性? vue-router模塊的router-link組件。 2.嵌套路由怎么定義? 在 VueRouter 的參數(shù)中使用 children 配置,這樣就可以很好的實現(xiàn)路由嵌套。 //引入兩個組件 ...

    SimonMa 評論0 收藏0

發(fā)表評論

0條評論

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