下面代码两次打印出myData,会发现Vue把myData转化为了getter/setter。这是因为Vue要对数据进行监听和代理,即使是引用配置选项外的变量,也不应该逃过监听。
另外,如果配置选项一开始没有设置的变量,Vue是不会监听的。因此Vue提供了方法Vue.set()和vm.$set()。对于数组,Vue改变了数组的原型链,在第一层原型中增加了8个新方法,所以可以直接通过vm.array.push()增加变量。
let myData ={n:1}
console.dir(myData)
new Vue({
data:myData,
template:...,
el:...
})
console.dir(myData)
下面代码是实现的思路,可以防止n被篡改为负数,即使数据引用变量
// 首先,把数据存放在出入作为实参的匿名对象上,这样就只能通过代理访问
let data1 = proxy1({data:{n:1}})
function proxy1({data}){
let obj = {}
Object.defineProperty(obj,'n', {get(){ return data.n},set(value){if(value>0) data.n=value}})
return obj
}
console.dir(data1.n);
// 但是,如果传入的不是匿名参数而是引用外部变量,那么还是可以篡改的,如下
let dataSource1 = {n:1}
let data2 = proxy2({data:dataSource1})
function proxy2({data}){
let obj = {}
Object.defineProperty(obj,'n', {get(){return data.n},set(value){if(value>0) data.n=value}})
return obj
}
dataSource1.n=-1
console.dir(data2.n);
// 所以解决方法是,在代理前调换数据源,实现监听
let dataSource2 = {n:1}
let data3 = proxy3({data:dataSource2})
function proxy3({data}){
let xxx =data.n
Object.defineProperty(data,'n',
{ get(){return xxx},set(value){if(value>0) xxx=value}})// 监听部分,新的n覆盖旧的n
let obj = {}
Object.defineProperty(obj,'n', {get(){return data.n},set(value){if(value>0) data.n=value}})
return obj
}
dataSource2.n=-1
data3.n =4
console.dir(data3.n);