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

Magento 2顶部菜单内容加载优化:悬停触发或页面加载后加载

实现Magento顶部菜单内容按需加载(悬停/页面加载完成后)

方案一:鼠标首次悬停时加载(仅加载一次)

这种方式会在用户第一次把鼠标移到顶部菜单时,通过AJAX拉取自定义phtml内容,之后缓存内容,无需每次悬停重复请求。

步骤1:修改原有模板,预留容器

将现有phtml替换为空占位容器,后续通过JS填充内容:

<?php
/**
 * @var $block Menu
 */
use MyStore\Widget\Block\Widget\Menu;
?>
<div class="header-widget-block" id="header-widget-container" data-block-url="<?= $block->getUrl('widget/menu/load') ?>">
    <!-- 内容将通过JS动态加载 -->
</div>

步骤2:创建AJAX控制器

在模块MyStore/Widget下创建控制器Controller/Menu/Load.php,负责渲染并返回phtml内容:

<?php
namespace MyStore\Widget\Controller\Menu;

use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\View\Result\PageFactory;

class Load implements HttpGetActionInterface
{
    protected $resultPageFactory;

    public function __construct(PageFactory $resultPageFactory)
    {
        $this->resultPageFactory = $resultPageFactory;
    }

    public function execute()
    {
        $resultPage = $this->resultPageFactory->create();
        $block = $resultPage->getLayout()->createBlock(\MyStore\Widget\Block\Widget\Menu::class);
        return $this->resultPageFactory->create()->getLayout()->renderElement($block->getNameInLayout());
    }
}

步骤3:添加JS处理悬停事件

在主题或模块中添加JS文件web/js/header-widget-loader.js,处理悬停触发逻辑:

require(['jquery'], function($) {
    $(document).ready(function() {
        var $widgetContainer = $('#header-widget-container');
        var isLoaded = false;
        var loadUrl = $widgetContainer.data('block-url');

        // 替换为你的顶部菜单实际选择器,比如'.main-nav-item'
        $('.main-nav-item').on('mouseenter', function() {
            if (!isLoaded) {
                $.ajax({
                    url: loadUrl,
                    type: 'GET',
                    beforeSend: function() {
                        // 可选:添加加载状态提示
                        $widgetContainer.html('<div class="loading">加载中...</div>');
                    },
                    success: function(response) {
                        $widgetContainer.html(response);
                        isLoaded = true; // 标记已加载,避免重复请求
                    },
                    error: function() {
                        $widgetContainer.html('<div class="error">加载失败,请重试</div>');
                    }
                });
            }
        });
    });
});

在模块requirejs-config.js中注册该JS:

var config = {
    map: {
        '*': {
            headerWidgetLoader: 'MyStore_Widget/js/header-widget-loader'
        }
    }
};

最后在布局文件中引入JS:

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <head>
        <script src="MyStore_Widget/js/header-widget-loader.js"/>
    </head>
</page>

方案二:页面完全加载完成后自动加载

如果不需要悬停触发,仅需等页面所有资源加载完成后再加载内容,可简化如下:

修改模板(同方案一,保留空容器)

<?php
/**
 * @var $block Menu
 */
use MyStore\Widget\Block\Widget\Menu;
?>
<div class="header-widget-block" id="header-widget-container" data-block-url="<?= $block->getUrl('widget/menu/load') ?>">
    <!-- 内容将通过JS动态加载 -->
</div>

修改JS逻辑

将悬停触发改为页面加载完成后自动请求:

require(['jquery'], function($) {
    // 等待页面所有资源(图片、样式等)加载完成
    $(window).on('load', function() {
        var $widgetContainer = $('#header-widget-container');
        var loadUrl = $widgetContainer.data('block-url');

        $.ajax({
            url: loadUrl,
            type: 'GET',
            beforeSend: function() {
                $widgetContainer.html('<div class="loading">加载中...</div>');
            },
            success: function(response) {
                $widgetContainer.html(response);
            },
            error: function() {
                $widgetContainer.html('<div class="error">加载失败,请重试</div>');
            }
        });
    });
});

控制器部分与方案一完全一致,无需修改。


额外注意事项

  • 替换代码中的.main-nav-item为你顶部菜单触发元素的实际CSS选择器
  • 确保控制器路由在etc/frontend/routes.xml中正确配置:
    <?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
        <router id="standard">
            <route id="widget" frontName="widget">
                <module name="MyStore_Widget"/>
            </route>
        </router>
    </config>
    
  • 若phtml作为widget使用,需确保控制器创建Block时能正确获取widget配置参数(如link、image),如需传递参数可在AJAX请求中携带。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 04:35:19