iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 7
0
Modern Web

我或許沒那麼懂 Web系列 第 7

JS Object.defineProperty(): (6) 相關應用

竟然已經耗費了六天在講 Object.defineProperty() 與其相關方法。主要是每天能特別研究的時間不多,不過儘管如此,每天研究一點並起寫點心得的感覺也很棒。

這篇主要是研究 Vue.js 怎麼使用 Object.defineProperty() 的部分情境,其中透過 Object.defineProperty() 實作資料雙向繫結的部分,因為會比較耗費時間研究,~~每次想寫時總會怕超過隔夜而擱著,但總不能這樣拖下去。所以決定在今日睡前把它寫完,但先發文佔著避免超過今日期限。~~所以留待明天去研究。今天先針對其中幾個情境做舉例:

使用其他模組的方法作為本物件的屬性

// src/core/index.js
import { isServerRendering } from 'core/util/env'

Object.defineProperty(Vue.prototype, '$isServer', {
  get: isServerRendering
})

// Usage:
//   Vue.$isServer

將其他模組的方法作為本物件的方法

// src/core/index.js
import { FunctionalRenderContext } from 'core/vdom/create-functional-component'

// expose FunctionalRenderContext for ssr runtime helper installation
Object.defineProperty(Vue, 'FunctionalRenderContext', {
  value: FunctionalRenderContext
})

// Usage:
//   Vue.FunctionalRenderContext()

作為一個透過計算得到值的屬性

// src/core/index.js
Object.defineProperty(Vue.prototype, '$ssrContext', {
  get () {
    return this.$vnode && this.$vnode.ssrContext
  }
})

設置警語

在非正式環境中提醒不要用取代這個屬性。

// src/core/global-api/index.js
import config from '../config'

export function initGlobalAPI (Vue: GlobalAPI) {
  // config
  const configDef = {}
  configDef.get = () => config
  if (process.env.NODE_ENV !== 'production') {
    configDef.set = () => {
      warn(
        'Do not replace the Vue.config object, set individual fields instead.'
      )
    }
  }
  Object.defineProperty(Vue, 'config', configDef)

	// .....
}

讓某個屬性被訪問時,改變別的值

這段程式碼是為了根據瀏覽器是否支援 passive,去決定要不要在 addEventListener 的選填參數中加上 {passive: true}。支援 passive 的瀏覽器會去訪問這個事件是否有 passive 屬性,藉這種方式先在一開始透過這段程式碼得知環境是否支援 passive,之後就可以在其他 addEventListener() 決定是否添加該參數。

// src/core/ulil/env.js
export let supportsPassive = false
if (inBrowser) {
  try {
    const opts = {}
    Object.defineProperty(opts, 'passive', ({
      get () {
        /* istanbul ignore next */
        supportsPassive = true
      }
    }: Object)) // https://github.com/facebook/flow/issues/285
    window.addEventListener('test-passive', null, opts)
  } catch (e) {}
}

這部分的應用情境很有趣,但也花費了不少時間在弄懂,所以導致其他的應用情境要等到明天繼續研究了。


上一篇
JS Object.defineProperty(): (5) 相關方法
下一篇
JS Object.defineProperty(): (7) Vue.js 資料繫結
系列文
我或許沒那麼懂 Web31

尚未有邦友留言

立即登入留言