【Vue.js】Composition API - reactive()

77 阅读2分钟

概述

reactive 用来返回一个对象的响应式代理

语法:

function reactive<T extends object>(target: T): UnwrapNestedRefs<T>

使用:

基本使用:

具体步骤如下:

  1. 使用 Vue.reactive, 接收一个对象并生成一个响应式对象
  2. setup() 函数中返回出去
  3. 在模板中使用 响应式对象.xxx 进行挂载访问
<script>
  import { defineComponent, reactive } from 'vue';

  export default defineComponent({
    name: 'Comp',
    setup(props, ctx) {
      const state = reactive({
        name: 'zhangsan',
        age: 18,
        career: 'programmer'
      });

      return {
        state
      };
    }
  });
  
</script>

<template>
  <div class="wrapper">
    <p>
      Name: {{ state.name }}
    </p>
    <p>
      Age: {{ state.age }}
    </p>
    <p>
      Career: {{ state.career }}
    </p>
  </div>
</template>

注意

  • reactive 对象的所有值都是深度代理的,不需要担心深层数据变化而视图没有响应的问题。
  • reactive 对象中的值不能够直接解构,这样会丧失原有的【响应性】!!!

配合其他组合式 API 使用

有时候,使用 state.xxx会比较麻烦,而直接解构会丧失响应式!

在 Vue 里面提供了其他的组合式 API 可以将 state 中所有的字面量转化成响应式数据并提供给视图使用:

  1. 配合 toRef使用:
<script>
  import { defineComponent, reactive, toRef } from 'vue';

  export default defineComponent({
    name: 'Comp',
    setup(props, ctx) {
      const state = reactive({
        name: 'zhangsan',
        age: 18,
        career: 'programmer'
      });

      const name = toRef(state, 'name'),
            age = toRef(state, 'age'),
            career = toRef(state, 'career');

      return {
        name,
        age,
        career,
      };
    }
  });
  
</script>

<template>
  <div class="wrapper">
    <p>
      Name: {{ name }}
    </p>
    <p>
      Age: {{ age }}
    </p>
    <p>
      Career: {{ career }}
    </p>
  </div>
</template>
  1. 配合 toRefs使用:
<script>
  import { defineComponent, reactive, toRefs } from 'vue';

  export default defineComponent({
    name: 'Comp',
    setup(props, ctx) {
      const state = reactive({
        name: 'zhangsan',
        age: 18,
        career: 'programmer'
      });

      return {
        ...toRefs(state)
      };
    }
  });
  
</script>

<template>
  <div class="wrapper">
    <p>
      Name: {{ name }}
    </p>
    <p>
      Age: {{ age }}
    </p>
    <p>
      Career: {{ career }}
    </p>
  </div>
</template>
  1. 配合 computed 使用
<script>
  import { defineComponent, reactive, computed } from 'vue';

  export default defineComponent({
    name: 'Comp',
    setup(props, ctx) {
      const state = reactive({
        name: 'zhangsan',
        age: 18,
        career: 'programmer'
      });

      const name = computed(() => state.name),
            age = computed(() => state.age),
            career = computed(() => state.career);

      return {
        name,
        age,
        career,
      };
    }
  });
  
</script>

<template>
  <div class="wrapper">
    <p>
      Name: {{ name }}
    </p>
    <p>
      Age: {{ age }}
    </p>
    <p>
      Career: {{ career }}
    </p>
  </div>
</template>

总结:

  1. reactive 响应式转换是“深层”的:它会影响到所有嵌套的属性。
  2. 如果 reactive 中还有其他的响应式对象(比如 refreadonly),reactive 也会去维持它们的【响应性】。
  3. 当访问到某个响应式数组或 Map (Set, WeakMap, WeakSet)这样的原生集合类型中的 ref 元素时,不会执行 ref 的解包。(proxyObject.map.mapKey.value);
  4. 若要避免深层响应式转换,只想保留对这个对象顶层次访问的响应性,请使用 shallowReactive() 作替代。
  5. 不要直接操作原始对象 (raw object)!为了保证视图的正确更新,应该对 reactive 对象进行操作
  6. 使用 reactive 包裹 ref 对象, reactiveref 对应的变量具有相同的引用
  7. 将一个 ref 赋值给为一个 reactive 属性时,该 ref 会被自动解包