【问题标题】:Why are my object and array props becoming strings in child components?为什么我的对象和数组道具在子组件中变成了字符串?
【发布时间】:2020-05-25 05:40:11
【问题描述】:

我正在创建一个即时通讯工具作为 Vue.js 学习练习,我遇到了一个令人困惑的错误,其中数组和对象作为 props 传递给有槽的子组件访问正在变成字符串,并产生类似的错误:

[Vue 警告]:无效的道具:道具“messageGroup”的类型检查失败。预期的数组,得到值为“[object Object],[object Object],[object Object],[object Object]”的字符串。

[Vue 警告]:无效的道具:道具“消息”的类型检查失败。预期对象,得到值为“[object Object]”的字符串。

将原始类型作为子组件的道具传递可以按预期工作。 使用 :prop-name 或 v-bind:prop-name 传递对象和数组会产生字符串。

我该如何解决这个问题,或者我对如何解决这个问题的正确方法缺乏理解?

这是组件的完整代码以及它们的注册方式:

信使:

<template>
    <section id="messenger">
        <header>
            <h1>Test Conversation Window</h1>
        </header>
        <aside class="control-menu">
            Control Menu 
            <hr>
        </aside>
        <!-- The aggrieving section -->
        <main v-if="messageGroups.length" >
            <vue-message-group 
                v-for="(messageGroup, i) of messageGroups" 
                :key="i"
                v-bind:message-group="messageGroup"
                :username="messageGroup[0].username" >
                <vue-message 
                    v-for="message of messageGroup" :key="message.id"
                    v-bind:message="message" >
                </vue-message>
            </vue-message-group>
        </main>
        <!-- -- -->
        <aside class="participants">
            Participants
            <hr>
            <ul v-if="participants.length">
                <li v-for="(user, i) in participants" :key="i">
                    <img v-bind:src="user.avatar" v-bind:alt="user.username">
                    <span>{{ user.username }}</span>
                </li>
            </ul>
        </aside>
    </section>
</template>

<script>
export default {
    data() {
        return {
            participants: [],
            messageGroups: null,
        }
    },
    created() {
        this.getParticipants( [ 'john', 'karen' ] );
        this.messageGroups = this.groupMessages( this.testMessages() );
    },
    methods: {
        getParticipants: async function( users ) {
            this.url = 'http://*.*.*.*/api/user/';
            this.participants = await Promise.all( users.map( 
                async participant => 
                await this.getUserFromAPI( participant )
            ) );
        },
        getUserFromAPI: async function( username )
        {
            return await fetch( this.url + username )
                .then( data => data.json() )
                .then( data => data.data );
        },
        groupMessages: function( messages ) {
            let lastUsername = null;
            let groups = new Array();
            let group = null;
            for ( const message of messages )
            {
                if ( message.username !== lastUsername )
                {
                    group = new Array();
                    group.push( message );
                    groups.push( group );
                    lastUsername = message.username;
                }
                else
                {
                    group.push( message );
                }
            }
            return groups;
        },
        testMessages: function() {
            return [
                {
                    id: 0,
                    username: 'john',
                    message: 'TEST 1 message content.',
                    timestamp: '2020-05-20T23:09:13',
                },
                {
                    id: 1,
                    username: 'john',
                    message: 'TEST 2 message content.',
                    timestamp: '2020-05-20T23:09:13',
                },
                {
                    id: 2,
                    username: 'john',
                    message: 'TEST 3 message content.',
                    timestamp: '2020-05-20T23:09:13',
                },
                {
                    id: 3,
                    username: 'karen >:[',
                    message: 'TEST 4 message content.',
                    timestamp: '2020-05-20T23:09:13',
                },
                {
                    id: 4,
                    username: 'karen >:[',
                    message: 'TEST 5 message content.',
                    timestamp: '2020-05-20T23:09:13',
                },
                {
                    id: 5,
                    username: 'john',
                    message: 'TEST 6 message content.',
                    timestamp: '2020-05-20T23:09:13',
                },
                {
                    id: 6,
                    username: 'karen >:[',
                    message: 'TEST 7 message content.',
                    timestamp: '2020-05-20T23:09:13',
                },
                {
                    id: 7,
                    username: 'karen >:[',
                    message: 'TEST 8 message content.',
                    timestamp: '2020-05-20T23:09:13',
                },
                {
                    id: 8,
                    username: 'karen >:[',
                    message: 'TEST 9 message content.',
                    timestamp: '2020-05-20T23:09:13',
                },
                {
                    id: 9,
                    username: 'karen >:[',
                    message: 'TEST 10 message content.',
                    timestamp: '2020-05-20T23:09:13',
                },
            ];
        },
    },
}
</script>

消息组:

<template>
    <figure class="message">
        <main>
            <span>{{ username }}</span>
            <slot></slot>
        </main>
    </figure>
</template>
<script>
export default {
    props: {
        username: String,
        messageGroup: Array,
    },
}
</script>

消息:

<template>
    <div class="message">
        <span class="line">{{ message.message }}</span>
        <div class="timestamp">{{ message.timestamp }}</div>
    </div>
</template>
<script>
export default {
    props: {
        message: Object,
    },
}
</script>

App.js:

import Vue from 'vue'

import vueCustomElement from 'vue-custom-element'
/*
* See: https://github.com/karol-f/vue-custom-element
*/

Vue.use(vueCustomElement);

Vue.config.ignoredElements = [
    'vue-messenger',
    'vue-message-group',
    'vue-message',
];


import VueMessenger from './components/VueMessenger.vue'
const messengerStyles = require( '!css-loader!sass-loader!./components/css/VueMessenger.scss' );
Vue.customElement( 
    'vue-messenger', 
    VueMessenger, 
    {
        shadow: true,
        shadowCss: messengerStyles.toString(),
    } 
);

import VueMessageGroup from './components/VueMessageGroup.vue'
const messageGroupStyles = require( '!css-loader!sass-loader!./components/css/VueMessageGroup.scss' );
Vue.customElement( 
    'vue-message-group', 
    VueMessageGroup, 
    {
        shadow: true,
        shadowCss: messageGroupStyles.toString(),
    } 
);

import VueMessage from './components/VueMessage.vue'
const messageStyles = require( '!css-loader!sass-loader!./components/css/VueMessage.scss' );
Vue.customElement( 
    'vue-message', 
    VueMessage, 
    {
        shadow: true,
        shadowCss: messageStyles.toString(),
    } 
);

结果:

【问题讨论】:

标签: vue.js vuejs2 web-component custom-element


【解决方案1】:

问题源于我将 Vue 组件注册为浏览器的自定义元素;浏览器要求所有元素属性都是字符串,因此强制对象和数组。

最简单的解决方法似乎是传递对象属性而不是对象本身。

我正在尝试在 :props 中传递 json。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-03-14
    • 2021-04-11
    • 2019-11-17
    • 2022-11-20
    • 1970-01-01
    • 2021-11-10
    • 2015-02-20
    相关资源
    最近更新 更多