Vue 3 传递数组警告:无关的非 props 属性已传递给组件但无法自动继承

问题描述 投票:0回答:7

拜托,我正在学习 VueJS 3,我可能有新手问题。我在浏览器开发者控制台中发出了这样的警告:

消息是:

[Vue warn]: Extraneous non-props attributes (class) were passed to component but could not be automatically inherited because component renders fragment or text root nodes.

我将对象数组传递给子组件。在我的父母

views/Home.vue
组件中,我有这个实现:

<template>
  <div class="wrapper">
    <section v-for="(item, index) in items" :key="index" class="box">
      <ItemProperties class="infobox-item-properties" :info="item.properties" />
    </section>
  </div>
</template>
<script>
import { ref } from 'vue'
import { data } from '@/data.js'
import ItemProperties from '@/components/ItemProperties.vue'

export default {
  components: {
    ItemDescription,
  },
  setup() {
    const items = ref(data)

    return {
      items,
    }
  },
</script>

在子组件中

components/ItemProperties.vue
我有这个代码:

<template>
  <div class="infobox-item-property" v-for="(object, index) in info" :key="index">
    <span class="infobox-item-title">{{ object.name }}:</span>
    <span v-if="object.type === 'rating'">
      <span v-for="(v, k) in object.value" :key="k">{{ object.icon }}</span>
    </span>
    <span v-else>
      <span>{{ object.value }}</span>
    </span>
  </div>
</template>

<script>
export default {
  props: {
    info: {
      type: Array,
      required: false,
      default: () => [
        {
          name: '',
          value: '',
          type: 'string',
          icon: '',
        },
      ],
    },
  },
}
</script>

有没有

default()
功能并不重要。我是否有
v-if
条件也没关系。如果我的数组中有循环,我会收到此警告

数据位于

data.js
文件中。文件部分在这里:

export const data = [
  {
    title: 'White shirt',
    properties: [
      { name: 'Material', value: 'Cotton', type: 'string', icon: '' },
      { name: 'Size', value: 'M', type: 'string', icon: '' },
      { name: 'Count', value: 4, type: 'number', icon: '' },
      { name: 'Absorption', value: 4, type: 'rating', icon: '💧' },
      { name: 'Rating', value: 2, type: 'rating', icon: '⭐️' },
      { name: 'Confort', value: 2, type: 'rating', icon: '🛏' },
      { name: 'Sleeves', value: 'Short', type: 'string', icon: '' },
      { name: 'Color', value: 'White', type: 'string', icon: '' },
    ],
  },
]

PS:应用程序有效,但我担心该警告。我能做什么,请喜欢正确的方式?

我很乐意提供任何建议。非常感谢。

javascript arrays vue.js warnings vuejs3
7个回答
91
投票

嗯,我认为错误消息非常清楚。

您的

ItemProperties.vue
组件正在渲染 fragments - 因为它正在使用
<div>
渲染多个
v-for
元素。这意味着不存在单根元素。

同时,您将

class
传递给带有
<ItemProperties class="infobox-item-properties"
的组件 -
class
只能放置在 HTML 元素上。如果将其放置在 Vue 组件上,Vue 会尝试将其放置在该组件正在渲染的内容的根元素上。但是因为你的组件渲染的内容没有根元素,Vue 不知道把它放在哪里......

要删除警告,请删除

class="infobox-item-properties"
或将
ItemProperties
的内容包装到单个
<div>

上述机制称为 Fallthrough Attributes(“非 prop 属性”Vue 2 文档)。很高兴知道这种自动继承可以被关闭,这允许您自己在根元素之外选择的元素(或组件)上应用这些属性(这样做也可以消除错误消息)。

这非常有用。最值得注意的是,当围绕标准 HTML 元素(如输入或按钮)或某些库组件设计专门的包装器时 - 您可以告诉“这是一个按钮 - 您可以放置标准

<button>
接受的任何内容并且它将起作用”,而无需重新定义所有标准
 <button>
属性作为包装器的道具


11
投票

ItemProperties
组件有多个根节点,因为它用
v-for
在根中渲染一个列表。

基于类名称 (

infobox-item-properties
),我认为您希望将该类应用于容器元素,因此一个简单的解决方案是在组件的根目录中添加该元素(例如,
div
) :

// ItemProperties.vue
<template>
  <div>
    <section v-for="(item, index) in items" :key="index" class="box">
    ...
    </section>
  </div>
</template>

演示


10
投票

您还可以通过这样做来防止在子组件中传递属性:

export default defineComponent({
  name: "ChildComponentName",
  inheritAttrs: false // This..
})

来源:https://vuejs.org/guide/components/attrs.html


2
投票

Michael 的答案是正确的,但很多人仍然会犯这个错误,因为它是由一些文档未涵盖或不太直观的额外场景(边缘情况)触发的。

问题 回顾一下,触发错误是因为我们传递了一个属性(例如禁用),并且我们计划渲染的 vue 组件在其根中有 2 个或更多元素。 (迈克尔对此做了很好的解释)。

边缘情况:

  • 如果您有 if/else 语句也会触发此错误
  • 如果您的根元素旁边有评论,也会触发此错误
  • 如果您使用传送或转换,根元素是实际使用的 HTML 元素(因此,如果传送或转换块中有 2 个元素,则会触发此错误)。

我在这里详细介绍了此错误:https://zelig880.com/how-to-solve-extraneous-non-props-attributes-in-vue-js


1
投票

这也可以从路由定义中具有

props: true
的父组件触发。确保仅在实际需要的组件中添加
props: true
并具有一些路由参数作为 props。


0
投票

您将

class
属性传递给
ItemProperties
但未声明它

class
options api 中声明
props
应该可以解决这个问题。

ItemProperties.vue

...
export default {
  props:["class"],
  ...
}

0
投票

您可以将 defineProps 添加到脚本设置代码中,以消除此警告:

const props = defineProps(['class'])
© www.soinside.com 2019 - 2024. All rights reserved.