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

Vue Composition API如何向Razor Page传递事件与值?

技术场景与问题

在基于ASP.NET Razor构建的页面中嵌入Vue组件(因现有系统架构复杂度,选择组件形式集成Vue)。Vue组件内包含带顶部筛选面板的DataGrid,支持按周期维度加载数据;Razor页面上的现有ReportViewer报表组件需要获取Vue面板的选择值(如目标周期ID、目标值等)来重新加载报表,同时需根据Vue面板中复选框的状态切换报表与DataGrid的显示状态。

现有困惑

  1. 如何在Vue Composition API中通过emit向Razor Page传递事件与选中参数值?
  2. 在Razor Page接收到这些参数后,需要执行哪些操作来重新加载ReportViewer组件?

相关代码片段

Vue组件代码

<template>
    <DxForm :col-count="1"
            :show-colon-after-label="true"
            :show-validation-summary="true"
            :columnWidth="100"
            @field-data-changed="onHandleFieldDataChanged">
        <DxGroupItem :col-count="3">
            <DxItem data-field="ViewType"
                    editor-type="dxLookup"
                    :label="{ text: formatMessage('lblSelectView') }"
                    :editor-options="{ items: viewTypes, valueexpr: 'value', displayexpr: 'text' }">
            </DxItem>
            <DxItem data-field="equityGoalLookup"
                    editor-type="dxLookup"
                    :label="{ text: formatMessage('lblSelectGoal') }"
                    :editor-options="{ dataSource: goalPeriodDataStore, valueExpr: 'value', displayExpr: 'text' }"
                    :visible="goalSelectVisible">
                <DxLabel text="Select Goal" />
            </DxItem>
            <DxItem data-field="targetLookup"
                    editor-type="dxLookup"
                    :label="{ text: formatMessage('lblSelectTarget') }"
                    :editor-options="{ dataSource: targetPeriodDataStore, valueExpr: 'value', displayExpr: 'text' }"
                    :visible="targetSelectVisible">
                <DxLabel text="Select Target" />
            </DxItem>
            <DxItem data-field="compareToActuals"
                    editor-type="dxCheckBox"
                    :label="{ text: formatMessage('lblCompareActuals') }"
                    :visible="compareToActualsVisible">
            </DxItem>
        </DxGroupItem>
    </DxForm>
</template>

<script setup>
const area = "Company.EmploymentEquityValue";
initLocale(area);

function onHandleFieldDataChanged(e) {
    employmentEquityService.HandleFieldDataChanged(e);

    emit("goalPeriodId", e.value);
    emit("targetPeriodId", e.value);
    console.log(props.filterPanel);
    if (props.filterPanel) {
        props.filterPanel.goalPeriodId = e.value;
    }
}

const panelHandleChange = (event) => {
    emit("customChange", event.target.value)
}

return {
    panelHandleChange,
    onHandleFieldDataChanged
}
</script>

Razor Page代码

@section scripts {
    <script>
        DevExpress.Analytics.Utils.ajaxSetup.ajaxSettings.headers = DevExpress.Analytics.Utils.ajaxSetup.ajaxSettings.headers || {};
        DevExpress.Analytics.Utils.ajaxSetup.ajaxSettings.headers["X-Parameters"] = "@Model.Parameters";
    </script>
}
<script type="module" src="~/pages/company-employment-equity-plan.js"></script>

<page-content>
    <div class="panel-box">
        <div class="panel-box__content">
            <div class="panel-box__body">
                <company-employment-equity-plan 
                    allow-edit=@Model.AllowEdit
                    api-endpoint="@Url.Action("Get", "EquityValueApi")"
                    api-equity-plan-goal-endpoint="@Url.Action("GetEquityPlanGoals", "EquityValueApi")"
                    api-equity-plan-target-endpoint="@Url.Action("GetEquityPlanTargets", "EquityValueApi")"
                    :filter-panel=@Model />
            </div>
        </div>
    </div>
    <div style="height:700px;">
        @await Component.InvokeAsync("ReportViewer", new
               {
                    Name = "EmploymentEquityPlanGoalVsActual/EmploymentEquityPlanGoalVsActual.repx",
                   Parameters = $"CompanyId={6464}&EffectiveDate=2023-02-01&UserId={Model.UserId}&pkEquityPlanPeriodIDGoal={Model.GoalPeriodId}",
                   ShowParameters = false
               })
    </div>

    <script type="text/html" id="equity-report"></script>
    <script>

    </script>
</page-content> 

解决方案

1. Vue Composition API中通过emit传递参数给Razor Page

修正Vue组件的emit逻辑,统一事件名称并传递完整筛选参数集合,避免直接修改props(props为单向数据流):

<script setup>
const props = defineProps({
    filterPanel: Object
});

const area = "Company.EmploymentEquityValue";
initLocale(area);

// 统一传递筛选更新事件
const emitFilterUpdate = (filterData) => {
    emit('filter-updated', filterData);
};

function onHandleFieldDataChanged(e) {
    employmentEquityService.HandleFieldDataChanged(e);
    
    // 收集所有筛选字段的最新值,根据实际表单结构调整
    const filterData = {
        goalPeriodId: e.dataField === 'equityGoalLookup' ? e.value : props.filterPanel?.goalPeriodId,
        targetPeriodId: e.dataField === 'targetLookup' ? e.value : props.filterPanel?.targetPeriodId,
        compareToActuals: e.dataField === 'compareToActuals' ? e.value : props.filterPanel?.compareToActuals,
        viewType: e.dataField === 'ViewType' ? e.value : props.filterPanel?.ViewType
    };
    
    emitFilterUpdate(filterData);
}

return {
    onHandleFieldDataChanged
}
</script>

在Razor页面的Vue组件标签上添加事件监听:

<company-employment-equity-plan 
    allow-edit=@Model.AllowEdit
    api-endpoint="@Url.Action("Get", "EquityValueApi")"
    api-equity-plan-goal-endpoint="@Url.Action("GetEquityPlanGoals", "EquityValueApi")"
    api-equity-plan-target-endpoint="@Url.Action("GetEquityPlanTargets", "EquityValueApi")"
    :filter-panel=@Model
    @filter-updated="handleFilterUpdated" />

2. Razor Page接收参数后重新加载ReportViewer

在Razor页面的脚本中实现事件处理函数,通过DevExpress ReportViewer API刷新报表,并切换显示状态:

<script>
    let reportViewerInstance;

    // 初始化时获取ReportViewer实例
    document.addEventListener('DOMContentLoaded', () => {
        reportViewerInstance = DevExpress.Reporting.Viewer.ReportViewer.getInstance('#reportViewerContainer');
    });

    // 处理Vue传递的筛选参数
    function handleFilterUpdated(filterData) {
        // 组装新的报表参数
        const newParams = `CompanyId=${@Model.CompanyId}&EffectiveDate=2023-02-01&UserId=${@Model.UserId}&pkEquityPlanPeriodIDGoal=${filterData.goalPeriodId}&pkEquityPlanPeriodIDTarget=${filterData.targetPeriodId}`;
        
        // 刷新报表
        if(reportViewerInstance) {
            reportViewerInstance.openReport('EmploymentEquityPlanGoalVsActual/EmploymentEquityPlanGoalVsActual.repx', {
                parameters: newParams
            });
        }

        // 根据复选框状态切换报表与DataGrid的显示
        const reportContainer = document.querySelector('#reportViewerContainer');
        const dataGridContainer = document.querySelector('.panel-box__body');
        
        if(filterData.compareToActuals) {
            reportContainer.style.display = 'block';
            dataGridContainer.style.display = 'none';
        } else {
            reportContainer.style.display = 'none';
            dataGridContainer.style.display = 'block';
        }
    }
</script>

同时给ReportViewer容器添加ID:

<div id="reportViewerContainer" style="height:700px;">
    @await Component.InvokeAsync("ReportViewer", new
           {
                Name = "EmploymentEquityPlanGoalVsActual/EmploymentEquityPlanGoalVsActual.repx",
               Parameters = $"CompanyId={@Model.CompanyId}&EffectiveDate=2023-02-01&UserId={@Model.UserId}&pkEquityPlanPeriodIDGoal={@Model.GoalPeriodId}",
               ShowParameters = false
           })
</div>

内容的提问来源于stack exchange,提问作者Donald N. Mafa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 23:48:11