소스 검색

异步渲染组件优化

jqh 4 년 전
부모
커밋
ed2301e23d

+ 20 - 0
src/Contracts/LazyRenderable.php

@@ -0,0 +1,20 @@
+<?php
+
+namespace Dcat\Admin\Contracts;
+
+interface LazyRenderable
+{
+    /**
+     * 获取请求地址
+     *
+     * @return string
+     */
+    public function getUrl();
+
+    /**
+     * 渲染组件.
+     *
+     * @return mixed
+     */
+    public function render();
+}

+ 11 - 5
src/Controllers/RenderableController.php

@@ -3,8 +3,8 @@
 namespace Dcat\Admin\Controllers;
 
 use Dcat\Admin\Admin;
+use Dcat\Admin\Contracts\LazyRenderable;
 use Dcat\Admin\Support\Helper;
-use Dcat\Admin\Support\LazyRenderable;
 use Illuminate\Http\Request;
 
 class RenderableController
@@ -18,8 +18,6 @@ class RenderableController
     {
         $renderable = $this->newRenderable($request);
 
-        $renderable::collectAssets();
-
         $this->addScript();
 
         $this->forgetDefaultAssets();
@@ -39,13 +37,21 @@ class RenderableController
             .$asset->styleToHtml();
     }
 
-    protected function newRenderable(Request $request)
+    protected function newRenderable(Request $request): LazyRenderable
     {
         $class = $request->get('renderable');
 
         $class = str_replace('_', '\\', $class);
 
-        return new $class($request->all());
+        $renderable = new $class();
+
+        $renderable->payload($request->all());
+
+        if (method_exists($renderable, 'collectAssets')) {
+            $renderable->collectAssets();
+        }
+
+        return $renderable;
     }
 
     protected function addScript()

+ 1 - 1
src/Grid/Displayers/Expand.php

@@ -3,8 +3,8 @@
 namespace Dcat\Admin\Grid\Displayers;
 
 use Dcat\Admin\Admin;
+use Dcat\Admin\Contracts\LazyRenderable;
 use Dcat\Admin\Support\Helper;
-use Dcat\Admin\Support\LazyRenderable;
 use Illuminate\Support\Str;
 
 class Expand extends AbstractDisplayer

+ 2 - 2
src/Grid/Displayers/Modal.php

@@ -2,8 +2,8 @@
 
 namespace Dcat\Admin\Grid\Displayers;
 
+use Dcat\Admin\Contracts\LazyRenderable;
 use Dcat\Admin\Support\Helper;
-use Dcat\Admin\Support\LazyRenderable;
 use Dcat\Admin\Widgets\Modal as WidgetModal;
 
 class Modal extends AbstractDisplayer
@@ -17,7 +17,7 @@ class Modal extends AbstractDisplayer
 
     protected function setUpLazyRenderable(LazyRenderable $renderable)
     {
-        return clone $renderable->with('key', $this->getKey());
+        return clone $renderable->payload(['key' => $this->getKey()]);
     }
 
     public function display($callback = null)

+ 1 - 5
src/Grid/Filter.php

@@ -225,9 +225,7 @@ class Filter implements Renderable
      */
     protected function formatFilterId()
     {
-        $gridName = $this->model->grid()->getName();
-
-        return 'filter-box'.($gridName ? '-'.$gridName : '');
+        return 'filter-box'.Str::random(8);
     }
 
     /**
@@ -382,8 +380,6 @@ class Filter implements Renderable
     {
         $this->name = $name;
 
-        $this->setFilterID("{$this->name}-{$this->filterID}");
-
         return $this;
     }
 

+ 1 - 3
src/Grid/LazyRenderable.php

@@ -38,7 +38,7 @@ abstract class LazyRenderable extends Renderable
      */
     public function simple(bool $value = true)
     {
-        return $this->with('_simple_', $value);
+        return $this->payload(['_simple_' => $value]);
     }
 
     /**
@@ -58,8 +58,6 @@ abstract class LazyRenderable extends Renderable
             $grid->disableBatchDelete();
             $grid->disableRefreshButton();
 
-            $grid->toolsWithOutline(false);
-
             $grid->filter()
                 ->panel()
                 ->view('admin::filter.tile-container');

+ 9 - 38
src/Support/LazyRenderable.php

@@ -2,45 +2,26 @@
 
 namespace Dcat\Admin\Support;
 
+use Dcat\Admin\Contracts\LazyRenderable as Renderable;
 use Dcat\Admin\Admin;
-use Illuminate\Contracts\Support\Renderable;
+use Dcat\Admin\Traits\LazyWidget;
 
 abstract class LazyRenderable implements Renderable
 {
+    use LazyWidget;
+
     protected static $js = [];
 
     protected static $css = [];
 
-    protected $parameters = [];
-
-    public function __construct(array $parameters = null)
-    {
-        $this->with($parameters);
-    }
-
-    public function with($key, $value = null)
+    public function __construct(array $payload = [])
     {
-        if (is_array($key)) {
-            $this->parameters = array_merge($this->parameters, $key);
-        } elseif ($key !== null) {
-            $this->parameters[$key] = $value;
-        }
-
-        return $this;
-    }
-
-    public function getUrl()
-    {
-        $data = array_merge($this->parameters(), [
-            'renderable' => str_replace('\\', '_', static::class),
-        ]);
-
-        return route(admin_api_route('render'), $data);
+        $this->payload($payload);
     }
 
-    public function parameters()
+    public static function make(...$params)
     {
-        return $this->parameters;
+        return new static(...$params);
     }
 
     public static function collectAssets()
@@ -49,18 +30,8 @@ abstract class LazyRenderable implements Renderable
         Admin::css(static::$css);
     }
 
-    public static function make(...$params)
-    {
-        return new static(...$params);
-    }
-
-    public function __set($name, $value)
-    {
-        $this->with($name, $value);
-    }
-
     public function __get($name)
     {
-        return $this->parameters[$name] ?? null;
+        return $this->payload[$name] ?? null;
     }
 }

+ 0 - 43
src/Traits/AsyncRenderable.php

@@ -1,43 +0,0 @@
-<?php
-
-namespace Dcat\Admin\Traits;
-
-use Dcat\Admin\Support\LazyRenderable;
-
-trait AsyncRenderable
-{
-    /**
-     * @var LazyRenderable
-     */
-    protected $renderable;
-
-    /**
-     * 获取请求地址
-     *
-     * @return string|null
-     */
-    public function getRequestUrl()
-    {
-        return optional($this->getRenderable())->getUrl();
-    }
-
-    /**
-     * @param LazyRenderable $renderable
-     *
-     * @return $this
-     */
-    public function setRenderable(?LazyRenderable $renderable)
-    {
-        $this->renderable = $renderable;
-
-        return $this;
-    }
-
-    /**
-     * @return LazyRenderable
-     */
-    public function getRenderable()
-    {
-        return $this->renderable;
-    }
-}

+ 2 - 2
src/Traits/HasFormResponse.php

@@ -105,14 +105,14 @@ trait HasFormResponse
     protected function getCurrentUrl(Request $request = null)
     {
         if ($this->currentUrl) {
-            return $this->currentUrl;
+            return admin_url($this->currentUrl);
         }
 
         /* @var Request $request */
         $request = $request ?: (empty($this->request) ? request() : $this->request);
 
         if ($current = $request->get(static::CURRENT_URL_NAME)) {
-            return url($current);
+            return admin_url($current);
         }
 
         $query = $request->query();

+ 68 - 0
src/Traits/InteractsWithRenderApi.php

@@ -0,0 +1,68 @@
+<?php
+
+namespace Dcat\Admin\Traits;
+
+use Dcat\Admin\Contracts\LazyRenderable;
+
+/**
+ * @property string $target
+ */
+trait InteractsWithRenderApi
+{
+    /**
+     * @var LazyRenderable
+     */
+    protected $renderable;
+
+    /**
+     * @var string
+     */
+    protected $loadScript;
+
+    /**
+     * 监听异步渲染完成事件.
+     *
+     * @param string $script
+     *
+     * @return $this
+     */
+    public function onLoad(string $script)
+    {
+        $this->loadScript .= ";{$script}";
+
+        return $this;
+    }
+
+    public function getRenderable()
+    {
+        return $this->renderable;
+    }
+
+    public function setRenderable(LazyRenderable $renderable)
+    {
+        $this->renderable = $renderable;
+
+        return $this;
+    }
+
+    protected function getRenderableScript()
+    {
+        if (! $this->getRenderable()) {
+            return;
+        }
+
+        $url = $this->renderable->getUrl();
+
+        return <<<JS
+target.on('{$this->target}:load', function () {
+    Dcat.helpers.asyncRender('{$url}', function (html) {
+        body.html(html);
+        
+        {$this->loadScript}
+        
+        target.trigger('{$this->target}:loaded');
+    });
+});
+JS;
+    }
+}

+ 29 - 0
src/Traits/LazyWidget.php

@@ -0,0 +1,29 @@
+<?php
+
+namespace Dcat\Admin\Traits;
+
+trait LazyWidget
+{
+    protected $payload = [];
+
+    public function payload(array $payload)
+    {
+        $this->payload = array_merge($this->payload, $payload);
+
+        return $this;
+    }
+
+    public function getUrl()
+    {
+        $data = array_merge($this->payload, [
+            'renderable' => $this->getRenderableName(),
+        ]);
+
+        return route(admin_api_route('render'), $data);
+    }
+
+    protected function getRenderableName()
+    {
+        return str_replace('\\', '_', static::class);
+    }
+}

+ 6 - 6
src/Widgets/AsyncTable.php

@@ -36,7 +36,7 @@ class AsyncTable extends Widget
      * @param LazyRenderable $renderable
      * @param bool $load
      */
-    public function __construct(LazyRenderable $renderable, bool $load = true)
+    public function __construct(LazyRenderable $renderable = null, bool $load = true)
     {
         $this->from($renderable);
         $this->load($load);
@@ -88,10 +88,6 @@ class AsyncTable extends Widget
     {
         $this->simple = $value;
 
-        if ($value) {
-            $this->class('simple-grid', true);
-        }
-
         return $this;
     }
 
@@ -141,7 +137,11 @@ JS;
     public function render()
     {
         if ($this->simple !== null) {
-            $this->renderable->simple();
+            $this->renderable->simple($this->simple);
+
+            if ($this->simple) {
+                $this->class('simple-grid', true);
+            }
         }
 
         $this->addScript();

+ 38 - 9
src/Widgets/Form.php

@@ -4,6 +4,7 @@ namespace Dcat\Admin\Widgets;
 
 use Closure;
 use Dcat\Admin\Admin;
+use Dcat\Admin\Contracts\LazyRenderable;
 use Dcat\Admin\Form\Concerns\HandleCascadeFields;
 use Dcat\Admin\Form\Concerns\HasRows;
 use Dcat\Admin\Form\Concerns\HasTabs;
@@ -85,15 +86,17 @@ use Illuminate\Validation\Validator;
  */
 class Form implements Renderable
 {
-    use HasHtmlAttributes,
-        HasFormResponse,
-        HasAuthorization,
-        HandleCascadeFields,
-        HasRows,
-        HasTabs,
-        Macroable {
-            __call as macroCall;
-        }
+    use HasHtmlAttributes;
+    use HasAuthorization;
+    use HandleCascadeFields;
+    use HasRows;
+    use HasTabs;
+    use HasFormResponse {
+        setCurrentUrl as defaultSetCurrentUrl;
+    }
+    use Macroable {
+        __call as macroCall;
+    }
 
     const REQUEST_NAME = '_form_';
     const CURRENT_URL_NAME = '_current_';
@@ -176,9 +179,16 @@ class Form implements Renderable
         }
         $this->setKey($key);
 
+        $this->setUp();
+    }
+
+    protected function setUp()
+    {
         $this->initFields();
 
         $this->initFormAttributes();
+
+        $this->initCurrentUrl();
     }
 
     /**
@@ -203,6 +213,13 @@ class Form implements Renderable
         ]);
     }
 
+    protected function initCurrentUrl()
+    {
+        if ($this instanceof LazyRenderable) {
+            $this->setCurrentUrl($this->getCurrentUrl());
+        }
+    }
+
     /**
      * Action uri of the form.
      *
@@ -634,6 +651,18 @@ HTML;
         return $this->elementId ?: ($this->elementId = 'form-'.Str::random(8));
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    public function setCurrentUrl($url)
+    {
+        if ($this instanceof LazyRenderable) {
+            $this->payload([static::CURRENT_URL_NAME => $url]);
+        }
+
+        return $this->defaultSetCurrentUrl($url);
+    }
+
     /**
      * Generate a Field object and add to form builder if Field exists.
      *

+ 27 - 47
src/Widgets/Modal.php

@@ -4,15 +4,18 @@ namespace Dcat\Admin\Widgets;
 
 use Closure;
 use Dcat\Admin\Admin;
+use Dcat\Admin\Grid\LazyRenderable as LazyGrid;
+use Dcat\Admin\Contracts\LazyRenderable;
 use Dcat\Admin\Support\Helper;
-use Dcat\Admin\Support\LazyRenderable;
-use Dcat\Admin\Traits\AsyncRenderable;
+use Dcat\Admin\Traits\InteractsWithRenderApi;
 use Illuminate\Contracts\Support\Renderable;
 use Illuminate\Support\Str;
 
 class Modal extends Widget
 {
-    use AsyncRenderable;
+    use InteractsWithRenderApi;
+
+    protected $target = 'modal';
 
     /**
      * @var string|Closure|Renderable
@@ -49,16 +52,6 @@ class Modal extends Widget
      */
     protected $delay = 10;
 
-    /**
-     * @var string
-     */
-    protected $load = '';
-
-    /**
-     * @var string
-     */
-    protected $subScript;
-
     /**
      * @var bool
      */
@@ -174,6 +167,16 @@ class Modal extends Widget
      */
     public function content($content)
     {
+        if ($content instanceof LazyGrid) {
+            $content = $table =
+                AsyncTable::make()
+                ->from($content)
+                ->simple()
+                ->load(false);
+
+            $this->onShow($table->getLoadScript());
+        }
+
         if ($content instanceof LazyRenderable) {
             $this->setRenderable($content);
         } else {
@@ -284,20 +287,6 @@ class Modal extends Widget
         return $this->on('hidden.bs.modal', $script);
     }
 
-    /**
-     * 监听弹窗异步渲染完成事件.
-     *
-     * @param string $script
-     *
-     * @return $this
-     */
-    public function onLoad(string $script)
-    {
-        $this->load .= "(function () { {$script} })();";
-
-        return $this;
-    }
-
     /**
      * 获取弹窗元素选择器.
      *
@@ -317,53 +306,44 @@ class Modal extends Widget
         $script = '';
 
         foreach ($this->events as $v) {
-            $script .= "modal.on('{$v['event']}', function (event) {
+            $script .= "target.on('{$v['event']}', function (event) {
                 {$v['script']}
             });";
         }
 
         $this->script = <<<JS
 (function () {
-    var modal = $(replaceNestedFormIndex('{$this->getElementSelector()}'));
-    {$this->subScript};
+    var target = $('{$this->getElementSelector()}');
+    {$this->getRenderableScript()}
     {$script}
 })();
 JS;
     }
 
-    protected function addRenderableScript()
+    protected function addLoadRenderableScript()
     {
-        if (! $url = $this->getRequestUrl()) {
+        if (! $this->getRenderable()) {
             return;
         }
 
-        $this->subScript = <<<JS
-modal.on('modal:load', function () {
-    Dcat.helpers.asyncRender('{$url}', function (html) {
-        body.html(html);
-        
-        {$this->load}
-        
-        modal.trigger('modal:loaded');
-    });
-});
-JS;
-
         $this->on('show.bs.modal', <<<JS
-body = modal.find('.modal-body');
+body = target.find('.modal-body');
 
 body.html('<div style="min-height:150px"></div>').loading();
         
 setTimeout(function () {
-    modal.trigger('modal:load')
+    target.trigger('modal:load')
 }, {$this->delay});
 JS
         );
     }
 
+    /**
+     * {@inheritDoc}
+     */
     public function render()
     {
-        $this->addRenderableScript();
+        $this->addLoadRenderableScript();
         $this->addEventScript();
 
         if ($this->join) {