- Vue对data做了什么
- Vue对data做的事情总结
- Vue的data存在bug
- data中数组变异
- 新增key总结
-曾老湿, 江湖人称曾老大。
-多年互联网运维工作经验,曾负责过大规模集群架构自动化运维管理工作。 -擅长Web集群架构与自动化运维,曾负责国内某大型金融公司运维工作。 -devops项目经理兼DBA。 -开发过一套自动化运维平台(功能如下): 1)整合了各个公有云API,自主创建云主机。 2)ELK自动化收集日志功能。 3)Saltstack自动化运维统一配置管理工具。 4)Git、Jenkins自动化代码上线及自动化测试平台。 5)堡垒机,连接Linux、Windows平台及日志审计。 6)SQL执行及审批流程。 7)慢查询日志分析web界面。
Vue对data做了什么
小实验 |
---|
data变了
codesandbox示例代码:TP
代码语言:javascript复制import Vue from "vue/dist/vue.js";
Vue.config.productionTip = false;
const myData = {
n:0
}
console.log(myData)
const vm = new Vue({
data:myData,
template:`
<div>
{{n}}
<button @click="add">
10
</button>
</div>
`,
methods:{
add(){
this.n = 10
}
}
}).$mount("#app")
setTimeout(()=>{
myData.n =10
console.log(myData)
console.log(vm)
},3000)
我们总共打印了两次myData
第一次打印是{n:0}
然后3秒钟之后再打印一次,应该是{n:10}对吧

myData变成了一个奇奇怪怪的东西
一开始{n:0},传给new Vue之后立马变成了{n:(...)}
{n:(...)}这是个什么玩意?为什么表现和{n:0}一致?
我们需要先学习一下ES6的getter
和setter
codesandbox示例代码:TP
代码语言:javascript复制let obj0 = {
姓: "邓",
名: "紫琪",
age: 18
}
// 需求一:得到姓名
let obj1 = {
姓: "邓",
名: "紫琪",
姓名(){
return this.姓 this.名
},
age: 18
}
console.log('需求一:' obj1.姓名())
// 姓名后面的括号能删除么?
// 不能,因为他是一个函数
// 如何去掉括号?
// 需求二,姓名不要括号也能得出值
let obj2 = {
姓: "邓",
名: "紫琪",
get 姓名(){
return this.姓 this.名
},
age: 18
}
console.log('需求二:' obj2.姓名)
// 总结:getter就是这样用的,不加括号的函数,仅此而已
// 需求三,姓名可以被写
let obj3 = {
姓: "邓",
名: "紫琪",
get 姓名(){
return this.姓 this.名
},
set 姓名(xxx){
this.姓 = xxx[0]
this.名 = xxx.slice(1)
},
age: 18
}
obj3.姓名 = "曾老湿"
console.log(`需求三:姓:${obj3.姓},名:${obj3.名}`)
//总结:setter就是这样赢的。 用 = xxx 触发set函数

我们把obj3打印出来,看看结果
代码语言:javascript复制console.log(obj3)

可以发现... 有个姓名:(...) 和刚才的{n:(...)}是不是有点蛛丝马迹了。这个姓名,不是真实的姓名,浏览器,允许读写,所以模拟姓名的操作。
所以{n:(...)}并不存在这样的一个n,只是浏览器模拟n的操作。
那么为什么要{n:(...)}用这种方法呢?
我们又要了解一个新的知识Object.defineProperty
Object.defineProperty
继续做实验:TP
我们现在已经把obj3定义完了,那么我们调用的时候,如果想要get age,怎么办?我们不可能去修改定义的部分,如果这个功能是别的开发写好的代码给你的,你不可能改别人的代码吧?所以此时,我们需要用到Object.defineProperty
let obj0 = {
姓: "邓",
名: "紫琪",
age: 18
};
// 需求一:得到姓名
let obj1 = {
姓: "邓",
名: "紫琪",
姓名() {
return this.姓 this.名;
},
age: 18
};
console.log("需求一:" obj1.姓名());
// 姓名后面的括号能删除么?
// 不能,因为他是一个函数
// 如何去掉括号?
// 需求二,姓名不要括号也能得出值
let obj2 = {
姓: "邓",
名: "紫琪",
get 姓名() {
return this.姓 this.名;
},
age: 18
};
console.log("需求二:" obj2.姓名);
// 总结:getter就是这样用的,不加括号的函数,仅此而已
// 需求三,姓名可以被写
let obj3 = {
姓: "邓",
名: "紫琪",
get 姓名() {
return this.姓 this.名;
},
set 姓名(xxx) {
this.姓 = xxx[0];
this.名 = xxx.slice(1);
},
age: 18
};
var _xxx = 0
Object.defineProperty(obj3,'xxx',{
get(){
return _xxx
},
set(value){
_xxx = value
}
})
obj3.姓名 = "曾老湿";
console.log(`需求三:姓:${obj3.姓},名:${obj3.名}`);
//总结:setter就是这样赢的。 用 = xxx 触发set函数
这就是Object.defineProperty,如果已经定义好的对象,你想给它添加虚拟属性,那么就使用这种方法。
Vue对data做的事情总结
Object.define.Property |
---|
可以 给对象添加属性value 可以 给对象添加getter/setter getter/setter用于对属性的读写进行监控
代理(设计模式) |
---|
对myData对象 的属性读写,全权由另一个对象vm负责 那么vm就是myData的代理 比如myData.n不用,偏要用vm.n来操作myData.n
vm=new Vue({data:myData}) |
---|
1.会让vm称为myData的代理(proxy) 2.会对myData的所有属性进行监控
为什么要监控,为了防止世界被破坏,为了守护世界的和平...对不起,乱入了,为了防止myData的属性变了,vm不知道
vm知道了又如何?知道属性变了就可以调用render(data)呀!!!UI=render(data)
Vue的data存在bug
数据响应式 |
---|
什么是数据响应式?
我打你一拳,你会喊疼,那你就是响应式。 若一个物体能对外界的刺激做出反应,它就是响应式
Vue的data是响应式
const vm = new Vue({data:{n:0}}) 我如果修改vm.n,那么UI中的n就会来响应我 Vue2通过Object.defineProperty来是想数据响应式
响应式网页是啥? 如果我改变窗口的大小,网页内容就会做出响应,那就是响应式网页。 比如:https://www.smashingmagazine.com/ 但是要注意,用户没事不会拖动网页大小。
data的bug |
---|
Object.defineProperty的问题 Object.defineProperty(obj,'n',{...}) 必须要有一个'n',才能监听&代理obj.n对吧 如果前端开发者比较"睿智",没有给n怎么办?
示例一:Vue会给出一个警告 TP
代码语言:javascript复制import Vue from "vue/dist/vue.js";
Vue.config.productionTip = false;
new Vue({
data: {},
template: `
<div>{{n}}</div>
`,
}).$mount("#app");

示例二:Vue只会检查第一层属性,我们有方法绕过他 TP
代码语言:javascript复制import Vue from "vue/dist/vue.js";
Vue.config.productionTip = false;
new Vue({
data:{
obj:{
a:0
}
},
template:`
<div>
{{obj.b}}
<button @click="setB">set b</button>
</div>
`,
methods:{
setB(){
this.obj.b = 1 //请问,页面会显示1嘛?
}
}
}).$mount("#app")
这样一来,vue就没有警告了。

此时如果我店家set b,请问图中会显示1嘛? 答案是:不会 因为,Vue再牛逼,它也不可能监听一个不存在的字符串 ,obj.b 一开始就不存在,如何监听?不能把所有字符串都监听一遍吧?
解决办法 1.那我把key都声明好,后面不再加属性不就行了 2.使用Vue.set或者this.$set
代码语言:javascript复制import Vue from "vue/dist/vue.js";
Vue.config.productionTip = false;
new Vue({
data: {
obj: {
a: 0
}
},
template: `
<div>
{{obj.b}}
<button @click="setB">set b</button>
</div>
`,
methods: {
setB() {
//this.obj.b = 1; //请问,页面会显示1嘛?
Vue.set(this.obj,'b',1)
this.$set(this.obj,'b',1)
}
}
}).$mount("#app");

Vue.set 和 this.$set
作用: 1.新增key 2.自动创建代理和监听(如果没创建就自动创建) 3.触发UI更新(但不会立刻更新,异步更新)
data中数组变异
data中有数组怎么办? |
---|
你没法提前声明所有key 示例1:数组的长度可以一直增加,下标就是key 你没有办法提前把数组的key都声明出来 Vue也不能检测对你新增了下标 难道每次改数组都要用Vue.set或者this.$set
代码语言:javascript复制import Vue from "vue/dist/vue.js";
Vue.config.productionTip = false;
new Vue({
data: {
array: ["a", "b", "c"]
},
template: `
<div>
{{array}}
<button @click="setD">set d</button>
</div>
`,
methods: {
setD() {
this.array[3] = "d"; //请问页面会显示d嘛?
//等下,你为什么不用this.array.puysh('d')
}
}
}).$mount("#app");

页面中,会显示d嘛?答案是不会,因为这个数组就相当于是 array:{0:'a',1:'b',2:'c'}
,你只设置了0,1,2所以Vue监听不到3,那这个时候我们用set可不可以呢?
import Vue from "vue/dist/vue.js";
Vue.config.productionTip = false;
new Vue({
data: {
array: ["a", "b", "c"]
},
template: `
<div>
{{array}}
<button @click="setD">set d</button>
</div>
`,
methods: {
setD() {
// this.array[3] = "d"; //请问页面会显示d嘛?
this.$set(this.array,3,'d')
//等下,你为什么不用this.array.puysh('d')
}
}
}).$mount("#app");

尤雨溪的做法
篡改数组的API,见文档中异更方法章节

这7个API都会被Vue篡改,调用后会更新UI
代码语言:javascript复制import Vue from "vue/dist/vue.js";
Vue.config.productionTip = false;
new Vue({
data: {
array: ["a", "b", "c"]
},
template: `
<div>
{{array}}
<button @click="setD">set d</button>
</div>
`,
methods: {
setD() {
// this.array[3] = "d"; //请问页面会显示d嘛?
// this.$set(this.array,3,'d')
//等下,你为什么不用this.array.puysh('d')
this.array.push('d')
}
}
}).$mount("#app");

怎么篡改的?ES6写法
代码语言:javascript复制class VueArray extends Array{
push(...args){
const oldLength = this.length //this就是当前数组
super.push(...args)
console.log('你push了')
for(let i = oldLength;i<this.length;i ){
Vue.set(this,i,this[i]) //将每个新增的key都告诉Vue
}
}
}
注意:者不代表Vue的真实实现,此代码仅用于教学目的,实际上我没看过相关源码
新增key总结
对象新增的key |
---|
Vue没有办法实现监听和代理 要使用set来新增key,创建监听和代理,更新UI 最好前提把属性都写出来,不要新增key 但数组做不到"不新增key"
数组新增的key |
---|
也可以使用set来新增key,更新UI(set新增key不会创建监听和代理) 不过尤雨溪篡改了7个API方便你对数组进行增删 这7个API会自动处理监听和代理,并更新UI