データ応答式の基礎
30025 ワード
Object.defineProperty()
Object.defineProperty()メソッドは、オブジェクトに直接新しい属性を定義したり、オブジェクトの既存の属性を変更したりして、このオブジェクトに戻ります.三つのパラメータを受信します. obj:新しい属性を定義する必要があるオブジェクト prop:定義または修正される属性名 descriptor:定義または修正される属性の記述子は、データ・ディスクリプタとアクセス・ディスクリプタに分類される. データ記述子:すなわち、descriptorは具体的な値であり、またはvalue属性を持つオブジェクトである: アクセスディスクリプタ:属性のgetterとsetter関数 です. configrable:この属性のconfigrableのキー値がtrueである場合にのみ、この属性の記述子は変更され、対応するオブジェクトから削除されることができる.デフォルトはfalseです enumerable:この属性のenumerableキーがtrueである場合にのみ、この属性はオブジェクトの列挙属性に現れる.デフォルトはfalseですObject.defineProperty()方法の詳細については、ここをクリックしてください.
実現データ応答式 Objectの応答式 最初に簡単なページを実現します.
この中のobj.fooは一秒ごとに変化します.setter関数を触発して、setter関数の中でビューを更新できます.ここで簡単なページを実現しました. defineReactive.js 以上はObjectタイプの変数に応答して処理します.Arayタイプに対しては、別の処理をする必要があります.
jsでは、元の配列を変える方法は7つしかありません.push()、pop()、shift()、unshift()、sort()、reverse()、splice()です.だから、これらの方法を書き換えて、更新を知らせる機能を持たせるだけで、配列の応答式を実現することができます.
ここをクリックしてObject.assignの方法について詳しく紹介します.
Object.defineProperty()メソッドは、オブジェクトに直接新しい属性を定義したり、オブジェクトの既存の属性を変更したりして、このオブジェクトに戻ります.三つのパラメータを受信します.
Object.defineProperty(obj, 'data', 'abc')
Object.defineProperty(obj, 'data', {
value: 'abc',
writable: false
})
let value
Object.defineProperty(obj, 'data', {
get () {
return obj.data
},
set (newVal) {
value = newVal
}
})
また、2つの記述子が共有する2つのキーがあります.実現データ応答式
この中のobj.fooは一秒ごとに変化します.setter関数を触発して、setter関数の中でビューを更新できます.ここで簡単なページを実現しました.
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Documenttitle>
head>
<body>
<div id="app">div>
<script>
const app = document.getElementById('app')
function definedReactive(obj, key, val) {
Object.defineProperty(obj, key, {
get() {
console.log('get', key, val)
return val
},
set(newVal) {
if (newVal !== val) {
console.log('set', key, newVal)
val = newVal
//
update()
}
}
})
}
function update() {
app.innerText = obj.foo
}
const obj = {
}
definedReactive(obj, 'foo', '')
obj.foo = new Date().toLocaleTimeString()
setInterval(() => {
obj.foo = new Date().toLocaleTimeString()
}, 1000)
script>
body>
html>
しかし、このOB jの構造はとても簡単で、一つのkey、一つのvalue、それはobj={foo]、baz:'baz}のように複数のkeyの対象があります.このように処理すると明らかに足りなくなります.各keyを遍歴して、各keyに対して応答式の処理を行う必要があります.// key
function observe (obj) {
if (!obj || typeof obj !== 'object') {
return
}
Object.keys(obj).forEach(key => {
defineReactive(obj, key, obj[key])
})
}
// key getter setter
function defineReactive (obj, key, val) {
Object.defineProperty(obj, key, {
get () {
console.log('get', key, val)
return val
},
set (newVal) {
if (newVal !== val) {
console.log('set', key, newVal)
val = newVal
}
}
})
}
let obj = {
foo: 'foo', baz: 'baz' }
observe(obj)
obj.foo // get foo foo
obj.foo = 'fooooooooo' //set foo fooooooooo
もっと複雑なオブジェクトに対しては、Obj={foo],baz:{a:1}を再帰的に使って応答式の処理を完了する必要があります.// key
function observe (obj) {
// obj ,
if (!obj || typeof obj !== 'object') {
return
}
Object.keys(obj).forEach(key => {
defineReactive(obj, key, obj[key])
})
}
// key getter setter
function defineReactive (obj, key, val) {
// val object, , observe() ,
observe(val)
Object.defineProperty(obj, key, {
get () {
console.log('get', key, val)
return val
},
set (newVal) {
if (newVal !== val) {
// newval,
observe(newVal)
console.log('set', key, newVal)
val = newVal
}
}
})
}
let obj = {
foo: 'foo', bar: 'bar', baz: {
a: 1 } }
observe(obj)
obj.baz.a // get baz { a: [Getter/Setter] } get a 1
obj.baz.a = {
b: 1 } // get baz { a: [Getter/Setter] } set a { b: [Getter/Setter] }
jsでは、元の配列を変える方法は7つしかありません.push()、pop()、shift()、unshift()、sort()、reverse()、splice()です.だから、これらの方法を書き換えて、更新を知らせる機能を持たせるだけで、配列の応答式を実現することができます.
// 1、
// 2、 ,
// 3、
// 4、
const arrayProto = Array.prototype
const newProto = Object.create(arrayProto)
const methods = ['push', 'pop', 'shift', 'unshift', 'sort', 'reverse', 'splice']
methods.forEach(method => {
newProto[method] = function () {
//
arrayProto[method].apply(this, arguments)
// , arr
observe(this)
console.log(method + ' !')
}
})
元のobserve関数を修正します.// key
function observe (obj) {
// object,
if (!obj || typeof obj !== 'object') {
return
}
// obj
if (Array.isArray(obj)) {
// arr , arrayProto
obj.__proto__ = Object.assign({
}, arrayProto, newProto)
// , object,
for (let i = 0; i < obj.length; i++) {
observe(obj[i])
}
} else {
Object.keys(obj).forEach(key => {
defineReactive(obj, key, obj[key])
})
}
}
テストをしますlet arr = [1, 2, 3]
observe(arr)
arr.push({
c: 4 }) // push !
console.log(arr[3]) // { c: [Getter/Setter] }
arr[3].c = 5 // set c 5
ここをクリックしてObject.creat()の方法について詳しく紹介します.ここをクリックしてObject.assignの方法について詳しく紹介します.