无法访问 Vue 3 中 prop 对象项的子数组

huangapple go评论69阅读模式
英文:

Unable to access sub-array in Vue 3 prop object item

问题

在一个Vue3/InertiaJS项目中,我试图实现一个简单的动态选择列表填充,但我在读取props数据以填充下拉框时遇到问题。

<script setup>
    import {Head, Link, useForm} from '@inertiajs/inertia-vue3'
    import SelectInput from '@/Components/ping/SelectInput.vue'
    import {ref} from 'vue';

    const props = defineProps({
        areas: [
          {
            id:1,
            name:"Club",
            approvers: [
              {
                id:12,
                first_name: "Joe",
                last_name: "Blow"
              }
            ]
          },
          {
            id:2,
            name:"Adult Small Bore",
            approvers: [
              {
                id:34,
                first_name: "Sam",
                last_name: "Snead"
              }
            ]
          },
          {
            id:3,
            name:"Appleseed",
            approvers: [
              {
                id:56,
                first_name: "Johhny",
                last_name: "Appleseed"
              }
            ]
          },
          {
            id:4,
            name:"Archery",
            approvers: [
              {
                id:56,
                first_name: "Jim",
                last_name: "Beam"
              },
              {
                id:56,
                first_name: "Jack",
                last_name: "Daniels"
              }
            ]
          },
          {
            id:5,
            name:"Armed Women of America",
            approvers: [
              {
                id: 99,
                first_name: "Amelia",
                last_name: "Earhart"
              }
            ]
          }
        ]  
    })

    const form = useForm({
        date: '',
        hours: '',
        area: '',
        reason: '',
        comments: '',
        approver: ''
    });

    let selectApprovers = ref([]);

    function updateApprovers(event) {
        const area = props.areas.filter(area => area.id === parseInt(event.target.value));
        console.log({area});
        selectApprovers.value = area.approvers.map(function (item) {
            return {
                id: item.id,
                name: item.first_name + ' ' + item.last_name
            }
        });

        selectApprovers.value = approvers;
    }

    function store() {
        form.post(`/admin/work-hours`)
    }
</script>

<template>
  <div>
    <form @submit.prevent="store">
    
                    <select-input v-model="form.area" :error="form.errors.area"
                                class="pb-8 pr-6 w-full lg:w-1/2" label="Area" @change="updateApprovers">
                        <option :value="null" />
                        <option v-for="area in props.areas" :key="area.id" :value="area.id">{{ area.name }}</option>
                    </select-input>
                    <select-input v-model="form.approver" :error="form.errors.approver"
                                class="pb-8 pr-6 w-full lg:w-1/2" label="Approver">
                        <option :value="null" />
                        <option v-for="approver in selectApprovers" :key="approver.id" :value="approver.id">{{ approver.name }}</option>
                    </select-input>
    </form>
  </div>
</template>

其中<select-list>输入只是一个标准<select>元素的包装器。

真实应用中的props是通过Laravel 通过InertiaJS传递的。我遇到问题的地方在于updateApprovers()。这一行工作正常:

const area = props.areas.filter(area => area.id === parseInt(event.target.value));

console.log({area})所示。然而,它在尝试读取area.approvers时出现错误,并出现以下错误:

Uncaught TypeError: can't access property "map", area.approvers is undefined

我尝试过使用value

 selectApprovers.value = area.value.approvers.map(function (item) {

但是我得到相同的错误。通过Vue DevTools对props进行视觉检查显示,approvers数组是存在的;我需要做什么才能访问它?

我尝试设置一个[sfc playground](https://sfc.vuejs.org/#eNrFV21v2zYQ/iuEEMAOGslt+oJVUwKk2z50H4YBAbYPU7DSEhUzlUiBopwFhv777vgiU4rjdEGBMUhCHo/PvfKO2kVXbZtsexalUdYVireadEz37WUueNNKpcmOKFaRgVRKNmQBrItcEIK/hRSdJpVUDblApuUOqYRQxWhKFoszt2xbJbdMIQkpw+mPUwTYbjuAKFnFBfsdVyFUl5K/7IoQR8bBy/SNk4BD0IalefRT3a/zKKB76SHKDMmjnQfHcFRcdfpvA0zy6FfJJsA4ahowfKrlfR6FDMN+ceOnwwgxtSUU7my5Kvtak+uG1jX5JNVU/Lfb9fbd/2nX2wN2tW3NOsbKFxr0/sMzBm024uG4TYEKLzUs9Ko3TBUbpqaiv59ZvHkmTowCx8ScCft/l0iL4xJ/poKzunu5D98f8mHDSvK

英文:

In a Vue3/InertiaJS project, I am attempting to do a simple dynamic select list population, but I'm having issues reading the props data to populate the dropdown.

<script setup>
import {Head, Link, useForm} from '@inertiajs/inertia-vue3'
import SelectInput from '@/Components/ping/SelectInput.vue'
import {ref} from 'vue';
const props = defineProps({
areas: [
{
id:1,
name:"Club",
approvers: [
{
id:12,
first_name: "Joe",
last_name: "Blow"
}
]
},
{
id:2,
name:"Adult Small Bore",
approvers: [
{
id:34,
first_name: "Sam",
last_name: "Snead"
}
]
},
{
id:3,
name:"Appleseed",
approvers: [
{
id:56,
first_name: "Johhny",
last_name: "Appleseed"
}
]
},
{
id:4,
name:"Archery",
approvers: [
{
id:56,
first_name: "Jim",
last_name: "Beam"
},
{
id:56,
first_name: "Jack",
last_name: "Daniels"
}
]
},
{
id:5,
name:"Armed Women of America",
approvers: [
{
id: 99,
first_name: "Amelia",
last_name: "Earhart"
}
]
}
]  
})
const form = useForm({
date: '',
hours: '',
area: '',
reason: '',
comments: '',
approver: ''
});
let selectApprovers = ref([]);
function updateApprovers(event) {
const area = props.areas.filter(area => area.id === parseInt(event.target.value));
console.log({area});
selectApprovers.value = area.approvers.map(function (item) {
return {
id: item.id,
name: item.first_name + ' ' + item.last_name
}
});
selectApprovers.value = approvers;
}
function store() {
form.post(`/admin/work-hours`)
}
</script>
<template>
<div>
<form @submit.prevent="store">
<select-input v-model="form.area" :error="form.errors.area"
class="pb-8 pr-6 w-full lg:w-1/2" label="Area" @change="updateApprovers">
<option :value="null" />
<option v-for="area in props.areas" :key="area.id" :value="area.id">{{ area.name }}</option>
</select-input>
<select-input v-model="form.approver" :error="form.errors.approver"
class="pb-8 pr-6 w-full lg:w-1/2" label="Approver">
<option :value="null" />
<option v-for="approver in selectApprovers" :key="approver.id" :value="approver.id">{{ approver.name }}</option>
</select-input>
</form>
</div>
</template>

where the <select-list> input is just a wrapper around a standard <select> element.

The props in the real app are coming from Laravel via InertiaJS. The issue I am having is in updateApprovers(). This line works fine:

const area = props.areas.filter(area => area.id === parseInt(event.target.value));

as seen in the console.log({area}). However, it errors out at the next line when it tries to read area.approvers, and I get the error

Uncaught TypeError: can't access property "map", area.approvers is undefined

I've tried using value

 selectApprovers.value = area.value.approvers.map(function (item) {

but I get the same error. Visual inspection of the props in Vue dev tools shows that the approvers array is there; what do I need to change to be able to access it?

I've tried setting up an sfc playground, but for some reason it's having issues reading the v-for loop.

答案1

得分: 1

Array.filter 总是返回另一个 数组,所以这行代码:

const area = props.areas.filter(area => area.id === parseInt(event.target.value));

导致 area 是一个对象数组。这些单独的对象可能每个都有一个内部的 approvers 数组,但 area 数组本身没有 approvers 属性,这就是为什么 area.approvers.map() 会抛出错误。

你可以使用 area[0].approvers.map(),但我认为更合适的是首先使用 Array.find 返回第一个匹配的 对象,然后进行映射。

function updateApprovers(event) {
  const area = props.value.areas.find(
    area => area.id === parseInt(event.target.value)
  );
  selectApprovers.value = area.approvers.map(function (item) {
    return {
      id: item.id,
      name: item.first_name + ' ' + item.last_name
    };
  });
}
英文:

Array.filter always returns another array, so this line:

const area = props.areas.filter(area => area.id === parseInt(event.target.value));

results in area being an array of objects. Those individual objects may each have an inner approvers array, but the area array itself has no approvers property, which is why area.approvers.map() throws an error.

You could do area[0].approvers.map(), but I think a more appropriate Array function to use in the first place would be Array.find to return the first matching object which you could then map.

function updateApprovers(event) {
  const area = props.value.areas.find(
    area => area.id === parseInt(event.target.value)
  );
  selectApprovers.value = area.approvers.map(function (item) {
    return {
      id: item.id,
      name: item.first_name + ' ' + item.last_name
    };
  });
}

huangapple
  • 本文由 发表于 2023年2月16日 09:24:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/75466961.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定