diff --git a/core/modules/views/src/Entity/View.php b/core/modules/views/src/Entity/View.php
index 51ad1a6..75970b5 100644
--- a/core/modules/views/src/Entity/View.php
+++ b/core/modules/views/src/Entity/View.php
@@ -220,7 +220,13 @@ protected function generateDisplayId($plugin_id) {
    * {@inheritdoc}
    */
   public function &getDisplay($display_id) {
-    return $this->display[$display_id];
+    $empty_array = [];
+    if (isset($this->display[$display_id])) {
+      return $this->display[$display_id];
+    }
+    else {
+      return $empty_array;
+    }
   }
 
   /**
@@ -330,8 +336,25 @@ protected function addCacheMetadata() {
   public function postSave(EntityStorageInterface $storage, $update = TRUE) {
     parent::postSave($storage, $update);
 
-    // @todo Remove if views implements a view_builder controller.
-    views_invalidate_cache();
+    Views::invalidateCache();
+
+    $executable = $this->getExecutable();
+    /** @var \Drupal\views\ViewExecutable $original_executable */
+    $original_executable = NULL;
+    if (isset($this->original)) {
+      $original_executable = $this->original->getExecutable();
+      $original_executable->initDisplay();
+    }
+    foreach ($executable->displayHandlers as $display_id => $display_handler) {
+      // Note: The original might have not had the new display, so let's cast it
+      // to an array so postSaveView can deal with it
+      $original_display_handler = NULL;
+      if ($original_executable && $original_executable->displayHandlers->has($display_id)) {
+        $original_executable->setDisplay($display_id);
+        $original_display_handler = $original_executable->display_handler;
+      }
+      $display_handler->postSaveView($original_display_handler);
+    }
 
     // Rebuild the router if this is a new view, or it's status changed.
     if (!isset($this->original) || ($this->status() != $this->original->status())) {
diff --git a/core/modules/views/src/Plugin/views/display/Block.php b/core/modules/views/src/Plugin/views/display/Block.php
index 9de84ef..6ab6e1b 100644
--- a/core/modules/views/src/Plugin/views/display/Block.php
+++ b/core/modules/views/src/Plugin/views/display/Block.php
@@ -372,4 +372,17 @@ public function remove() {
     }
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function postSaveView(DisplayPluginInterface $original_display = NULL) {
+    parent::postSaveView($original_display);
+
+    // Invalidate the block cache to update views block derivatives.
+    if (\Drupal::moduleHandler()->moduleExists('block')) {
+      \Drupal::service('plugin.manager.block')->clearCachedDefinitions();
+    }
+  }
+
+
 }
diff --git a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
index 5a4bda2..dcc15bc 100644
--- a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
+++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
@@ -157,6 +157,7 @@ public function initDisplay(ViewExecutable $view, array &$display, array &$optio
     $this->view = $view;
 
     // Load extenders as soon as possible.
+    $display += ['display_options' => []];
     $display['display_options'] += ['display_extenders' => []];
     $this->extenders = array();
     if ($extenders = Views::getEnabledDisplayExtenders()) {
@@ -2617,6 +2618,13 @@ protected function isBaseTableTranslatable() {
     }
     return FALSE;
   }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function postSaveView(DisplayPluginInterface $original_display = NULL) {
+  }
+
 }
 
 /**
diff --git a/core/modules/views/src/Plugin/views/display/DisplayPluginInterface.php b/core/modules/views/src/Plugin/views/display/DisplayPluginInterface.php
index 2c9da2b..2c99787 100644
--- a/core/modules/views/src/Plugin/views/display/DisplayPluginInterface.php
+++ b/core/modules/views/src/Plugin/views/display/DisplayPluginInterface.php
@@ -570,4 +570,13 @@ public function mergeDefaults();
    */
   public function getExtenders();
 
+  /**
+   * Act on saving a view.
+   *
+   * @param \Drupal\views\Plugin\views\display\DisplayPluginInterface $original_display
+   * @return
+   * @internal param \Drupal\views\Plugin\views\display\DisplayPluginInterface $orginal_display (optional) The display settings, of the original entity empty in case of a new view.*   (optional) The display settings, of the original entity empty in case of a new view.
+   */
+  public function postSaveView(DisplayPluginInterface $original_display = NULL);
+
 }
diff --git a/core/modules/views/src/Plugin/views/display/Page.php b/core/modules/views/src/Plugin/views/display/Page.php
index 27905b8..47bac2d 100644
--- a/core/modules/views/src/Plugin/views/display/Page.php
+++ b/core/modules/views/src/Plugin/views/display/Page.php
@@ -12,6 +12,7 @@
 use Drupal\Core\Form\FormStateInterface;
 use Drupal\Core\State\StateInterface;
 use Drupal\Core\Routing\RouteProviderInterface;
+use Drupal\views\Views;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
@@ -487,4 +488,30 @@ public function calculateDependencies() {
     return $dependencies;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function postSaveView(DisplayPluginInterface $original_display = NULL) {
+    parent::postSaveView($original_display);
+
+    // An empty original display means a new view, we need a router rebuild.
+    $route_rebuild = FALSE;
+    if (!$original_display) {
+      $route_rebuild = TRUE;
+    }
+    else {
+      $determining_options = ['menu', 'tab_options'];
+      foreach ($determining_options as $determining_option) {
+        if ($this->getOption($determining_option) != $original_display->getOption($determining_option)) {
+          $route_rebuild = TRUE;
+        }
+      }
+    }
+
+
+    if ($route_rebuild) {
+      Views::routeRebuildNeeded();
+    }
+  }
+
 }
diff --git a/core/modules/views/src/Plugin/views/display/PathPluginBase.php b/core/modules/views/src/Plugin/views/display/PathPluginBase.php
index 415b704..c7e2136 100644
--- a/core/modules/views/src/Plugin/views/display/PathPluginBase.php
+++ b/core/modules/views/src/Plugin/views/display/PathPluginBase.php
@@ -512,4 +512,30 @@ public function getAlteredRouteNames() {
     return $this->state->get('views.view_route_names') ?: array();
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function postSaveView(DisplayPluginInterface $original_display = NULL) {
+    parent::postSaveView($original_display);
+
+    // An empty original display means a new view, we need a router rebuild.
+    $route_rebuild = FALSE;
+    if (!$original_display) {
+      $route_rebuild = TRUE;
+    }
+    else {
+      $determining_options = ['path', 'route_name', 'arguments', 'access'];
+      foreach ($determining_options as $determining_option) {
+        if ($this->getOption($determining_option) != $original_display->getOption($determining_option)) {
+          $route_rebuild = TRUE;
+        }
+      }
+    }
+
+    if ($route_rebuild) {
+      Views::routeRebuildNeeded();
+    }
+  }
+
+
 }
diff --git a/core/modules/views/src/ViewExecutable.php b/core/modules/views/src/ViewExecutable.php
index 11dce89..20d5979 100644
--- a/core/modules/views/src/ViewExecutable.php
+++ b/core/modules/views/src/ViewExecutable.php
@@ -214,7 +214,7 @@ class ViewExecutable implements \Serializable {
    * An array containing Drupal\views\Plugin\views\display\DisplayPluginBase
    * objects.
    *
-   * @var \Drupal\views\DisplayPluginCollection
+   * @var \Drupal\views\DisplayPluginCollection|\Drupal\views\Plugin\views\display\DisplayPluginBase[]
    */
   public $displayHandlers;
 
diff --git a/core/modules/views/src/Views.php b/core/modules/views/src/Views.php
index 525177f..5dfd5ca 100644
--- a/core/modules/views/src/Views.php
+++ b/core/modules/views/src/Views.php
@@ -8,6 +8,7 @@
 namespace Drupal\views;
 
 use Drupal\Component\Utility\String;
+use Drupal\Core\Cache\Cache;
 
 /**
  * Static service container wrapper for views.
@@ -534,4 +535,25 @@ protected static function t($string, array $args = array(), array $options = arr
     return static::$translationManager->translate($string, $args, $options);
   }
 
+  /**
+   * Forces a router rebuild for views.
+   */
+  public static function routeRebuildNeeded() {
+    // Set the router as needed to be rebuilt.
+    \Drupal::service('router.builder')->setRebuildNeeded();
+
+    // Reset the RouteSubscriber from views.
+    \Drupal::service('views.route_subscriber')->reset();
+  }
+
+  /**
+   * Invalidate the views cache, forcing a rebuild on the next grab of table data.
+   */
+  public static function invalidateCache() {
+    \Drupal::service('cache_tags.invalidator')->invalidateTags(['views_data']);
+    $module_handler = \Drupal::moduleHandler();
+    // Allow modules to respond to the Views cache being cleared.
+    $module_handler->invokeAll('views_invalidate_cache');
+  }
+
 }
diff --git a/core/modules/views/views.module b/core/modules/views/views.module
index 23fd877..305da7c 100644
--- a/core/modules/views/views.module
+++ b/core/modules/views/views.module
@@ -483,21 +483,7 @@ function views_field_config_delete(FieldConfigInterface $field) {
  * Invalidate the views cache, forcing a rebuild on the next grab of table data.
  */
 function views_invalidate_cache() {
-  // Set the menu as needed to be rebuilt.
-  \Drupal::service('router.builder')->setRebuildNeeded();
-
-  $module_handler = \Drupal::moduleHandler();
-
-  // Reset the RouteSubscriber from views.
-  \Drupal::getContainer()->get('views.route_subscriber')->reset();
-
-  // Invalidate the block cache to update views block derivatives.
-  if ($module_handler->moduleExists('block')) {
-    \Drupal::service('plugin.manager.block')->clearCachedDefinitions();
-  }
-
-  // Allow modules to respond to the Views cache being cleared.
-  $module_handler->invokeAll('views_invalidate_cache');
+  Views::invalidateCache();
 }
 
 /**
