diff --git a/core/modules/views/src/Entity/View.php b/core/modules/views/src/Entity/View.php
index 63d3ba1..f4b926e 100644
--- a/core/modules/views/src/Entity/View.php
+++ b/core/modules/views/src/Entity/View.php
@@ -329,8 +329,12 @@ 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();
+    foreach ($executable->displayHandlers as $display_id => $display_handler) {
+      $display_handler->postSaveView($this->original->getDisplay($display_id));
+    }
 
     // Rebuild the router case the view got enabled.
     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..4deac68 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(array $original_display) {
+    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 7cd1041..1f83a23 100644
--- a/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
+++ b/core/modules/views/src/Plugin/views/display/DisplayPluginBase.php
@@ -2599,6 +2599,16 @@ protected function isBaseTableTranslatable() {
     }
     return FALSE;
   }
+
+  /**
+   * Act on saving a view.
+   *
+   * @param array $orginal_display
+   *   The display settings, of the original entity.
+   */
+  public function postSaveView(array $orginal_display) {
+  }
+
 }
 
 /**
diff --git a/core/modules/views/src/Plugin/views/display/Page.php b/core/modules/views/src/Plugin/views/display/Page.php
index 27905b8..e07a9a8 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,34 @@ public function calculateDependencies() {
     return $dependencies;
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function postSaveView(array $original_display) {
+    parent::postSaveView($original_display);
+
+    $route_rebuild = FALSE;
+
+    $this->display['display_options'] += [
+      'menu' => [],
+      'tab_options' => [],
+    ];
+
+    $original_display['display_options'] += [
+      'menu' => [],
+      'tab_options' => [],
+    ];
+
+    if ($this->display['display_options']['menu'] != $original_display['display_options']['menu']) {
+      $route_rebuild = TRUE;
+    }
+    if ($this->display['display_options']['tab_options'] != $original_display['display_options']['tab_options']) {
+      $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 c4cc43f..3730d6b 100644
--- a/core/modules/views/src/Plugin/views/display/PathPluginBase.php
+++ b/core/modules/views/src/Plugin/views/display/PathPluginBase.php
@@ -512,4 +512,48 @@ public function getAlteredRouteNames() {
     return $this->state->get('views.view_route_names') ?: array();
   }
 
+  /**
+   * {@inheritdoc}
+   */
+  public function postSaveView(array $original_display) {
+    parent::postSaveView($original_display);
+
+    $route_rebuild = FALSE;
+
+    $this->display['display_options'] += [
+      'path' => '',
+      'route_name' => '',
+      'arguments' => [],
+      'access' => [],
+    ];
+
+    $original_display['display_options'] += [
+      'path' => '',
+      'route_name' => '',
+      'arguments' => [],
+      'access' => [],
+    ];
+
+    if ($this->display['display_options']['path'] != $original_display['display_options']['path']) {
+      $route_rebuild = TRUE;
+    }
+
+    if ($this->display['display_options']['route_name'] != $original_display['display_options']['route_name']) {
+      $route_rebuild = TRUE;
+    }
+
+    if ($this->display['display_options']['arguments'] != $original_display['display_options']['arguments']) {
+      $route_rebuild = TRUE;
+    }
+
+    if ($this->display['display_options']['access'] != $original_display['display_options']['access']) {
+      $route_rebuild = TRUE;
+    }
+
+    if ($route_rebuild) {
+      Views::routeRebuildNeeded();
+    }
+  }
+
+
 }
diff --git a/core/modules/views/src/Views.php b/core/modules/views/src/Views.php
index 525177f..c736135 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_indicator')->setRebuildNeeded();
+
+    // Reset the RouteSubscriber from views.
+    \Drupal::getContainer()->get('views.route_subscriber')->reset();
+  }
+
+  /**
+   * Invalidate the views cache, forcing a rebuild on the next grab of table data.
+   */
+  public static function invalidateCache() {
+    Cache::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 3197622..47fb870 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_indicator')->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();
 }
 
 /**
