Vue 3 – Laravel – Inertia 部分重新加载未正常工作

huangapple go评论93阅读模式
英文:

Vue 3 - Laravel - Inertia Partial reloading not working properly

问题

我有经验使用以前的router-view,但现在我感到困惑。我面临的问题是所有组件都在更新,页面没有重新加载,但一切都在更新。

我遇到的问题是,当我点击例如“Home”时,会在我的组件中添加一个过渡效果,并且会与此子菜单(1,2,3)一起淡入,但当我点击这些子菜单项目(1,2,3)中的任何一个时,我期望仅更新子菜单组件,而不再为我的组件和子菜单组件都添加过渡效果。

结构如下:

布局:

<script setup>

</script>

<template>
  <h1>This is layout</h1>
  <nav>
    <Link :href="route('home')">Home</Link>
    <Link :href="route('info')">Info</Link>
    <Link :href="route('about')">About</Link>
  </nav>
  <div class="content">
    <Transition name="page" appear>
      <span />
    </Transition>
  </div>
</template>

<style scoped lang="scss">

</style>

MyComponent:

<script setup>
import Layout from "@/layouts/Layout.vue";
</script>

<template>
  <Layout>
    <h1>This is my component</h1>
    <ul>
      <li>
        <Link :href="route('my.route.1')">Menu 1</Link>
        <Link :href="route('my.route.2')">Menu 2</Link>
        <Link :href="route('my.route.3')">Menu 3</Link>
      </li>
    </ul>
    <div class="submenu-content">
      <slot />
    </div>
  </Layout>
</template>

<style scoped lang="scss">

</style>

SubmenuComponent:

<script setup>
import Layout from "@/layouts/MyComponent.vue";
</script>

<template>
  <MyComponent>
    <h1>I'm submenu component and my content is here</h1>
  </MyComponent>
</template>

<style scoped lang="scss">

</style>

MyController.php:

public function viewSubComponent(Request $request) {
   $data = [1,2,3,4,5];
   return inertia('SubComponent', ['data' => $data]);
}

Vue 3 – Laravel – Inertia 部分重新加载未正常工作


请注意,这些是您提供的代码和文本的翻译。

<details>
<summary>英文:</summary>

I have experience with the previous router-view but right now I&#39;m confused. The Problem I&#39;m facing is that all components are updated, the page is not reloading, but everything is being updated. 

The issue that I&#39;m facing is when I click on for example &quot;Home&quot;, a Transition will be added to My component and It will fade in with this sub-menu (1,2,3), but when I click on any of this sub-menu items (1,2,3) I was expecting to update only Submenu Component  and not to get transition again for both My component and Submenu Component 

[![enter image description here][1]][1]




The structure that I have is next:

Layout :

    &lt;script setup&gt;
    
    &lt;/script&gt;
    
    &lt;template&gt;
      &lt;h1&gt;This is layout&lt;/h1&gt;
      &lt;nav&gt;
        &lt;Link :href=&quot;route(&#39;home&#39;)&quot;&gt;Home&lt;/Link&gt;
        &lt;Link :href=&quot;route(&#39;info&#39;)&quot;&gt;Info&lt;/Link&gt;
        &lt;Link :href=&quot;route(&#39;about&#39;)&quot;&gt;About&lt;/Link&gt;
      &lt;/nav&gt;
      &lt;div class=&quot;content&quot;&gt;
        &lt;Transition name=&quot;page&quot; appear&gt;
          &lt;span /&gt;
        &lt;/Transition&gt;
      &lt;/div&gt;
    &lt;/template&gt;
    
    &lt;style scoped lang=&quot;scss&quot;&gt;
    
    &lt;/style&gt;


MyComponent:

    &lt;script setup&gt;
    import Layout from &quot;@/layouts/Layout.vue&quot;
    &lt;/script&gt;
    
    &lt;template&gt;
      &lt;Layout&gt;
        &lt;h1&gt;This is my component&lt;/h1&gt;
        &lt;ul&gt;
          &lt;li&gt;
            &lt;Link :href=&quot;route(&#39;my.route.1&#39;)&quot;&gt;Menu 1&lt;/Link&gt;
            &lt;Link :href=&quot;route(&#39;my.route.2&#39;)&quot;&gt;Menu 2&lt;/Link&gt;
            &lt;Link :href=&quot;route(&#39;my.route.3&#39;)&quot;&gt;Menu 3&lt;/Link&gt;
          &lt;/li&gt;
        &lt;/ul&gt;
        &lt;div class=&quot;submenu-content&quot;&gt;
          &lt;slot /&gt;
        &lt;/div&gt;
      &lt;/Layout&gt;
    &lt;/template&gt;
    
    &lt;style scoped lang=&quot;scss&quot;&gt;
    
    &lt;/style&gt;


SubmenuComponent:

    &lt;script setup&gt;
    import Layout from &quot;@/layouts/MyComponent.vue&quot;
    &lt;/script&gt;
    
    &lt;template&gt;
      &lt;MyComponent&gt;
        &lt;h1&gt;I&#39;m submenu component and my content is here&lt;/h1&gt;
      &lt;/MyComponent&gt;
    &lt;/template&gt;
    
    &lt;style scoped lang=&quot;scss&quot;&gt;
    
    &lt;/style&gt;


MyController.php

    public function viewSubComponent(Request $request) {
       $data = [1,2,3,4,5];
       return inertia(&#39;SubComponent&#39;, [&#39;data&#39; =&gt; $data]);
    }






  [1]: https://i.stack.imgur.com/RIbha.png


</details>


# 答案1
**得分**: 2

我们使用称为“布局”(layouts)的模板来构建网页。布局的优点是其中声明的组件在页面刷新后不会重新加载...只有它们加载的内容会发生变化。

#### 声明布局

```html
<!-- ./resources/js/layouts/Layout.vue -->
<template>
  <div>
    <!-- Header元素(例如导航) -->
    <h1>这是布局</h1>
    <nav>
      <Link :href="route('home')">主页</Link>
      <Link :href="route('info')">信息</Link>
      <Link :href="route('about')">关于</Link>
    </nav>

    <div class="content">
      <!-- 子菜单,如果您希望避免每次重新加载它,您需要在布局中实现子菜单。这并不是不可能的,这种方法将帮助您实现一致的页面布局。 -->
      <slot name="submenu"></slot> <!-- 它不会更新,只要内容相同,因为在过渡之外 -->

      <!-- 内容 -->
      <div class="submenu-content">
        <Transition name="page" appear>
          <slot></slot> <!-- 当通过过渡刷新页面时,它将更新 -->
        </Transition>
      </div>
    </div>
  </div>
</template>

您可以自行设计它。重要的是在Vue可以稍后实现页面内容的地方放置一个默认插槽。

页面(如何实现布局?)

<!-- ./resources/js/pages/HomePage.vue -->
<template>
  <div>
     <!-- 子菜单 -->
     <template #submenu>
       <SubMenu />
     </template>
    
     <!-- 页面内容 -->
     <h1>我是子菜单组件,我的内容在这里</h1>
  </div>
</template>

<script setup>
import Layout from '@/layouts/Layout.vue'
import SubMenu from '@/components/SubMenu.vue'

defineOptions({
  layout: Layout, // 将布局定义为页面(Vue 3组合API)
})
</script>

如果通过Inertia调用HomePage组件,其内容将放置在布局的插槽元素内。如果您从那里导航到另一页,例如AboutUsPage.vue,它也将MyLayout作为其布局,只有插槽内的内容将被更新,插槽之外的所有内容将保持不变。

分离的子菜单

**重要提示:这不是布局,只是一个组件。**每个页面只能有一个布局。

<!-- ./resources/js/components/SubMenu.vue -->
<template>
  <div>
    <ul>
      <li>
        <Link :href="route('my.route.1')">菜单1</Link>
        <Link :href="route('my.route.2')">菜单2</Link>
        <Link :href="route('my.route.3')">菜单3</Link>
      </li>
    </ul>
  </div>
</template>

过渡

放置在<transition>块中的元素在页面加载后会刷新,因此对于子菜单是必要的...

1)将其放置在单独的过渡块中。
或者
2)将其放置在过渡之外 - 就像在当前示例中一样。

更多信息

什么是"defineOptions"?

InertiaJS 布局-页面关系

Vue 过渡

英文:

We use templates called "layouts" to build web pages. The advantage of layouts is that the components declared within them will not reload after a page refresh... only the content they load will change.

Declare Layout

&lt;!-- ./resources/js/layouts/Layout.vue --&gt;
&lt;template&gt;
  &lt;div&gt;
    &lt;!-- Header elements (ex. navigation) --&gt;
    &lt;h1&gt;This is layout&lt;/h1&gt;
    &lt;nav&gt;
      &lt;Link :href=&quot;route(&#39;home&#39;)&quot;&gt;Home&lt;/Link&gt;
      &lt;Link :href=&quot;route(&#39;info&#39;)&quot;&gt;Info&lt;/Link&gt;
      &lt;Link :href=&quot;route(&#39;about&#39;)&quot;&gt;About&lt;/Link&gt;
    &lt;/nav&gt;

    &lt;div class=&quot;content&quot;&gt;
      &lt;!-- Submenu, You need to implement the submenu in the layout if you want to avoid reloading it every time. It is not impossible, and this approach will help you achieve a consistent page layout. --&gt;
      &lt;slot name=&quot;submenu&quot;&gt;&lt;/slot&gt; &lt;!-- it will not update, while content equal, because outside of transition --&gt;
     
      &lt;!-- Content --&gt;
      &lt;div class=&quot;submenu-content&quot;&gt;
        &lt;Transition name=&quot;page&quot; appear&gt;
          &lt;slot&gt;&lt;/slot&gt; &lt;!-- it will update, when refresh page by transition --&gt;
        &lt;/Transition&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/template&gt;

It is up to you to design it. The important thing is to place a default slot somewhere where Vue can later implement the content of the page.

Page (How to implement Layout?)

&lt;!-- ./resources/js/pages/HomePage.vue --&gt;
&lt;template&gt;
  &lt;div&gt;
     &lt;!-- Submenu --&gt;
     &lt;template #submenu&gt;
       &lt;SubMenu /&gt;
     &lt;/template&gt;
    
     &lt;!-- Page content --&gt;
     &lt;h1&gt;I&#39;m submenu component and my content is here&lt;/h1&gt;
  &lt;/div&gt;
&lt;/template&gt;

&lt;script setup&gt;
import Layout from &#39;@/layouts/Layout.vue&#39;
import SubMenu from &#39;@/components/SubMenu.vue&#39;

defineOptions({
  layout: Layout, // define Layout to Page (Vue 3 Composition API)
})
&lt;/script&gt;

If you invoke the HomePage component through Inertia, its content will be placed inside the slot element of the Layout. If you navigate from there to another page, such as AboutUsPage.vue, which also specifies MyLayout as its layout, only the content within the slot will be updated, and everything outside the slot will remain unchanged.

Separated submenu

IMPORTANT: it's not layout, just a component. You can only have one layout to page.

&lt;!-- ./resources/js/components/SubMenu.vue --&gt;
&lt;template&gt;
  &lt;div&gt;
    &lt;ul&gt;
      &lt;li&gt;
        &lt;Link :href=&quot;route(&#39;my.route.1&#39;)&quot;&gt;Menu 1&lt;/Link&gt;
        &lt;Link :href=&quot;route(&#39;my.route.2&#39;)&quot;&gt;Menu 2&lt;/Link&gt;
        &lt;Link :href=&quot;route(&#39;my.route.3&#39;)&quot;&gt;Menu 3&lt;/Link&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/template&gt;

Transition

Elements placed in a &lt;transition&gt; block refresh after the page loads, so it is necessary for the submenu...

  1. to be placed in a separate transition block.
    or
  2. to be placed outside the transition - like in the current example -.

<br><br>

More informations

What is "defineOptions"?

InertiaJS Layout-Page relationship

Vue Transitions

huangapple
  • 本文由 发表于 2023年6月2日 06:00:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76385991.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定