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

Vue结合Symfony项目无法从Ajax返回结果加载动态组件求助

解决方案

核心问题原因

你通过原生innerHTML接口插入的<gamecard>自定义标签,不会被已初始化的Vue实例自动编译。Vue只会在实例初始化挂载阶段编译一次对应挂载节点下的DOM,后续手动插入的自定义组件标签无法被识别渲染,仅会作为普通未知标签存在。此外你当前代码中重复注册了Gamecard组件,同步导入+异步导入的写法属于冗余逻辑,可删除其中一种。


方案1:推荐实现(Vue统一管理列表渲染,性能最优)

该方案完全由Vue控制组件渲染逻辑,避免混用原生DOM操作和Vue响应式逻辑。

1. 修改控制器AJAX响应

不再返回渲染后的Twig HTML片段,直接返回游戏数据的JSON数组:

if ($request->isXMLHttpRequest()) {
    $gameData = array_map(function($game) {
        return [
            'id' => $game->getId(),
            'name' => $game->getName(),
            'description' => $game->getDescription(),
            'tourneyscount' => count($game->getTourneys()) . ' active tourneys'
        ];
    }, $gameList);
    return new JsonResponse(
        [
            'code' => Response::HTTP_OK,
            'games' => $gameData
        ]
    );
}

return $this->render('home/index.html.twig', [
    'games' => $gameList
]);

2. 修改Twig模板,注入初始数据

在home/index.html.twig中注入初始游戏数据供Vue读取:

<div id="game-card">
    <gamecard
        v-for="game in games"
        :key="game.id"
        :name="game.name"
        :description="game.description"
        :tourneyscount="game.tourneyscount"
    ></gamecard>
</div>
<script>
window.initialGames = {{ games|json_encode(constant('JSON_HEX_TAG'))|raw }}
</script>

3. 调整Vue实例逻辑

import Vue from 'vue';
import Gamecard from './../../components/Gamecard'

new Vue({
    el: '#game-card',
    components: {
        Gamecard
    },
    data() {
        return {
            games: window.initialGames || [],
            page: 1,
            canLoad: true
        }
    },
    mounted() {
        // 绑定你原有的滚动监听逻辑
        window.addEventListener('scroll', this.handleScroll)
    },
    methods: {
        handleScroll() {
            // 替换为你原有的滚动到底部判断逻辑
            const scrollBottom = window.innerHeight + window.scrollY >= document.body.offsetHeight - 100
            if (scrollBottom && this.canLoad) {
                this.loadMore()
            }
        },
        async loadMore() {
            this.canLoad = false
            try {
                const res = await fetch(`?page=${this.page + 1}`, {
                    headers: {"X-Requested-With": "XMLHttpRequest"}
                })
                const data = await res.json()
                if (data.code === 200 && data.games.length) {
                    this.games = [...this.games, ...data.games]
                    this.page += 1
                    this.canLoad = true
                } else {
                    this.canLoad = false
                }
            } catch (e) {
                this.canLoad = false
            }
        }
    }
})

方案2:兼容现有代码的快速修复

如果你不想改动现有Twig渲染逻辑,可手动编译新插入的DOM节点,修改你的AJAX请求逻辑即可:

fetch('?page=' + page, {
    headers: {
        "X-Requested-With": "XMLHttpRequest"
    }
})
.then(response => response.json())
.then(function (response) {
    if (response.code === 200) {
        const container = document.getElementById('game-card')
        const tempNode = document.createElement('div')
        tempNode.innerHTML = response.cards
        // 逐个插入新节点并编译组件
        Array.from(tempNode.children).forEach(child => {
            const mountedNode = container.appendChild(child)
            new Vue({
                el: mountedNode,
                components: { Gamecard }
            })
        })
        canLoad = true;
    } else {
        canLoad = false;
    }
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 10:06:02