我使用的是Vue.js 2.5.x和Nuxt1.4。我相信这是一个与vue-router相关的问题。
我在两个不同的Nuxt页面上有相同的组件,当在页面之间导航时,我希望将它们保留在布局中(而不仅仅是内存中)。
在生命周期事件方面,一些组件被添加到布局中或从布局中删除,并触发创建、安装、卸载和销毁的整个生命周期。我理解keep-alive是如何工作的,以避免我们期望在布局中重新挂载的组件的创建/销毁过程的开销,这不是这里的问题。
相比之下,当路线改变时,简单的组件似乎根本不会被卸载,好像Vue以某种方式理解这些组件在两个不同的布局中看起来是相同的,所以它不仅不会销毁/创建它们……它会将它们留在布局中,甚至不会卸载它们。
我正在尝试更好地理解在路由之间导航时允许当前页面的组件保持挂载的条件。我发现的许多讨论的性质都是“为什么我的组件不刷新?”当发生路由更改时,我实际上遇到了相反的问题:我想保留一个组件及其状态,但该组件正在被销毁。我尝试过将“key”显式设置为一个特定的共享值(通常给出相反的建议来确保组件卸载),但似乎还有更深层次的原因。
再说一次,为了清楚起见,我并不是指试图挂起内存中临时从布局中删除的组件的“保持活动”。我在这里观察并试图理解的似乎是一种不同的行为,Vue的某些部分识别出两个布局之间的组件是相同的,并优化了此类组件的销毁和(重新)创建。这是一个巨大的优化,但它的行为似乎在我能找到的任何地方都没有讨论或记录。
我有一个Nuxt布局,它在概念上类似于这个…
default.vue:
<template>
<div>
<my-marvelous-header-component />
<nuxt/>
<my-also-marvelous-footer-component />
</div>
</template>
…我有几个Nuxt页面,看起来像这样的…
页面-a.vue:
<template>
<section id=mainContent>
<wonderful-component id="wonder1" :key=321 />
<complex-component-with-children :key=123 />
</section>
</template>
页面-b.vue:
<template>
<section id=mainContent>
<wonderful-component id="wonder1" :key=321 />
<complex-component-with-children :key=123 />
</section>
</template>
您将注意到,这两个页面具有完全相同的组件,并且我尝试使用关键属性来唯一地标识它们,以便在渲染时向Vue传达它们是相同的生物。
当我使用this.$router.push()在这些页面之间导航时,我的页眉和页脚组件在路由导航中完好无损(我通过在生命周期钩子中放入一些控制台输出来验证这一点),但是奇妙和复杂的组件都会被销毁,然后重新创建。
我尝试回收的两个组件都有许多动态创建的子组件,因此vdom的状态将与初始页面的原始启动条件有很大不同。像wonderful或complex这样的组件没有任何属性或从模板…传递的任何其他数据它们与上面的布局完全相同。我已经尝试给它们一个唯一的ID或键值,在模板之间共享(以及什么都没有),但无论我尝试过什么,路由器推送都会导致这些组件销毁并重新呈现。
像我的页眉和页脚回收这样的琐碎组件很好,我只是想让我的更复杂的组件也有类似的行为。
因此,我的核心问题是,是什么允许或阻止回收组件?检查什么来确定组件是否可以回收?有没有一种方法可以在布线更改之间通知应该保留/回收组件?如果不是,我必须在组件外部保留什么,才能使它显示为在转换期间保持不变的候选对象?
我曾认为“key”属性是这里的魔术,但这似乎不起作用,不幸的是,浏览这个单词的Vue.js源代码发现,它被广泛用于命名参数和局部变量…我相信在Vue中有一个名为“patch()”的函数,它至少可以用新旧组件一致地更新vdom,但坦率地说,其中的逻辑超出了我目前对Vue的了解。如果对Vue内部有更好了解的人对代码的哪些部分可能有助于澄清我的想法有洞察力,我会热衷于再次深入了解这一点。
我觉得我已经追了好几天了。任何想法或见解都是非常感谢的。
发布于 2018-05-31 10:44:39
(不确定这些解释对您是否足够,但无论如何我都会尝试回答它)
在Vue中使用的通用术语称为,而不是回收。这是你在研究这个问题时想要用到的术语。
对于Nuxt,keep-alive doesn't seem to be reliable yet。我建议您将所有数据保存在Vuex中,并基于Vuex中的数据渲染元素。
什么允许或禁止回收组件?检查什么来确定组件是否可以回收?
在这里考虑挂载和卸载是很有用的。默认情况下,组件在卸载时总是会被销毁。(除非使用keep-alive
。)
在此示例中,
<my-marvelous-header-component />
<nuxt/>
<my-also-marvelous-footer-component />
<nuxt/>
是Vue路由器的<router-view></router-view>
所在的位置。在路由更改时,只有router-view
内部的组件会被挂载/卸载。因此,在路由更改时,<my-marvelous-header-component />
和<my-also-marvelous-footer-component />
将保持不变,并且不会被挂载/卸载。
有没有一种方法可以在路由更改之间发出信号,表明应该保留/回收组件?
在一个典型的(不是Nuxt) Vue项目中,它是通过在<router-view>
上应用<keep-alive>
来控制的。
这是一个很好的例子:https://jsfiddle.net/Linusborg/L613xva0/4/
<div id="app">
...
<keep-alive include="foo">
<router-view></router-view>
</keep-alive>
</div>
但在Nuxt中,<router-view>
是自动生成的,您不能像在普通的Vue项目中那样对其应用<keep-alive>
。
(再次)对于Nuxt,keep-alive doesn't seem to be reliable yet。我建议您将所有数据保存在Vuex中,并基于Vuex中的数据渲染元素。
发布于 2021-03-26 22:03:28
inertiajs用vue组件做到了这一点。
为布局创建vue模板
Layout.vue:
<template>
<div>
<!-- Your Layout code -->
</div>
</template>
SomePage.vue:
<template>
<div>
<!-- Your specific page's code -->
</div>
</template>
<script>
import Layout from 'path/to/Layout'
export default {
layout: Layout,
}
</script>
SomePage
将被包裹在Layout
中返回
使用这个框架可以做更多的事情,比如默认布局、特定目录中页面的布局等。
这种布局结构将确保每个页面调用之间的布局是持久的,而不是在每次页面调用时销毁和重建,因此您可以保存滚动位置,在用户离开时继续播放音频,等等。所有这些都可以在here中找到
您还可以使用呈现函数从export
语句中获取要显示的布局,查看PingCRM git代码库以获取更多示例,还可以考虑laracasts关于Inertia.js、Vue和Laravel的这个精彩系列
https://stackoverflow.com/questions/50613268
复制相似问题