美文网首页
vue3响应式原理

vue3响应式原理

作者: TurnHug | 来源:发表于2023-10-17 11:06 被阅读0次

    vue3中,声明响应式状态有两种方式,ref和reactive
    ref用于基础类型(当 ref 的值是一个对象时,ref() 也会在内部调用reactive())
    reactive用于引用类型

    下面通过简单的例子实现这两种方法

    <template>
      <h2>vue3响应式原理</h2>
      <div>姓名:{{person.name}}</div>
      <div>年龄:<span id='age'>{{person.age}}</span></div>
      <div>点赞数:<span id='like'>{{like}}</span></div>
      <button @click='changeData'>更改年龄和点赞数</button>
    </template>
    <script setup>
    // import {ref, reactive} from 'vue'
    // 不使用官方方法,自己简单实现
    const ref = function (target) {
      let _value = target
      return {
        get value () {
          //处理访问逻辑
          return _value
        },
        set value (newValue) {
          //处理更新逻辑
          _value = newValue
          document.getElementById('like').innerHTML = _value
        }
      }
    }
    const reactive = function (target) {
      return new Proxy(target, {
        get: (obj, key) => {
          //处理访问逻辑
          return obj[key]
        },
        set: (obj, key, value) => {
          //处理更新逻辑
          if (key == 'age') {
            obj[key] = value
            document.getElementById('age').innerHTML = value
          }
        }
      })
    }
    
    const like = 10
    const person = {
      name:'xxx',
      age:18
    }
    const rlike = ref(like)
    const rperson = reactive(person)
    function changeData () {
      rlike.value++
      rperson.age++
    }
    </script>
    

    vue2响应式使用Object.defineProperty 的缺陷

    1、无法监控到数组下标的变化,通过数组下标修改元素,无法实时响应
    2、只能劫持对象的属性,如果对象的属性还是对象,则需要深度遍历,Proxy 可以劫持整个对象,并返回一个新的对象
    3、只能监听已存在属性的变化,不能监听新属性的添加,Proxy 不仅可以代理对象,还可以代理数据,可以代理动态增加的属性

    vue3改进了响应式原理

    vue3通过reactive方法,利用Proxy的代理对象,解决大量在vue2中Object.defineProperty的痛点,极好的支持对象监听,但同时Proxy并不能直接监听基础类型,需要每次都构建一个对象使用Proxy去代理,这样会造成极大的性能损耗,因此vue3提供了一个ref方法,通过返回一个简单的响应式对象,专门用来处理基础类型的数据响应

    小提示

    开发过程中,我们会遇到需要替换整个响应式数据的情况
    会发现使用reactive,页面数据无法响应更新

    let xiaoming = reactive({
      name:'xiaoming',
      age:18
    })
    function replaceperson () {
      xiaoming.value = {
        name:'xiaoming111',
        age:10
      }
      console.log(xiaoming.value)
    }
    
    image.png

    点击按钮,此时通过控制台打印可知道xiaoming这个对象的数据已被修改,但页面渲染数据未发生变化
    原因:
    reactive声明的数据不能替换整个对象:由于 Vue 的响应式跟踪是通过属性访问实现的,因此我们必须始终保持对响应式对象的相同引用。这意味着我们不能轻易地“替换”响应式对象,因为这样的话与第一个引用的响应性连接将丢失

    我们可以使用ref来声明

    let xiaoming = ref({
      name:'xiaoming',
      age:18
    })
    // let xiaoming = reactive({
    //   name:'xiaoming',
    //   age:18
    // })
    function replaceperson () {
      xiaoming.value = {
        name:'xiaoming111',
        age:10
      }
      console.log(xiaoming.value)
    }
    
    image.png

    相关文章

      网友评论

          本文标题:vue3响应式原理

          本文链接:https://www.haomeiwen.com/subject/dknfidtx.html