Vue-数据响应式

  • 一个物体能对外界的刺激作出反应,那他就是响应式的
    1. const vm = new Vue({data:{n:0}})
    2. 我如果修改 vm.n ,那么UI中的 n 就回来响应我
    3. Vue通过Object.defineProperty来实现数据响应式
  • Vue通过Object.defineProperty的 getter/setter 对收集的依赖项进行监听,在属性被访问和修改时通知变化,进而更新视图数据

getter/setter

用于对属性的读写进行监控

getter

let obj1 = {
  姓: "高",
  名: "圆圆",
  姓名() {
    return this.姓 + this.名;
  },
  age: 18
};

console.log( obj1.姓名());
// 高圆圆
let obj2 = {
  姓: "高",
  名: "圆圆",
  get 姓名() {
    return this.姓 + this.名;
  },
  age: 18
};

console.log( obj2.姓名);
// 高圆圆
  • 对比代码,发现只是在姓名函数处添加了 get ,最后使用的时候就不再需要加 ()
  • getter 就是这样用的,不加括号的函数

setter

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 函数

Object.defineProperty

用于给对象添加新属性,也可以给对象添加 getter/setter

let obj = {}

Object.defineProperty(obj, 'x', {value: 1})

Object.defineProperty(obj, 'y', {
  get(){...}
  set(value){...}
})

监听与代理

  • 对 myData 对象的属性读写,全权由另一个对象 vm 负责
  • 那么 vm 就是 myData 的代理 (类似房东租房通过中介)
  • 比如 myData.n 不用,偏要用 vm.n 来操作 myData.n
    代码案例:bold-heyrovsky-8jcm2 - CodeSandbox

vm = new Vue({data: myData}) 就做了和上面代码类似的事情。

  1. vm 成为了 myData 的代理
  2. 会对 mydata 的所有属性进行监控

目的: 无论直接修改 myData.n 还是修改 vm.n,vm 都会收到通知,然后调用触发重新渲染

Vue 对 methods 和 computed 也有类似处理。

Object.defineProperty 的问题

Object.defineProperty(obj, 'n', {...}
必须有 'n' 才可以监听&代理 obj.n

//无 data.n
new Vue({
  data: {},
  template: `
    <div>{{n}}</div>
  `
}).$mount("#app");

无 data.n 或 data.n 的值为 undefined ,此时 n 被引用,不会有显示,控制台会报警告

//有 data.obj,但无 data.obj.n
new Vue({
  data: {
    obj: {
      a: 0 // obj.a 会被 Vue 监听 & 代理
    }
  },
  template: `
    <div>
      {{obj.b}}
      <button @click="setB">set b</button>
    </div>
  `,
  methods: {
    setB() {
      this.obj.b = 1; //不显示1
    }
  }
}).$mount("#app");

data.obj 中开始并没有 b,后面运行 this.obj.b = 1 并不会让 1 出现在页面中,因为 vm 没有监听&代理 data.obj.b

解决办法:

  1. 在开始就定义好 data.obj.n = undefined
  2. 使用 Vue.set 或者 this.$set
    一个特例:
//html
<div id="app">
    <span class=span-a>
      {{obj.a}} 
    </span>
    <span class=span-b>
      {{obj.b}}
    </span>
  </div>
js

//js
var app = new Vue({
  el: '#app',
  data: {
    obj: {
      a: 'a',
    }
  },
})
app.obj.a = 'a2'
app.obj.b = 'b'

最终 span-a 中会显示 a2,span-b 中显示 b
这是因为视图更新是异步的,a1 变成 a2 时,Vue 监听到这个变化,并不会马上更新视图,而是创建一个视图更新任务到任务队列里。然后继续运行代码 app.obj.b = 'b'。视图更新时,Vue 会去做 diff,发现 a 和 b 都变了,于是去更新 span-a 和 span-b。

Vue.set 和 this.$set

作用:

  1. 新增key
  2. 自动创建代理和监听(如果没有创建过)
  3. 触发UI更新(不会立即更新)
this.$set(this.object,'m',100)

变异方法

在数组中,数组的长度一直增加,下标就是key,没办法提前声明所有下标,难道每次改数组都要Vue.set 或者 this.$set?

new Vue({
  data: {
    array: ["a", "b", "c"]
  },
  template: `
    <div>
      {{array}}
      <button @click="setD">set d</button>
    </div>
  `,
  methods: {
    setD() {
      this.array[3] = "d"; //不显示d
    }
  }
}).$mount("#app");

使用变异方法
push()、pop()、shift()、unshift()、splice()、sort()、reverse()

new Vue({
  data: {
    array: ["a", "b", "c"]
  },
  template: `
    <div>
      {{array}}
      <button @click="setD">set d</button>
    </div>
  `,
  methods: {
    setD() {
      this.array.push('d'); //修改后的push可完成我们想要的操作
    }
  }
}).$mount("#app");
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,744评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,505评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,105评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,242评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,269评论 6 389
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,215评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,096评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,939评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,354评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,573评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,745评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,448评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,048评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,683评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,838评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,776评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,652评论 2 354

推荐阅读更多精彩内容

  • Vue到底对 data 做了什么? 我们有如上的代码,其中 data 中的的数据引用外面的变量 myData; 我...
    MrTon_1965阅读 234评论 0 0
  • 写在前面 我相信很多同学对Vue的数据响应式是通过Vue.js文档[https://link.zhihu.com/...
    luci_dity阅读 305评论 0 0
  • Vue数据响应式主要研究的是 Vue 构造选项中 data 属性的特性 深入响应式 官方文档 网址: http...
    雨溪滩阅读 517评论 0 0
  • vue响应式 1.data变化 1.1 尝试在外部改变data的值 2秒后myData.n也变为了100,页面上也...
    西域战神阅读 230评论 0 1
  • vue是怎么通过data对数据进行改写的 ps.console.log(obj) 可以看出姓名不是一个真实的属性,...
    小芬芬007阅读 173评论 0 2