跳到主内容

vue3中ref和reactive的区别?

· 3分钟阅读

例子如下:

Reactive

<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>

Ref

<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>

Key Points

  • reactive() only takes objects, NOT JS primitives (String, Boolean, Number, BigInt, Symbol, null, undefined)
  • ref() is calling reactive() behind the scenes
  • Since reactive() works for objects and ref() calls reactive(), objects work for both
  • BUT, ref() has a .value property for reassigning, reactive() does not have this and therefore CANNOT be reassigned

Use

ref() when..

  • it's a primitive (for example 'string', true, 23, etc)
  • it's an object you need to later reassign (like an array - more info here)

reactive() when..

  • it's an object you don't need to reassign, and you want to avoid the overhead of ref()

In Summary

ref() seems like the way to go since it supports all object types and allows reassigning with .value. ref() is a good place to start, but as you get used to the API, know that reactive() has less overhead, and you may find it better meets your needs.

ref() Use-Case

You'll always use ref() for primitives, but ref() is good for objects that need to be reassigned, like an array.

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

The above with reactive() would require reassigning a property instead of the whole object.

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

reactive() Use-Case

A good use-case for reactive() is a group of primitives that belong together:

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

the code above feels more logical than

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

If you're still lost, this simple guide helped me: https://www.danvega.dev/blog/2020/02/12/vue3-ref-vs-reactive/

An argument for only ever using ref(): https://dev.to/ycmjason/thought-on-vue-3-composition-api-reactive-considered-harmful-j8c

The decision-making behind why reactive() and ref() exist as they do and other great information, the Vue Composition API RFC: https://vue-composition-api-rfc.netlify.app/#overhead-of-introducing-refs