您的位置:

深入剖析Vue 3的shallowRef函数

一、什么是shallowRef函数

shallowRef函数是Vue 3中一个响应式函数,它可以将传入的非响应式对象转换为响应式对象,并且可以让这个对象成为响应式状态的根源,当对象发生变化时,会让所有引用该对象的组件或者函数重新渲染。

shallowRef函数与ref函数的不同之处在于它仅对对象的第一层进行响应式处理,第二层及以下的属性变化将不会触发更新。这种特性常用于性能优化。


import { shallowRef } from 'vue'

const obj = { name: 'Tom', age: 20 }
const objRef = shallowRef(obj)

console.log(objRef.value.name) // Tom

objRef.value.name = 'Jerry' // 触发组件渲染

二、shallowRef函数的使用场景

使用shallowRef函数一般意味着你需要用到对象的第一层属性,并且这些属性的变化需要触发组件更新。常见的使用场景有:

1、对象属性在模板中使用

当对象的第一层属性在组件模板中展示时,常用shallowRef函数将对象转换为响应式对象,这样在属性发生变化时能够触发组件的重新渲染。


<template>
  <div>
    <p>Name: {{ user.name }}</p>
    <p>Age: {{ user.age }}</p>
  </div>
</template>

<script>
  import { shallowRef } from 'vue'

  export default {
    setup() {
      const user = shallowRef({ name: 'Tom', age: 20 })
      return { user }
    }
  }
</script>

2、对象作为函数参数传递

当对象作为函数参数传递时,常用shallowRef函数将对象转换为响应式对象,这样在函数内部修改对象的属性时能够触发组件的重新渲染。


<template>
  <div>
    <p>Name: {{ user.name }}</p>
    <p>Age: {{ user.age }}</p>
    <button @click="updateUser">Update</button>
  </div>
</template>

<script>
  import { shallowRef } from 'vue'

  export default {
    setup() {
      const user = shallowRef({ name: 'Tom', age: 20 })

      function updateUser() {
        // 修改对象属性,触发组件重新渲染
        user.value.name = 'Jerry'
        user.value.age = 21
      }

      return { user, updateUser }
    }
  }
</script>

三、shallowRef函数的注意事项

1、使用shallowRef函数的对象不应该是一个响应式对象

当使用shallowRef函数将一个已经是响应式对象的对象再次转换为响应式对象时,会出现以下错误:


const obj = reactive({ name: 'Tom', age: 20 })
const objRef = shallowRef(obj) // 报错:不能将已经是响应式的对象转换为响应式对象

2、不要滥用shallowRef函数

由于shallowRef函数的特性,只会对对象的第一层进行响应式处理,当对象的更深层次的属性变化时,不会触发组件重新渲染,容易出现更新不及时的情况。因此,在使用shallowRef函数时,需慎重考虑对象的属性结构,以免滥用。

3、使用shallowRef函数的对象不要包含函数属性

当对象包含函数属性时,使用shallowRef函数将会把函数当做对象的属性进行处理,而函数属性本身不应该被响应式处理。


const obj = { name: 'Tom', sayHello: function() { console.log('Hello!') } }
const objRef = shallowRef(obj) // 函数属性不应该被响应式处理

四、shallowRef函数的优化应用

shallowRef函数由于只会对对象的第一层进行响应式处理,可以用于优化组件性能。通常情况下,当一个对象的第一层属性发生变化时,组件需要重新渲染,而对象深层次的属性发生变化时,渲染没有必要,因此使用shallowRef函数可以有效避免不必要的组件渲染,提高应用程序性能。

例如,在Vue 3中使用shallowRef函数优化一个包含子组件的列表时:


<template>
  <div>
    <div v-for="item in list" :key="item.id">
      <my-component :item="item" :is-active="item.isActive" />
      <button @click="update(item)">Update</button>
    </div>
  </div>
</template>

<script>
  import { shallowRef } from 'vue'
  import MyComponent from './MyComponent.vue'

  export default {
    components: { MyComponent },
    setup() {
      const list = shallowRef([
        { id: 1, name: 'Item 1', isActive: false },
        { id: 2, name: 'Item 2', isActive: false },
        { id: 3, name: 'Item 3', isActive: false }
      ])

      function update(item) {
        item.isActive = !item.isActive // 只更新对象的第一层属性,避免不必要的渲染
      }

      return { list, update }
    }
  }
</script>

五、总结

通过本文的介绍,我们对Vue 3的shallowRef函数有了更深入的了解。shallowRef函数提供了性能优化的方案,但也存在一些需要注意的问题。在实际使用时,需要根据对象的属性结构以及业务需求进行慎重考虑,避免滥用和出现不必要的问题。