前言
当我们把一个数据传给 vue 实例 data 属性完成视图更新时, 经过一番操作发现并没有更新. console 打印发现数据只是 JavaScript 普通对象数据.
原因是因为 Vue 想要完成视图响应必须把 JavaScript 普通对象数据转为具有 getter/setter 的属性对象数据. 当调用 setter 被调用时 Vue 捕获数据从而完成响应组件更新. vue.js - 深入响应式原理
检测变化
允许创建视图响应的方式有:
在 Vue 实例 data 中添加初始属性值作为响应节点
通过 $set 方法动态添加响应节点
实例
首先我们准备两组数据,,jsData 和 vueData.
- const jsData = {
- ja: "张三",
- jb: "李四"
- }
- export default {
- data() {
- return {
- vueData: {
- va: "张三",
- vb: "李四"
- }
- }
- },
- mounted() {
- console.log(jsData, this.vueData);
- },
- // ...
- }
运行可以看出 jsData 不在 vue 实例内创建, 不具备 getter/setter,vueData 通过 vue 实例内 data 属性创建初始属性值从而具备 getter/setter.
不允许更新
视图监测不到变化的实例如下:
- export default {
- // ...
- mounted() {
- console.log(jsData, this.vueData);
- this.notAllow()
- },
- methods: {
- notAllow() {
- // demo 1
- this.vueData.newKeyA = "keyA";
- console.log(this.vueData);
- // demo 2
- // Object.assign(this.vueData, { newKeyA: "keyA" });
- // console.log(this.vueData);
- // demo 3
- // this.vueData = Object.assign(this.vueData, { newKeyA: "keyA" });
- // console.log(this.vueData);
- }
- }
- }
上述代码中都有一个问题, 在同一个引用类型中插入数据, 导致数据对象本身没有改变, 也就意味着 Vue 检查不到数据内存指向做更改, 这就会导致插入的只是不具备 getter/setter 的属性.
运行结果:
允许更新
- export default {
- mounted() {
- console.log(jsData, this.vueData);
- this.allow()
- },
- allow() {
- // demo 1
- this.vueData = {
- ...this.vueData,
- newKeyA: "keyA"
- }
- console.log(this.vueData);
- // demo 2
- // this.$set(this.vueData, "newKeyA", "keyA");
- // console.log(this.vueData);
- }
- }
上述 demo1 的方式是替换一个内存指向完成数据变化. demo2 是通过 Vue 实例提供的 $set 方法, 在不改变内指向的同时, 添加一个的具备 getter/setter 属性做了补充.
运行结果:
例子
本文提供 demo 见: GitHub
来源: https://juejin.im/post/5c46dd43e51d4567680e3bcd