Last active
November 18, 2019 06:27
-
-
Save ryo-utsunomiya/b9e1f6ad64047f0f7e219d8037852604 to your computer and use it in GitHub Desktop.
Object.definePropertyによるVue.jsのリアクティビティを紐解く ref: https://qiita.com/ryo511/items/b3e639be256d17e31422
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const vm = new Vue({ | |
el: '#app', | |
data: { | |
message: 'Hello, World', | |
} | |
}); | |
// ここではvm.messageはリアクティブ | |
vm.message = 'Hello, Vue.js!'; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function initData (vm: Component) { | |
let data = vm.$options.data | |
// (中略) | |
// observe data | |
observe(data, true /* asRootData */) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export function observe (value: any, asRootData: ?boolean): Observer | void { | |
// valueの型に応じた処理等があるが、諸々省略すると以下のようになる | |
return new Observer(value) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// リアクティビティに関係ある部分のみ抜粋 | |
export class Observer { | |
constructor (value: any) { | |
this.walk(value) | |
} | |
walk (obj: Object) { | |
const keys = Object.keys(obj) | |
for (let i = 0; i < keys.length; i++) { | |
defineReactive(obj, keys[i], obj[keys[i]]) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const data = { message: 'Hello, World' }; | |
defineRaactive(data, 'message', 'Hello, World'); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Define a reactive property on an Object. | |
*/ | |
export function defineReactive ( | |
obj: Object, | |
key: string, | |
val: any, | |
customSetter?: ?Function, | |
shallow?: boolean | |
) { | |
const dep = new Dep() | |
const property = Object.getOwnPropertyDescriptor(obj, key) | |
if (property && property.configurable === false) { | |
return | |
} | |
// cater for pre-defined getter/setters | |
const getter = property && property.get | |
const setter = property && property.set | |
let childOb = !shallow && observe(val) | |
Object.defineProperty(obj, key, { | |
enumerable: true, | |
configurable: true, | |
get: function reactiveGetter () { | |
const value = getter ? getter.call(obj) : val | |
if (Dep.target) { | |
dep.depend() | |
if (childOb) { | |
childOb.dep.depend() | |
} | |
if (Array.isArray(value)) { | |
dependArray(value) | |
} | |
} | |
return value | |
}, | |
set: function reactiveSetter (newVal) { | |
const value = getter ? getter.call(obj) : val | |
/* eslint-disable no-self-compare */ | |
if (newVal === value || (newVal !== newVal && value !== value)) { | |
return | |
} | |
/* eslint-enable no-self-compare */ | |
if (process.env.NODE_ENV !== 'production' && customSetter) { | |
customSetter() | |
} | |
if (setter) { | |
setter.call(obj, newVal) | |
} else { | |
val = newVal | |
} | |
childOb = !shallow && observe(newVal) | |
dep.notify() | |
} | |
}) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="ja"> | |
<head> | |
<meta charset="UTF-8"> | |
<title>defineProperty</title> | |
</head> | |
<body> | |
<h1 id="message"></h1> | |
<input type="text" id="input"> | |
<script> | |
// 下準備 | |
let message = 'Hello, World!'; | |
const data = {}; | |
const h1 = document.getElementById('message'); | |
const input = document.getElementById('input'); | |
h1.textContent = input.value = message; | |
// リアクティブプロパティの定義 | |
Object.defineProperty(data, 'message', { | |
get() { | |
return message; | |
}, | |
set(newVal) { | |
message = newVal; | |
h1.textContent = message; | |
} | |
}); | |
// 入力値をdataオブジェクトに伝播 | |
input.addEventListener('input', (ev) => { | |
data.message = ev.target.value; | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment