Please see below code.
<template>
<div v-for="item in arr" :key="item">{{ item }}</div>
</template>
<script>
import { ref } from "vue";
export default {
name: "TestArr",
setup() {
const arr = [];
arr.push(ref("a"));
arr.push(ref("b"));
arr.push(ref("c"));
return { arr };
}
};
</script>
And the output is below
{ "_rawValue": "a", "_shallow": false, "__v_isRef": true, "_value": "a" }
{ "_rawValue": "b", "_shallow": false, "__v_isRef": true, "_value": "b" }
{ "_rawValue": "c", "_shallow": false, "__v_isRef": true, "_value": "c" }
expected output
a
b
c
I have to call item.value in the template to make it work. What's the work around for this scenario in vue3?
Cheers!
Thankfully, Vue 3 Reactivity with Composition API is equally robust. Vue 3 Reactivity with Composition API is driven by reactive () and ref () functions. These functions turn the component model data reactive so that Vue is able to track changes. However, both reactive () and ref () have their specific use-cases.
Bookmark this question. Show activity on this post. Please see below code. I have to call item.value in the template to make it work. What's the work around for this scenario in vue3? Cheers! Show activity on this post. There is no point adding ref items to a normal array. The Array itself should be ref.
In the end, thanks to the huge developer outcry the initial plan to deprecate the old component syntax was abandoned, so v3 will still support the old Vue syntax we love. Yay! The Composition API came about as a solution to the age-old problem of code reuse and encapsulation of business logic.
So, how can you work with template refs in Composition API? It might be more simple than you think! The thing is, Vue.js unifies the concept of refs, meaning that you just need to use the ref () function you already know for declaring reactive state variables in order to declare a template ref as well.
You are doing it wrong; try following
setup() {
const arr = ref([]);
arr.value.push("a");
arr.value.push("b");
arr.value.push("c");
return { arr };
}
There is no point adding ref items to a normal array. The Array itself should be ref.
Recently, I am learning composition API by developing a simple todo list app. I ran into some problems when dealing with array by using ref()
and reactive()
and found some behaviors which may be helpful for folks who are learning composition API too, so I wrote down some words here. If there is something wrong, please tell me!
So...at first everything just work as I expected until I working on developing delete function.
I tried to build a button which will trigger the deleteHandler
function when it been click. And the deleteHandler
would filter out the element in todos
:
Here is my code:
<template>
<div>
<h1>reactive</h1>
<button @click="add">click</button>
<div v-for="item in todos" :key="item">
<button @click="mark(item)">mark</button>
<span>{{item}}</span>
<button @click="deleteHandler(item.id)">delete</button>
</div>
</div>
</template>
<script>
import {reactive, ref} from "vue";
export default {
name: "ReactiveMethod",
setup(){
let todos = reactive([])
const id = ref(0);
function add(){
todos.push({id:id.value, name:"hallo", state:"undone"});
id.value += 1
}
function mark(item){
if(item.state === "undone"){
item.state = "done"
}else{
item.state = "undone"
}
}
function deleteHandler(id){
const temp = todos.filter((element)=>{
return element.id !== id
})
todos = temp
}
return {
todos,
id,
deleteHandler,
add,
mark
}
}
}
</script>
However, I face a crucial problem, since the filter
function would not mutate the original value but return a new value. Vue could not detect the change inside todos
.
To solve this problem, I rewrite my code. Instead of assigning todos
to reactice([])
, I warpped the array with object like this -> reactive({todos:[]})
. And it works !
<template>
<div>
<h1>reactive</h1>
<button @click="add">click</button>
<div v-for="item in todos" :key="item">
<button @click="mark(item)">mark</button>
<span>{{item}}</span>
<button @click="deleteHandler(item.id)">delete</button>
</div>
</div>
</template>
<script>
import {reactive, ref, toRefs} from "vue";
export default {
name: "ReactiveMethod",
setup(){
const state = reactive({
todos:[]
})
const id = ref(0);
function add(){
state.todos.push({id:id.value, name:"hallo", state:"undone"});
id.value += 1
}
function mark(item){
if(item.state === "undone"){
item.state = "done"
}else{
item.state = "undone"
}
}
function deleteHandler(id){
const temp = state.todos.filter((element)=>{
return element.id !== id
})
state.todos = temp
}
return {
...toRefs(state),
id,
deleteHandler,
add,
mark
}
}
}
</script>
It seems that vue could only watch on the change with same reference(object in JavaScript is called by reference), but could not detect the change when the reference is changed. As a resault, I think "wrap the array inside object" is a better way to deal with array in composition API.
According to the most information we could found, It seems that we can make a conclusion:
ref() for primitive value and reactive() value
However, if we write some code like this, Vue is still able to detect the change inside it:
const obj = ref({name:"charles"});
return{
...toRefs(obj)
}
The reason is that when we pass data into ref()
, it would first check whether the data been sended is primitive or object. If it is object, ref()
would call reactive()
to deal with it.In other words, reactive()
is the one who actually take on the job behind the scene.
At this stage, it seems that we can use ref()
anytime. However, I think it's better to use reactive()
for object and ref()
for primitive to make difference!(If you have any ideas about this topic, please share it to me !)
This is the correct answer
setup() {
const arr = ref([]);
arr.value.push("a");
arr.value.push("b");
arr.value.push("c");
console.log(arr.value)
return { arr };
}
This option is possible, but the first is much better.
const arr = reactive([]);
arr.push("a")
arr.push("b")
arr.push("c")
console.log(arr)
They should be accessed using value
field :
setup() {
const arr = [];
arr.push(ref("a").value);
arr.push(ref("b").value);
arr.push(ref("c").value);
return { arr };
}
but this is a bad practice, your should define your array as ref then push values to it :
setup() {
const arr = ref([]);
arr.value.push("a");
arr.value.push("b");
arr.value.push("c");
return { arr };
}
another crafted solution is to init the array with that values :
setup() {
const arr = ref(["a","b","c"]);
return { arr };
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With