Magento 2.3 - Các tab Topmenu với lớp 'kích hoạt' sai (được lưu trong bộ nhớ cache)


10

Tôi có một vấn đề menu nhỏ. Các tab hoạt động không phù hợp với lớp hoạt động. Nếu tôi tắt static_blockbộ đệm, nó sẽ hoạt động trở lại, vì vậy nó thực sự trông giống như menu được lưu trong bộ nhớ cache và tiếp tục hiển thị nội dung được lưu trong bộ nhớ cache bất kể tab được chọn.
Tôi đã cố gắng đưa cacheable=falsevào khối topmenu liên quan đến default.xmlbố cục nhưng điều này không thay đổi gì cả.
nếu ai đó đã có vấn đề này hoặc có một khách hàng tiềm năng ...

Chỉnh sửa:
Tôi đã sửa nó một cách nhanh chóng, bằng cách xóa topmenu khỏi bộ đệm, (nếu tôi hiểu chính xác những gì tôi đã làm) nhưng như bạn có thể thấy nó không khủng khiếp, nhưng giờ nó hoạt động rất tốt

<?php

namespace MyNamespace\Indo\Block\Html;

use Magento\Framework\Data\Tree\NodeFactory;
use Magento\Framework\Data\TreeFactory;
use Magento\Framework\View\Element\Template;
use Magento\Framework\View\LayoutFactory;
use TemplateMonster\Megamenu\Helper\Data;

class Topmenu extends \Magento\Theme\Block\Html\Topmenu
{


    public $_helper;

    public $_layoutFactory;

    public function __construct(
        Template\Context $context,
        NodeFactory $nodeFactory,
        TreeFactory $treeFactory,
        Data $helper,
        LayoutFactory $layoutFactory,
        array $data = []
    )
    {
        parent::__construct($context, $nodeFactory, $treeFactory, $data);
        $this->_helper        = $helper;
        $this->_layoutFactory = $layoutFactory;
    }

    /**
     * Get block cache life time
     *
     * @return int
     * @since 100.1.0
     */
    protected function getCacheLifetime()
    {
        return 0;
    }
}

1
+1 cho câu hỏi hay;)
Chirag Patel

Câu trả lời:


4

Từ hiểu biết của tôi, không có giải pháp hoàn hảo cho vấn đề này. Bất cứ sửa chữa nào bạn quyết định thực hiện sẽ có nhược điểm của nó.

Tôi nghĩ cũng có thể có 2 kỹ thuật khác mà bạn có thể sử dụng đó là ESI (Edge Side Bao gồm) hoặc đục lỗ. Mặc dù tôi không có bất kỳ kinh nghiệm hoặc kiến ​​thức nào về những điều này, vì vậy nếu đây là những kỹ thuật hợp lệ cho mục đích này. Tôi sẽ để người khác hiểu rõ hơn về họ đề cập giải thích cho họ.

TLD

Nếu bạn muốn điều hướng luôn hiển thị trạng thái hoạt động chính xác và không ngại thực hiện một cú đánh hiệu suất nhỏ, thì hãy tắt bộ đệm ẩn trên khối điều hướng và cố gắng giữ nó càng gần khối gốc càng tốt.

Nếu bạn muốn hiệu suất tối đa, thì hãy tắt kết xuất phía máy chủ và hy vọng khách truy cập đã bật JS.


Tổng quat

Trong lõi Magento, có cả logic phía máy chủ và phía máy khách để đặt trạng thái hoạt động trên các mục điều hướng. Và theo mặc định, cả logic máy chủ và máy khách đều hoạt động vì một số lý do.

Logic phía máy chủ

Vấn đề với việc sử dụng logic phía máy chủ cho việc này là bạn không thể lưu trữ khối vì bạn cũng sẽ lưu vào trạng thái hoạt động đó. Khi bạn tắt bộ đệm ẩn cho menu điều hướng, trường hợp tốt nhất là bạn chỉ làm mất hiệu lực bộ đệm toàn bộ trang, trường hợp xấu hơn là bạn làm mất hiệu lực một số khối khác như tiêu đề, v.v. tùy thuộc vào cách thiết lập chủ đề của bạn.

Logic phía máy chủ có thể được tìm thấy trong Magento\Theme\Block\Html\Topmenu::_getMenuItemClasses() Nó sử dụng các thuộc tính is_activehas_activetrên thuộc tính nút cây đã qua, được đặt trongMagento\Catalog\Plugin\Block\Topmenu::getCategoryAsArray

Logic phía khách hàng

Nhược điểm của phương thức này là, không có trạng thái hoạt động được đánh dấu cho đến khi tải JS. Và nếu máy khách đã bị vô hiệu hóa thì họ sẽ không có chỉ báo hoạt động nào cả.

Hàm xử lý logic phía máy khách là lib/web/mage/menu.js::_setActiveMenu() cách chức năng này hoạt động là nó tìm kiếm href của các mục điều hướng nếu kiểm tra xem có khớp với URL hiện tại không.


Các giải pháp

Vô hiệu hóa bộ nhớ đệm

Bạn có thể tắt bộ đệm ẩn trên khối điều hướng, điều này cũng sẽ vô hiệu hóa bộ đệm ẩn trên các khối cha. Vì vậy, nếu khối điều hướng của bạn nằm trong khối tiêu đề, thì tiêu đề của bạn sẽ không được lưu trong bộ nhớ cache.

Bạn có thể làm điều này, bằng cách đặt nút xml TTLtrên đó giống như ghi đè lên khối và ghi đè thời gian lưu trữ bộ đệm như bạn đã thực hiện là chỉnh sửa của mình.catalog.topnav0

<reference name="catalog.topnav" ttl="0"/>

Sử dụng logic phía máy khách

Phương pháp khác mà bạn có là vô hiệu hóa trạng thái hoạt động được hiển thị ở phía máy chủ và dựa vào logic phía máy khách.

Magento\Theme\Block\Html\Topmenu::_getMenuItemClasses()phương thức này là riêng tư, chúng tôi không thể sử dụng plugin để sửa đổi kết quả của nó. Bạn có thể ghi đè lên lớp bằng cách sử dụng tùy chọn và

  • gọi phương thức cha và loại bỏ activehas-activetừ mảng cuối cùng
  • xác định lại phương thức không bao gồm logic trong đó nó thêm lớp hoạt động.

Vậy ,,, chúng ta làm gì sau đó? Bạn có nói rằng tất cả những người sử dụng Magento sẽ phải đối mặt với vấn đề này? Tôi mới nâng cấp từ 2.2.5 lên 2.2.9 và vấn đề này xuất hiện. Lớp hoạt động không thay đổi và hai menu hoạt động xuất hiện cùng nhau ở lối vào.
Mohammed Joraid

2

Giải pháp @arno trong câu hỏi ban đầu hoạt động hoàn hảo với tôi nhưng tôi muốn mở rộng một chút về cách triển khai mã. Cũng như đơn giản hóa mã không cần thiết.

Tạo một mô-đun tùy chỉnh cho các thay đổi

ứng dụng / mã / VendorName / ModuleName / đăng ký.php

<?php
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'VendorName_ModuleName',
__DIR__
);

ứng dụng / mã / VendorName / ModuleName / etc / module.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="VendorName_ModuleName" setup_version="1.0.0">
        <sequence>
            <module name="Magento_Theme"/>
        </sequence>
    </module>
</config>

ứng dụng / mã / VendorName / ModuleName / etc / di.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Theme\Block\Html\Topmenu" type="VendorName\ModuleName\Block\Html\Topmenu" />
</config>

ứng dụng / mã / VendorName / ModuleName / Block / Html / Topmenu.php

<?php

namespace VendorName\ModuleName\Block\Html;

class Topmenu extends \Magento\Theme\Block\Html\Topmenu
{
    /**
     * Get block cache life time
     *
     * @return int
     * @since 100.1.0
     */
    protected function getCacheLifetime()
    {
        return 0;
    }
}

+1 Tôi mới sử dụng M2 vì vậy điều này đã giúp tôi ra ngoài
AdRock

1

Giải pháp của bạn có vẻ tốt, nhưng theo hiểu biết của tôi nếu bạn được đặt CacheLifetimesố 0 thì nó sẽ vô hiệu hóa bộ đệm cho trang đó, nó hoạt động giống nhưcacheable=false

Vì vậy, tôi muốn khuyên bạn nên xóa bộ nhớ cache theo chương trình thay vì đặt CacheLifetimesố không.

Bạn có thể xóa bộ nhớ cache lập trình bằng cách sử dụng cách dưới đây.

Xác định hàm tạo - truyền Magento\Framework\App\Cache\TypeListInterfaceMagento\Framework\App\Cache\Frontend\Poolcho hàm tạo của tệp của bạn như được định nghĩa bên dưới.

public function __construct(
    Context $context,
    \Magento\Framework\App\Cache\TypeListInterface $cacheTypeList,
    \Magento\Framework\App\Cache\Frontend\Pool $cacheFrontendPool
) {
    parent::__construct($context);
    $this->_cacheTypeList = $cacheTypeList;
    $this->_cacheFrontendPool = $cacheFrontendPool;
}

Bây giờ thêm đoạn mã sau vào phương thức mà bạn muốn clear/flushbộ đệm

$types = array('config','layout','block_html','collections','reflection','db_ddl','eav','config_integration','config_integration_api','full_page','translate','config_webservice');
foreach ($types as $type) {
    $this->_cacheTypeList->cleanType($type);
}
foreach ($this->_cacheFrontendPool as $cacheFrontend) {
    $cacheFrontend->getBackend()->clean();
}

Vì vậy, theo cách này, bạn có thể làm sạch và xóa bộ nhớ cache.

Lưu ý: Trong đoạn mã trên $types=tôi đã xác định tất cả các loại bộ đệm. bạn có thể xác định loại bộ đệm theo yêu cầu của bạn.

Có một phương pháp khác để xóa bộ đệm nếu bạn không muốn ghi loại bộ đệm được mã hóa cứng

public function __construct(
    \Magento\Framework\App\Cache\Manager $cacheManager
) {
    $this->cacheManager = $cacheManager;
}

private function whereYouNeedToCleanCache()
{
    $this->cacheManager->flush($this->cacheManager->getAvailableTypes());

    // or this
    $this->cacheManager->clean($this->cacheManager->getAvailableTypes());
}

Tôi hy vọng nó sẽ giúp!


1
Nếu bạn thêm mã tuôn bộ đệm đó vào một trong các trang danh mục lối vào thì đó sẽ là một sự tiêu hao hiệu suất lớn. Bộ nhớ cache đồng thời đọc và ghi sẽ làm cạn kiệt tài nguyên máy chủ. Đây là một vấn đề nhỏ, anh ta không nên vô hiệu hóa / xóa bộ đệm trang hoặc chặn bộ đệm cho một trục trặc hình ảnh nhỏ.
che khuất

@obscure Nó có thể là một cống hiệu suất. cường độ của tôi chỉ là để tránh chơi nhiều hơn với cache lifetime& cachable=falsebởi vì đó là bộ đệm bị vô hiệu hóa cho toàn bộ trang và có thể xảy ra sự cố mới. Cảm ơn.
Chirag Patel

Nếu chúng ta sử dụng bộ đệm bộ đệm bằng lập trình thì phần tử không được hiển thị từ bộ đệm. tôi cũng đã phải đối mặt với vấn đề này 1 năm trước với bộ nhớ cache magento.stackexchange.com/questions/229527/ory
Chirag Patel
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.