系列文章
数据响应式
小实验
getter/setter
Object.defineProperty
代理和监听
小结:vue对data做了什么
this.$set和Vue.set
数组的变异方法
小结:数组的变异方法
【Vue 全解 0】Vue 实例
【Vue 全解 1】构造选项 options 之 data
【Vue 全解 2】Vue 模板语法摘要
【Vue 全解 3】Vue 的 data 代理和数据响应式
【Vue 全解 4】options 之生命周期钩子(created、mounted、updated、destroyed)
【Vue 全解 5】options 之 DOM(el、template、render)
【Vue 全解 6】options 之资源(directive、filter、components)和修饰符
【Vue 全解 7】options 之组合(mixin、extends、provide/inject)
【Vue 全解 8】Vue 表单输入绑定 v-model
响应式就是做某种刺激作出反应,而数据响应式就是对数据的改变作出响应。在Vue中,数据的响应就是意味着数据变化,Vue就会进行一次render()渲染。以此来更新UI界面。--
个人理解
Vue的数组响应式
我如果修改
vm.n
,那么UI里面的n就会响应我,Vue2通过Object.defineProperty来实现数据响应式
const vm=new Vue({
/* 对n进行改变 */
data:{
n:0
}
})
data变了?
/* 引入完整Vue */
import Vue from "vue/dist/vue.js";
const myData={
n:0,
}
console.log(myData); //第一次打印myData
const vm=new Vue({
data:myData,
template:`
{
{n}}
`,
methods:{
add(){
this.n+=20;
}
}
}).$mount('#app');
/* 设置定时器,功能是让n值+10 */
setTimeout(() => {
myData.n+=10;
console.log(myData); //第二次打印myData
console.log(vm);
}, 3000);
程序运行结果截图--展示myData的变化
结论:一开始是{n:0},传给new Vue之后立马变成{n:(...)}。可以看见,两次打印出来的myData不一样!其中的原因是什么呢?接下来让我们了解一下ES6的新语法getter/setter,通过这个新语法,能让我们有进一步的认识。
getter
let obj={
姓:'高',
名:'圆圆',
age:18,
get 姓名(){
return this.姓+this.名;
}
}
console.log('姓名是:'+obj.姓名); //不用括号也能打印出姓名,这就是getter
setter
let obj={
姓:'高',
名:'圆圆',
age:18,
get 姓名(){
return this.姓+this.名;
},
set 姓名(name){
this.姓=name[0]; //只考虑第一个字为姓
this.名=name.substring(1);
}
};
obj.姓名='袁姗姗';
console.log(`姓名为:${
obj.姓名}`);
理解data为什么不一样了吗?并没有!我也是这样认为的,让我们接下来再研究一个东西吧!
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象,即在对象已经定义完成后,后面手动添加getter/setter时使用。
可以给对象添加属性
可以给对象添加getter/setter
getter/setter用于对属性的读写和监控
Object.defineProperty(obj,prop,descriptor)
obj是要修改的对象
prop是定义或修改的属性名或symbol
descriptor是要定义或修改的描述符
const object1 = {
};
let value=0;
Object.defineProperty(object1, 'property1', {
get (){
return value;
};
set (num){
value=num;
}
});
坑预警:get/set函数不需要写属性名,get返回时不能写this.property1,这样会造成死循环。一般是使用外部变量来做中间过渡
代理
例如对myData的对象的属性读写,全权由另外一个对象vm对象负责(Vue构造出来的),那么vm就是myData的代理。
监听
在Vue创建之后,data里面的值就会被Vue构造函数进行监听。只要监听的数据改变了。Vue就知道数据发生了改变,将会通过一系列操作去更新UI界面
使用代理的代码示例
let data={
proxy({
data:{
n:0}})};
/* 参数使用的为解构赋值 */
function proxy({
data}) {
let value=data.n;
Object.defeinProperty(data,'n',{
get (){
return value;
};
set (newValue){
if(newValue<0)return; //实现一个门槛,n值小于0就不能设置n值
value=newValue;
}
})
/* 上面的代码就会监听data */
const obj={
};
Object.defeinProperty(obj,'n',{
get (){
return data.n;
}
set (){
data.n=value;
}
})
}
console.log("data.n:"+data.n);
data.n=-1;
console.log("data.n:"+data.n+'设置-1失败!');
data.n=1;
console.log("data.n:"+data.n+"设置1成功!");
下面的代码看着眼熟吗?
let data5=proxy({
data:{
n:0
}})
const vm=new Vue({
data:{
n:0
}
})
终于将刚开始的议题解释了,接下来是我的个人小结
Vue 里面肯定是简化了原生的Object.defineProperty的。他们就是两个API:
this.$set和Vue.set
this.$set和Vue.set是等价的
新增key
自动创建代理和监听(前提是没有创建过)
触发UI更新(但并不会立即更新)
new Vue({
data:{
obj:{
n:0
}
},
methods:{
setVal(){
Vue.set(this.obj,'b',1); //添加obj里面一个为'b'的属性,值为1
this.$set(this.obj,'c',2); //添加obj里面一个为'c'的属性,值为2
}
}
})
那么问题来了,如果data里面有数组怎么办?数组里面直接定义好所有key后,你对数组作出增加key的操作Vue是不会知道的。
代码示例
import Vue from 'vue/dist/vue.js';
new Vue({
data:{
arr:['a','b','c'],
},
template:`
{
{arr}}
`,
methods:{
setD(){
// this.arr[3]='d'; //页面中并不会显示d
this.$set(arr,3,"d"); //这样设置是可以的。
this.arr.push('e'); //这样也可以设置。
}
}
})
注意:Vue里面数组的push、pop等操作并不是数组原生自带的。而是被Vue的作者尤雨溪篡改了的。就是在原型链上自己封装新的push、pop等常用函数API
Vue 没有办法事先监听和代理
使用this.$set或Vue.set来新增key,创建监听和代理,更新UI
最好提前将属性都写出来,不要新增key
可以用this.$set和Vue.set来新增key
Vue的作者对数组的常用API进行了篡改,我们可以直接进行操作。并且这些API会自动处理监听和代理。
数组新增key最好通过7个篡改的API