竟然已經耗費了六天在講 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) {}
}
這部分的應用情境很有趣,但也花費了不少時間在弄懂,所以導致其他的應用情境要等到明天繼續研究了。