1. No vue2, o sequestro de dados (monitoramento de eventos de alterações de dados) por meio de Object.defineProperty() realiza ligação de dados bidirecional
Object.defineProperty():
definição:
Object.defineProperty()
O método define uma nova propriedade diretamente em um objeto ou modifica uma propriedade existente de um objeto e retorna o objeto. (Meu próprio entendimento: por meio deste método, você pode adicionar propriedades a objetos ou modificar propriedades existentes e pode monitorar alterações nas propriedades)
No Vue2 podemos usar este método para usar o objeto de dados (dados)Object.defineProperty()进行监听data里面属性的变化进行双向数据绑定
2. Para o uso de Object.defineProperty(), consulte a documentação oficial do mdn, que não será explicada aqui. A documentação é a seguinte:
Object.defineProperty() - JavaScript | MDN
3. Use Object.defineProperty()
uma função para encapsular uma nova propriedade de um objeto e possa monitorar a mudança desta propriedade
function objAddProperty(obj, key,value){
// 返回处理完毕的对象
return Object.defineProperty(obj,key, {
set(val) {
//属性被赋值或者被修改时该函数自动执行,函数只有一个形参,
//形参值为该属性被修改后的最新值
console.log('obj.a被修改成...'+val)
value = val
},
get(){
//属性被访问时该函数自动执行
//属性的值即为该函数的返回值
console.log('obj.a被访问...')
return value
}
})
}
//声明一个对象
let obj={}
// 为对象新增属性并进行监听该属性的变化
obj= objAddProperty(obj, 'a',1)
console.log(obj);
obj.a=666
3. Use Object.defineProperty()
uma função para modificar as propriedades existentes do objeto e monitorar as alterações nas propriedades.Ele também pode realizar o sequestro das propriedades sem modificar as propriedades (sequestro de dados no Vue2, sequestro de alterações nas propriedades do objeto)
1. Sequestrar um atributo no objeto
function observeKey(obj, key) {
let value = obj[key];
Object.defineProperty(obj, key, {
set(val) {
//属性被赋值或者被修改时该函数自动执行,函数只有一个形参,
//形参值为该属性被修改后的最新值
console.log('属性被修改成...'+val)
value = val
},
get(){
//属性被访问时该函数自动执行
//属性的值即为该函数的返回值
console.log('属性被访问...')
return value
}
});
}
let obj = { a: 1 };
observeKey(obj, "a");
// 读取a,触发get函数
console.log(obj.a);
// 设置a,触发set函数
obj.a = 2;
2. Sequestre todas as propriedades do objeto
Na verdade, é percorrer as propriedades do objeto para monitorar
function observeObj(obj){
//循环对象的属性进行监听
for(let key in obj){
observeKey(obj,key)
}
}
function observeKey(obj, key) {
let value = obj[key];
Object.defineProperty(obj, key, {
set(val) {
//属性被赋值或者被修改时该函数自动执行,函数只有一个形参,
//形参值为该属性被修改后的最新值
console.log('属性被修改成...'+val)
value = val
},
get(){
//属性被访问时该函数自动执行
//属性的值即为该函数的返回值
console.log('属性被访问...')
return value
}
});
}
let obj = { a: 1,b:2 };
observeObj(obj)
// 读取a,触发get函数
console.log(obj.a);
// 设置a,触发set函数
obj.a = 2;
// 读取b,触发get函数
console.log(obj.b);
// 设置a,触发set函数
obj.b = 3;
Nota: Há uma falha acima, ou seja, quando o valor do atributo também é um objeto, o valor do atributo não pode ser sequestrado, como {a:1,c:{b:1}}
Solução: Determine o tipo de dados do valor do atributo do objeto e determine se a recursão é necessária
function observeObj(obj){
//循环对象的属性进行监听
for(let key in obj){
if(obj[key] instanceof Object){
observeObj(obj[key])
}
else{
observeKey(obj,key)
}
}
}
function observeKey(obj, key) {
let value = obj[key];
Object.defineProperty(obj, key, {
set(val) {
//属性被赋值或者被修改时该函数自动执行,函数只有一个形参,
//形参值为该属性被修改后的最新值
console.log('属性被修改成...'+val)
value = val
},
get(){
//属性被访问时该函数自动执行
//属性的值即为该函数的返回值
console.log('属性被访问...')
return value
}
});
}
let obj = { a: 1,c:{b:2} };
observeObj(obj)
// 读取a,触发get函数
console.log(obj.a);
// 设置a,触发set函数
obj.a = 2;
// 读取b,触发get函数
console.log(obj.c.b);
// 设置a,触发set函数
obj.c.b = 3;
Observe que a função observeObj não pode sequestrar as novas propriedades do objeto, mas apenas sequestrar as propriedades existentes do objeto.
Quatro,Object.defineProperty()的缺陷
1. O monitoramento aprofundado requer recursão única (alto consumo de desempenho)
2. Não é possível monitorar as propriedades adicionadas e excluídas do objeto
Cinco, simulação simples de ligação de dados bidirecional
Nota: Se você não entende this._name, você usará Object.definePropety para relatar um erro Tamanho máximo da pilha de chamadas excedido
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div class="app">
<input type="text">
<p><span></span></p>
<p><button>点击修改data数据模型的name值为马云</button></p>
</div>
<script>
const button=document.querySelector("button")
const span=document.querySelector("span")
const input =document.querySelector('input')
const data={
name:'hsq'
}
input.value=data.name
span.innerText=`data数据模型的值为${data.name}`
Object.defineProperty(data,'name',{
get(){
return this._name
},
set(newValue){
input.value=newValue
this._name=newValue
span.innerText=`data数据模型的值为${newValue}`
console.log('data数据模型name属性值',newValue);
}
})
input.addEventListener("input",function(e){
console.log('输入框的值',e.target.value);
data.name=e.target.value
})
button.addEventListener("click",function(){
data.name='马云'
})
</script>
</body>
</html>