ref vs reactive в Vue 3?

Рассмотрение некоторых примеров руководств некоторых пользователей по предварительному просмотру Vue 3. [Сейчас бета-версия]

Я нашел два примера:

Реактивный

<template>
  <button @click="increment">
    Count is: {{ state.count }}, double is: {{ state.double }}
  </button>
</template>

<script>
import { reactive, computed } from 'vue'

export default {
  setup() {
    const state = reactive({
      count: 0,
      double: computed(() => state.count * 2)
    })

    function increment() {
      state.count++
    }

    return {
      state,
      increment
    }
  }
}
</script>

Ссылка

<template>
  <div>
    <h2 ref="titleRef">{{ formattedMoney }}</h2>
    <input v-model="delta" type="number">
    <button @click="add">Add</button>
  </div>
</template>

<script>
import { ref, computed, onMounted } from "vue";

export default {
  setup(props) {
    // State
    const money = ref(1);
    const delta = ref(1);

    // Refs
    const titleRef = ref(null);

    // Computed props
    const formattedMoney = computed(() => money.value.toFixed(2));

    // Hooks
    onMounted(() => {
      console.log("titleRef", titleRef.value);
    });

    // Methods
    const add = () => (money.value += Number(delta.value));

    return {
      delta,
      money,
      titleRef,
      formattedMoney,
      add
    };
  }
};
</script>

person Denis Tsoi    schedule 27.04.2020    source источник


Ответы (5)


Ключевые моменты

  • reactive() принимает только объекты, НЕ примитивы JS (String, Boolean, Number, BigInt, Symbol, null, undefined)
  • ref() звонит reactive() за кулисами
  • Поскольку reactive() работает с объектами, а ref() вызывает reactive(), объекты работают с обоими
  • НО, ref() имеет свойство .value для переназначения, reactive() его не имеет и поэтому НЕЛЬЗЯ переназначить

Использовать

ref() когда ..

  • это примитив (например, 'string', true, 23 и т. д.)
  • это объект, который вам нужно позже переназначить (например, массив - подробнее здесь < / а>)

reactive() когда ..

  • это объект, который вам не нужно переназначать, и вы хотите избежать накладных расходов, связанных с ref()

В итоге

ref() кажется подходящим вариантом, поскольку он поддерживает все типы объектов и позволяет переназначать с помощью .value. ref() - хорошее место для начала, но по мере того, как вы привыкните к API, знайте, что reactive() имеет меньше накладных расходов и, возможно, вы обнаружите, что он лучше соответствует вашим потребностям.

ref() Сценарий использования

Вы всегда будете использовать ref() для примитивов, но ref() подходит для объектов, которые необходимо переназначить, например, для массива.

setup() {
    const blogPosts = ref([]);
    return { blogPosts };
}
getBlogPosts() {
    this.blogPosts.value = await fetchBlogPosts();
}

Вышеупомянутое с reactive() потребует переназначения свойства вместо всего объекта.

setup() {
    const blog = reactive({ posts: [] });
    return { blog };
}
getBlogPosts() {
    this.blog.posts = await fetchBlogPosts();
}

reactive() Сценарий использования

Хороший вариант использования reactive() - это группа примитивов, которые принадлежат друг другу:

const person = reactive({
  name: 'Albert',
  age: 30,
  isNinja: true,
});

приведенный выше код кажется более логичным, чем

const name = ref('Albert');
const age = ref(30);
const isNinja = ref(true);

Полезные ссылки

Если вы все еще заблудились, мне помогло это простое руководство: https://www.danvega.dev/blog/2020/02/12/vue3-ref-vs-reactive/

Аргумент в пользу использования только ref(): https://dev.to/ycmjason/ought-on-vue-3-composition-api-reactive-considered-harmful-j8c

Принятие решения о том, почему reactive() и ref() существуют именно так, и другая полезная информация, Vue Composition API RFC: https://vue-composition-api-rfc.netlify.app/#overhead-of-введение-refs

person Chris Hayes    schedule 12.12.2020
comment
v3.vuejs.org/guide/ в чем разница между const list = reactive ([1, 2, 3]) и const divs = ref ([])? - person Yiping; 16.12.2020
comment
@Yiping хороший момент. Массив - это объект, и оба принимают объекты, поэтому я не был уверен. Но оказывается, что переназначение массивов с ref .value имеет преимущества, которых у reactive нет. github.com/vuejs/docs-next/issues/801#issuecomment- 757587022 - person Chris Hayes; 11.01.2021
comment
Я обновил ответ, добавив больше информации и примеров. - person Chris Hayes; 11.01.2021
comment
reactive можно переназначить с помощью Object.assign () - person Bryant; 16.01.2021
comment
@Bryant Object.assign объединяет объекты. Это не переназначение. Предположим, у вас есть два реактива: один для хранения исходного состояния, а другой - для хранения измененного состояния. Если вы попытаетесь использовать Object.assign для возврата измененного обратно в исходное состояние, вместо этого вы получите объединенный объект. const original = reactive({name: "Original"}) const modified = reactive({name: "Modified", age: 5}) Object.assign(modified, original); = ›{name: 'Original', возраст: 5} - person nogridbag; 12.03.2021

Между ref и reactive есть некоторое сходство в том, что они оба предоставляют метод для хранения данных и позволяют этим данным быть реактивными.

Тем не мение:

Высокие уровни различий:

Вы не можете использовать reactive () для примитивов (строк, чисел, логических значений) - это то, для чего вам нужны ссылки, потому что у вас будут ситуации, когда вам понадобится, например, «реактивное логическое значение» ...

конечно, вы можете создать объект, который обертывает примитивное значение и сделать это reactive ():

const wrappedBoolean = reactive({
  value: true
})

и вот так вы заново изобрели исх.

Источник: обсуждение на форуме Vue

Реактивный

reactive берет объект и возвращает реактивный proxy исходному объекту.

Пример

import {ref, reactive} from "vue";

export default {
  name: "component",
  setup() {
    const title = ref("my cool title")
    const page = reactive({
      contents: "meh?",
      number: 1,
      ads: [{ source: "google" }],
      filteredAds: computed(() => {
        return ads.filter(ad => ad.source === "google")
      })
    })
    
    return {
       page, 
       title
    }
  }
}

Объяснение

Как указано выше, всякий раз, когда мы хотим изменить или получить доступ к свойствам page,
скажем, page.ads, page.filteredAds будет обновляться через прокси.

person Denis Tsoi    schedule 27.04.2020
comment
Есть ли какое-то мнение о том, что лучше для массивов? То есть ref([]) vs. reactive([])? - person Alex Balashov; 18.12.2020
comment
опубликовал комментарий к вашему Q - person Denis Tsoi; 24.12.2020

ref / reactive оба используются для создания реактивного объекта, в котором отслеживаются изменения.

Ссылка:

Он принимает аргумент примитивов и возвращает реактивный изменяемый объект. У объекта есть единственное свойство «значение», и оно будет указывать на принимаемый им аргумент.

Реактивный:

Он принимает объект JavaScript в качестве аргумента и возвращает реактивную копию объекта на основе прокси.

Реф. Против реактивного:

Как правило, ref и reactive используются для создания реактивных объектов, где ref используется, чтобы сделать примитивные значения реактивными (Boolean, Number, String). Но реактивный не работает с примитивами, а не с объектами.

Для получения дополнительной информации: см. Ref vs Reactive

person George Princelin J    schedule 18.12.2020

Ниже вы можете увидеть наш пример с использованием реактивных ссылок в верхней части и под другим альтернативным реактивным синтаксисом.

//reactivity with ref syntax

import { ref, computed } from vue

export default {
  setup() {
    const capacity = ref(4)
    const members = ref(["Tim", "John", "Andr"])
    const simpleComputed = computed(() => {
      return capacity.value - members.value.length
    })

    return { capacity, members, simpleComputed }
  }
}


//reactivity with reactive syntax

import { reactive, computed } from vue

export default {
  setup() {
    const event = reactive({
      capacity: 4,
      members: ["Tim", "John", "Andr"]
      simpleComputed: computed(() => {
        return event.capacity - event.capacity.length
      }
    })
    return { event }
  }
}

Как показано в приведенном выше коде в нижней части, я создал новую константу события, которая принимает простой объект JavaScript и возвращает реактивный объект. Это может показаться знакомым с использованием параметра данных в нашем обычном синтаксисе компонентов, куда я также отправляю объект. Однако, как вы можете видеть выше, я также могу отправить в этот объект наши вычисленные свойства. Вы также должны заметить, что когда я использую этот синтаксис, нам больше не нужно писать .value при доступе к свойствам. Это потому, что я просто получаю доступ к свойствам объекта в объекте события. Вы также должны заметить, что мы возвращаем все мероприятие

Оба синтаксиса допустимы для использования, и ни один из них не считается оптимальным

person elvonkh    schedule 27.04.2020

Ссылка: принимает аргумент примитивов и возвращает реактивный изменяемый объект. У объекта есть единственное свойство «значение», и оно будет указывать на принимаемый им аргумент.

Реактивный: он принимает объект JavaScript в качестве аргумента и возвращает реактивную копию объекта на основе прокси.

Подробнее об этом можно узнать из этого видеоурока: https://www.youtube.com/watch?v=JJM7yCHLMu4

person Harish Kumar    schedule 24.12.2020