如何在拉拉维尔刀片中进行一次性推送

2022-08-30 22:54:59

我正在尝试使用Laravel刀片创建一个HTML小部件,类似于以下内容(widget.blade.php):

@push('scripts')
   <script src="{{ asset('js/foo.js') }}"></script>
   <script>
   ...
   </script>
@endpush
@push('styles')
   <link href="{{ asset('css/bar.css') }}" rel="stylesheet">
@endpush
<div>
... HTML contents
</div>

我在另一个边栏选项卡中使用小部件,例如:

<div>
  ... 
  @include('widget')
</div>
<div>
  ... 
  @include('widget')
</div>

问题是,当我在一个页面中多次使用小部件时,“脚本”和“样式”重复了多次。

如何防止Laravel多次推送“脚本”和“样式”?


答案 1

从Laravel 7.25开始,Blade现在包含一个新的@once组件,该组件只能渲染一次标签内的项目。https://laravel.com/docs/8.x/blade#the-once-directive

在下面的答案中,我假设您熟悉Blade扩展。这种方法已经在Laravel 5.2和5.3上进行了测试(请参阅下面的注释)。

在测试了Ismail RBOUH的答案(所以请阅读它)之后,似乎解决方案有两个问题:

1-$isDisplayed变量与其他包含的小部件不在同一范围内,因此每个@include将其脚本推送到堆栈。因此,我将其更改为:

Blade::directive('pushonce', function ($expression) {
    $isDisplayed = '__pushonce_'.trim(substr($expression, 2, -2));
    return "<?php if(!isset(\$__env->{$isDisplayed})): \$__env->{$isDisplayed} = true; \$__env->startPush{$expression}; ?>";
});
Blade::directive('endpushonce', function ($expression) {
    return '<?php $__env->stopPush(); endif; ?>';
});

2-解决方案将@pushonce的使用限制为一个小部件。即,在2个或多个小部件(widget1.blade.php,widget2.blade.php,...)的情况下,它可以阻止推送其他小部件脚本。因此,我使用以下代码将域添加到@pushonce:

Blade::directive('pushonce', function ($expression) {
    $domain = explode(':', trim(substr($expression, 2, -2)));
    $push_name = $domain[0];
    $push_sub = $domain[1];
    $isDisplayed = '__pushonce_'.$push_name.'_'.$push_sub;
    return "<?php if(!isset(\$__env->{$isDisplayed})): \$__env->{$isDisplayed} = true; \$__env->startPush('{$push_name}'); ?>";
});
Blade::directive('endpushonce', function ($expression) {
    return '<?php $__env->stopPush(); endif; ?>';
});

用法:

小部件1.刀片.php

@pushonce('scripts:widget1')
   <script src="{{ asset('js/foo.js') }}"></script>
   <script>
   ...
   </script>
@endpushonce

小部件2.刀片.php

@pushonce('scripts:widget2')
   <script src="{{ asset('js/bar.js') }}"></script>
   <script>
   ...
   </script>
@endpushonce

注意 L 5.3:更改以下行:

$domain = explode(':', trim(substr($expression, 2, -2)));

$domain = explode(':', trim(substr($expression, 1, -1)));

答案 2

这对我有用。

@once
    @push('page_scripts')
        <script type="text/javascript">
           
        </script>
    @endpush
@endonce

推荐