一、getter和setter
- 叫getter,在对象中写的话写get,后面接一个函数;
- 叫setter,在对象中写set;
- 在定义完一个对象后,你又想定义新的getter、setter该怎么办,这时候就要用
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
};
obj3.姓名 = '高媛媛'
console.log(`需求三:姓 ${obj3.姓},名 ${obj3.名}`) //需求三:姓 高,名 媛媛
// 总结:setter 就是这样用的。用 = xxx 触发 set 函数
var _yyy //它的作用只是用来过渡装yyy的值得
Object.defineProperty(obj3,'yyy',{
get(){
return _yyy
},
set(value){
_yyy = value
}
})
obj3.yyy = 127
console.log(obj3)
console.log(obj3.yyy)
//这里一定注意!!!通过Object.defineProperty定义的yyy是虚拟的,不存在的,所以一定要再定义一个变量来装它的值;

二、代理和监听
// 需求五:就算用户擅自修改 myData,也要拦截他
let myData5 = {n:0}
let data5 = proxy2({ data:myData5 }) // 括号里是匿名对象,无法访问
function proxy2({data}/* 解构赋值,别TM老问 */){
// 这里的 'n' 写死了,理论上应该遍历 data 的所有 key,这里做了简化
let value = data.n
// delete data.n 这里写不写这句话都无所谓,因为下面用defineProperty定义data.n时会覆盖原来的值
Object.defineProperty(data, 'n', {
get(){
return value
},
set(newValue){
if(newValue<0)return
value = newValue
}
})
// 就加了上面几句,这几句话会监听 data
const obj = {}
Object.defineProperty(obj, 'n', {
get(){
return data.n
},
set(value){
if(value<0)return//这句话多余了
data.n = value
}
})
return obj // obj 就是代理
}
// data3 就是 obj
console.log(`需求五:${data5.n}`)
myData5.n = -1
console.log(`需求五:${data5.n},设置为 -1 失败了`)
myData5.n = 1
console.log(`需求五:${data5.n},设置为 1 成功了`)
// 这代码看着眼熟吗?
// let data5 = proxy2({ data:myData5 })
// let vm = new Vue({data: myData})
// 现在我们可以说说 new Vue 做了什么了
- 对Vue做的任何修改我vm必须知道!!!
- 可参考图127,你只把data给
new Vue
了,Vue就会给你生成一些getter、setter等属性;为了就是时时刻刻监听你的变化,好随时把这些变化体现在视图上~Vue真是操碎了心呐
图127.png
如何来表述Vue的数据响应式?
它主要通过object.defineProperty()里的getter和setter函数对数据的属性进行监听,通过setter可以改变数据的值,在页面上通过getter可以访问到数据的值;但是它有一个缺点,一开始没有在vue的data中声明的属性,是无法进行监听,实现数据响应的,不过Vue给了一个解决办法,通过Vue.set()
来添加属性,可以实现数据响应;
想要了解更详细的可以参考:这里
三、Vue.set()和this.$set()
<div id="app">
<div>{{obj.b}}</div>
<button @click="setB">显示b</button>
</div>
new Vue({
data:{
obj:{
a:1
}
},
methods:{
setB(){
this.obj.b = 1 //这样是不会显示b的
// Vue.set(this.obj,'b',1)
// this.$set(this.obj,'b',1) 这两句都会让b显示
}
}
}).$mount('#app')
- Vue只会检查一层data,如果发现视图里出现了没有定义在data里的属性,那么会警告;但是!!!如果像上面那样,包一层obj,然后使用obj里未定义的属性,vue是不会警告的;
- vue有个特点,当它发现data里的属性值为undefined或null时,是不会显示在视图里的;
- 当obj里没有定义b,下面方法里直接用
this.obj.b = 1
,对b进行定义是没有用的,必须用Vue.set(this.obj,'b',1)
或this.$set(this.obj,'b',1)
来定义生成b(这两句的意思一模一样),给它赋值,然后才会触发视图,显示b; - 所以
Vue.set()
和this.$set()
的作用是:
①新增key;
②自动创建代理和监听(如果没有创建过的话);
③触发UI更新(但并不会立即更新);
四、Vue中数组的变异
<div id="app">
{{array}}
<button @click="add">添加d</button>
</div>
new Vue({
data:{
array: ['a','b','c']
},
methods:{
add(){
this.array[3] = 'd' //这样写是没有作用的
this.array.push('d')
}
}
}).$mount('#app')
-
this.array[3] = 'd'
这样写是没有作用的,因为data里的array可以看做是array:[ 0: 'a', 1: 'b', 2: 'c']
,它的小标【3】还没生成呢,所以this.array[3] = 'd'
这样写不行,当然可以用this.$set(this.array, 3 , 'd')
,但是duck不必这样写,因为vue帮你把数组组合变异生成了一些新特性呀,你就可以直接用this.array.push('d')
来添加新的值;下图就是Vue组合生成的7个特性~~
array.png
- this.$set 作用于数组时,并不会自动添加监听和代理,原因未知,只能问尤雨溪了;set 了之后再用 this.array[n] += 1 是不会触发 UI 更新的,所以永远不要用
this.array[n]
这种写法!!! -
使用 Vue 提供的数组变异 API 时,会自动添加监听和代理;
对象添加多个属性.png
延伸话题——Vue数组中的替换数组

-
filter()
:哪个元素能通过我给你设的条件,那我就把你筛选出去组成一个新数组,但是不会改变原有数组(好比司马家选出道组,你满足条件了,我就把你放到出道组里,残忍( Ĭ ^ Ĭ ))
网友评论