vue响应式

操作数据,页面会随之改变。

实现原理:

Vue在组件和实例初始化的时候,会将data里的数据进行数据劫持(object.definepropty对数据做处理)。被劫持后的数据会有两个属性:一个叫getter,一个叫setter。[在生成vue实例时,为对传入的data进行遍历,使用Object.defineProperty把这些属性转为getter/setter.]

getter是使用数据的时候触发,setter是在修改数据的时候触发,修改数据的时候触发setter,同时也触发了底层的watcher监听,通知dom修改刷新。

每个vue实例都有一个watcher实例,它会在实例渲染时记录这些属性,并在setter触发时重新渲染。

export default {
  name: "test",
  components: {},
  data() {
    return {
      data0:{
        name:"yyp"
      }
    }
  },
  methods: { },
  mounted: function () {
    let data1 ={name:1};
    console.log("初始化时就定义的的name,会有getter和setter属性:",this.data0);
    console.log("初始化后新定义的name,没有getter和setter属性:",data1);
    Object.defineProperty(data1,'age',{
      get(){},
      set(){}
    });
    console.log("被Object.defineProperty处理过的data,age属性有getter和setter属性:",data1)
  },
  created(){ }
}

三次console.log的结果如下:


image.png

Object.definepropty

是es5中的一个方法,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。处理数据,给数据赋予getter和setter。
正常情况下,这两个方法都不会触发,当我们给数据赋值和改变值的情况下会执行这两个函数。

let middle = 6
Object.defineProperty(data,'age',{
  get(){
    console.log('获取age')
    return middle
  },
  set(parmas){
    //参数就是赋值的数据
    console.log('修改age数据',parmas)
    middle = parmas
  }
})
// 取值的时候触发getter
console.log(data.age)
//赋值的时候触发setter
data.age = 15
console.log(data.age)

Vue中数据变页面一定变嘛?

先来看一个小例子:

<div id ='app'>
    {{user}}
    <hr>  
    <button @click='changeName'>changeName</button>
</div>
<script>
new Vue({
  el:'#app',
  data:{
    user:{
      age:15
    }
  },
  methods: {
    changeName(){
      this.user.name = '韩梅梅'
      console.log(this.user)
    }
  },
})
</script>

这时候点按钮,发现改变不了name的值,所以打开控制看一下


image.png

我们会发现只有age有getter和setter,name没有,Vue 无法检测到对象属性的添加或删除,所以没法进行响应式改变数据。
Vue 不允许动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, propertyName, value)方法向嵌套对象添加响应式属性。

两种情况新添加的属性都有没有getter和setter,数据变页面也不变:
  1. 对象数据的添加
  2. 数组长度的改变
    解决方式:动态的往里面添加数据,使用this.$set方法
methods: {
    changeName(){
      // this.user.name = '韩梅梅'
      // set 将数据用 object.defainPropty进行处理 添加getter和setter
      this.$set(this.user,'name','韩梅梅')
      console.log(this.user)
    }
  }

这样我们就能在页面上看到新增的属性


image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容