You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue.js 3模板无法渲染后端获取的Proxy数据问题求助

Vue.js 3中Proxy数组数据无法在模板显示排查

问题描述

已从后端成功获取数据,控制台显示为包含3个对象的Proxy数组,但数据无法在Vue.js 3模板中显示。

控制台输出

Proxy { <target>: (3) […], <handler>: {…} }

<target>: Array(3) [ {…}, {…}, {…} ]
​​
0: Object { id: 3, user_id_as_sender: 5, user_id_as_receiver: 4, … }
​​
1: Object { id: 2, user_id_as_sender: 5, user_id_as_receiver: 4, … }
​​
2: Object { id: 1, user_id_as_sender: 5, user_id_as_receiver: 4, … }
​​
length: 3
​​
<prototype>: Array []

<handler>: Object { _isReadonly: false, _shallow: false }

代码片段

HTML模板

<div class="card-body">
    <div class="table-responsive" v-if="pinboards">
        <table class="table table-head-custom table-vertical-center mt-5 mb-5">
            <thead>
            <tr>    
                <th>{{trans('custom.name')}}</th>
                <th>{{trans('custom.time')}} </th>
                <th>{{trans('custom.date')}}</th>
                <th v-if="userId == 'HumanResource' || userId == 'dispatcher'"  class="text-center">{{trans('custom.read')}}</th>
                <th class="text-right">{{trans('custom.action')}}</th>
            </tr>
            </thead>
            <tbody>
                <tr v-for="(document, index) in pinboards" :class="((document.user_id_as_receiver).split(',')).includes(String(current_user_id)) && !((document.is_read_by_receiver).split(',')).includes(String(current_user_id)) ? 'active' : ''" :key="index">
                    <td >
                        <a href="" @click.prevent="readMessage(index, document.id)">
                            <template v-if="document.is_grouped_msg">{{translateDocumentName(document.subject)}}</template>
                            <template v-else>{{document.user_name}} {{document.user_surname}}</template>
                        </a>
                    </td>
                    <td >{{document.updated_at | formatHours}}</td>
                    <td >{{document.updated_at | formatDate}}</td>
                    <td v-if="userId == 'HumanResource' || userId == 'dispatcher'" class="text-center">
                        <template v-if="!document.is_grouped_msg">
                            <i v-if="document.is_read_by_receiver != 0" class="la la-check-double text-success"></i>
                            <i v-else class="la la-check-double"></i>
                        </template>
                        <template v-else>
                            {{(((document.is_read_by_receiver).split(',')).length)-1}} / {{((document.user_id_as_receiver).split(',')).length}}
                        </template>
                    </td>
                    <td class="text-right">
                        <a @click.prevent="readMessage(index, document.id)" href="#" class="btn btn-sm btn-primary btn-clean delete" title="read">
                            <i class="la la-eye"></i> {{trans('custom.read')}}
                        </a>
                        <a @click.prevent="removeMessage(index, document.id, 'single')" href="#" class="btn btn-sm btn-danger btn-clean delete" title="Delete">
                            <i class="la la-trash"></i> {{trans('custom.delete')}}
                        </a>
                        <a v-if="current_user_id == document.user_id_as_sender" @click.prevent="removeMessage(index, document.id, 'all')" href="#" class="btn btn-sm btn-danger btn-clean delete" title="Delete from all">
                            <i class="la la-trash"></i> {{trans('custom.deleteFromAll')}}
                        </a>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>

    <p class="text-center" v-else>{{trans('custom.noPinboard')}}</p>
</div>

JavaScript代码

getPinboards() 
{
    let that = this;

    const url = new URLSearchParams(window.location.search);
    const column_id = url.get("column_id");
    const user_id = url.get("u_id");
    
    if (column_id && user_id) {
        axios.get(`/get-pinboard/${column_id}/${user_id}`)
            .then(function(response){
                if(response.data.success){
                    that.pinboards = response.data.pinboards;
                }else{
                    toastr.error("Error getting pinboards!");
                }
            });
    } else {
        axios.get('/get-pinboard')
            .then(function(response){
                if(response.data.success){
                    that.pinboards = response.data.pinboards;
                    console.log(that.pinboards);

                }else{
                    toastr.error("Error getting pinboards!");
                }
            });
    }
},

排查原因及解决方法

  • Vue 3已移除过滤器语法:模板中使用的formatHours和formatDate是Vue 2的过滤器写法,Vue 3不再支持该语法,会导致模板渲染报错,进而无法显示内容。解决方法是将过滤器替换为组件方法或计算属性,比如定义formatHours(date)方法,模板中改为{{ formatHours(document.updated_at) }}。

  • pinboards初始值未正确声明:如果pinboards在组件data中未初始化为空数组[],而是默认的undefined,赋值后虽会转为响应式Proxy,但可能导致v-if="pinboards"初始状态为false,赋值后无法触发模板重新渲染。解决方法是在data()中明确声明pinboards: []。

  • 复杂表达式的容错问题:v-for中的:class表达式直接对document.user_id_as_receiver调用split(','),若该字段为数字或null,会抛出错误导致渲染失败。解决方法是添加容错处理,改为(document.user_id_as_receiver || '').split(','),确保调用split的是字符串类型。

  • 响应式变量声明问题:若pinboards未通过Vue响应式API声明(如选项式API的data,或组合式API的ref/reactive),赋值后无法触发模板更新。需确认pinboards是组件data中定义的响应式变量。

内容的提问来源于stack exchange,提问作者Mohammad Murad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 22:04:56