Vue 3,组合 API,引用数组不起作用

Phi*_* Li 2 javascript vue.js vuejs3 vue-composition-api

请看下面的代码。

<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>
Run Code Online (Sandbox Code Playgroud)

输出如下

{ "_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" }
Run Code Online (Sandbox Code Playgroud)

预期产出

a
b
c
Run Code Online (Sandbox Code Playgroud)

我必须在模板中调用 item.value 才能使其工作。这个 sinario for vue3 的解决方法是什么?

干杯!

ash*_*nde 8

你做错了; 尝试跟随

setup() {
    const arr = ref([]);
    arr.value.push("a");
    arr.value.push("b");
    arr.value.push("c");
    return { arr };
  }
Run Code Online (Sandbox Code Playgroud)

在普通数组中添加 ref 项是没有意义的。所述阵列应REF。

  • ☝️ 由于对象和数组都是引用类型而不是基元,因此应该使用“reactive”而不是“ref” - 或者我错过了什么? (3认同)

小智 6

有关将数组与 ref() 和reactive() 一起使用的一些信息可能会有所帮助。

最近,我正在通过开发一个简单的待办事项列表应用程序来学习组合 API。ref()我在使用and处理数组时遇到了一些问题,reactive()发现一些行为可能对学习组合 API 的人有帮助,所以我在这里写下一些话。如果有什么不对的地方请告诉我!

1.使用reactive()处理数组时出现什么问题?

所以......起初一切都按我的预期工作,直到我致力于开发删除功能。

我尝试构建一个按钮,deleteHandler单击该按钮时将触发该功能。并且deleteHandler会过滤掉 中的元素todos

这是我的代码:

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

Run Code Online (Sandbox Code Playgroud)

然而,我面临一个关键问题,因为该filter函数不会改变原始值,而是返回一个新值。Vue 无法检测到内部的变化todos

为了解决这个问题,我重写了我的代码。我没有分配todosreactive([]),而是用这样的对象扭曲了数组 -> reactive({todos:[]})。它有效!

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

Run Code Online (Sandbox Code Playgroud)

结论

看来vue只能观察相同引用的变化(JavaScript中的对象是通过引用调用的),但当引用改变时无法检测到变化。因此,我认为“将数组包装在对象内”是在组合 API 中处理数组的更好方法。

2. ref() 表示原始值和reactive() 值?

根据我们所能找到的最多的信息,我们似乎可以得出一个结论:

ref() 用于原始值和reactive() 值

然而,如果我们编写这样的代码,Vue 仍然能够检测到其中的变化:

const obj = ref({name:"charles"});

return{
 ...toRefs(obj)
}

Run Code Online (Sandbox Code Playgroud)

原因是当我们将数据传递给 时ref(),它会首先检查发送的数据是原始数据还是对象数据。如果是对象,ref()就会调用reactive()去处理它。换句话说,reactive()是真正在幕后承担工作的人。

小结论

到了这个阶段,似乎ref()随时都可以使用。但是,我认为最好使用reactive()对象和ref()基元来产生区别!(如果您对这个主题有任何想法,请分享给我!)

  • 请留下您找到这些信息的链接。 (3认同)