【问题标题】:Vue 3, composition API, Array of refs doesn't workVue 3,组合 API,引用数组不起作用
【发布时间】:2021-04-22 16:25:22
【问题描述】:

请看下面的代码。

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

输出如下

{ "_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" }

预期输出

a
b
c

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

干杯!

【问题讨论】:

  • 数组本身应该是一个引用而不是数组项

标签: javascript vue.js vuejs3 vue-composition-api


【解决方案1】:

你做错了;尝试关注

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

将 ref 项添加到普通数组是没有意义的。 Array 本身应该是 ref.

【讨论】:

  • ☝️ 因为对象和数组都是引用类型而不是原始类型,所以应该使用 reactive 而不是 ref - 或者我错过了什么?
  • @IrgendSonHansel 答案是“取决于”,我最近有一个非常具体的案例,用于 ref 而不是对数组进行反应。本质上,我需要它引用一个数组,而不是数组的属性,因为自定义 getter 会导致响应式做奇怪的事情。
【解决方案2】:

这是正确答案

setup() {
    const arr = ref([]);
    arr.value.push("a");
    arr.value.push("b");
    arr.value.push("c");
    console.log(arr.value)
    return { arr };
  }

这个选项是可能的,但第一个更好。

const arr = reactive([]);
      arr.push("a")
      arr.push("b")
      arr.push("c")
      console.log(arr)

【讨论】:

    【解决方案3】:

    应使用value 字段访问它们:

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

    但这是一个不好的做法,你应该将你的数组定义为 ref 然后将值推送到它:

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

    另一种精心设计的解决方案是使用该值初始化数组:

      setup() {
        const arr = ref(["a","b","c"]);
       
        return { arr };
      }
    

    【讨论】:

      【解决方案4】:

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

      最近,我正在通过开发一个简单的待办事项列表应用程序来学习作文 API。我在使用ref()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>
      
      

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

      为了解决这个问题,我重写了我的代码。我没有将todos 分配给reactice([]),而是使用这样的对象-> 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>
      
      

      结论

      vue 似乎只能在引用相同的情况下观察变化(JavaScript 中的对象是通过引用调用的),但在引用发生变化时无法检测到变化。作为结果,我认为“将数组包装在对象中”是在组合 API 中处理数组的更好方法。

      2。 ref() 用于原始值和 reactive() 值?

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

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

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

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

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

      小结论

      现阶段,我们似乎可以随时使用ref()。但是,我认为最好将reactive() 用于对象,将ref() 用于原语以产生影响!(如果您对此主题有任何想法,请分享给我!)

      【讨论】:

      • 请留下您找到这些信息的链接。
      • 你好,今天我发现我的理解有问题,所以我编辑了它!
      猜你喜欢
      • 2021-06-24
      • 1970-01-01
      • 2021-10-04
      • 1970-01-01
      • 2021-01-14
      • 1970-01-01
      • 2021-10-28
      • 2021-12-31
      • 2021-07-06
      相关资源
      最近更新 更多