简体   繁体   English

vue js 看不懂keep alive

[英]vue js cant understand keep alive

I'm doing tests with this code:我正在用这段代码做测试:
https://jsfiddle.net/b2qj69o1/25/ https://jsfiddle.net/b2qj69o1/25/

  <button
    v-for="tab in tabs"
    v-bind:key="tab.name"
    v-bind:class="['tab-button', { active: currentTab.name === tab.name }]"
    v-on:click="currentTab = tab"
  >{{ tab.name }}</button>

  <component
    v-bind:is="currentTab.component"
    class="tab"
  ></component>

And the js part还有js部分

var tabs = [
  {
    name: 'Home', 
    component: function() { 
    alert();  // test
    return new Promise((resolve, reject) => resolve({ 
      template: '<div>Home component</div>' 
    }))
    }
  },
  {
    name: 'Posts',
    component: {
      template: '<div>Posts component</div>'
    }
  },
  {
    name: 'Archive',
    component: {
      template: '<div>Archive component</div>',
    }
  }
]
new Vue({
  el: '#dynamic-component-demo',
  data: {
    tabs: tabs,
    currentTab: tabs[1]
  }
})

I did the alert() test to see whether vue will re-render the component.我做了 alert() 测试,看看 vue 是否会重新渲染组件。 I see that with or without wraping <component> with <keep-alive> , the alert() if called only the first time I enter the Home tab.我看到无论是否使用<keep-alive>包装<component> ,如果仅在我第一次进入 Home 选项卡时调用 alert() 。 So I have two questions:所以我有两个问题:
1. What exactly keep-alive does? 1. keep-alive到底是做什么的? cause it seems that anyway the component is created only once.因为似乎无论如何该组件只创建一次。
2. Is it possible for vue to show/hide the tabs, instead of replacing single DOM element? 2. vue 是否可以显示/隐藏选项卡,而不是替换单个 DOM 元素? But still not to load the component until it is shown.但是在显示之前仍然不要加载组件。

You've put the alert() call in the function that asynchronously returns the component definition.您已将alert()调用放在异步返回组件定义的函数中。 This function will only get called the first time the definition of the component is accessed.这个函数只会在第一次访问组件的定义时被调用。

The <keep-alive> tag will cache an instance of a component so that it does not get destroyed and need to be mounted again. <keep-alive>标签将缓存一个组件的实例,这样它就不会被破坏并且需要再次挂载。

Using your example, you can see that the mounted hook gets called any time you switch to the "Home" tab:使用您的示例,您可以看到无论何时切换到“主页”选项卡,都会调用mounted的钩子:

 var tabs = [ { name: 'Home', component: function() { return new Promise((resolve, reject) => resolve({ template: '<div>Home component</div>', mounted() { console.log('mounted') } })) } }, { name: 'Posts', component: { template: '<div>Posts component</div>' } }, { name: 'Archive', component: { template: '<div>Archive component</div>', } } ] new Vue({ el: '#dynamic-component-demo', data: { tabs: tabs, currentTab: tabs[1] } })
 .tab-button { padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid #ccc; cursor: pointer; background: #f0f0f0; margin-bottom: -1px; margin-right: -1px; } .tab-button:hover { background: #e0e0e0; } .tab-button.active { background: #e0e0e0; } .tab { border: 1px solid #ccc; padding: 10px; }
 <script src="https://unpkg.com/vue"></script> <div id="dynamic-component-demo" class="demo"> <button v-for="tab in tabs" v-bind:key="tab.name" v-bind:class="['tab-button', { active: currentTab.name === tab.name }]" v-on:click="currentTab = tab" >{{ tab.name }}</button> <component v-bind:is="currentTab.component" class="tab" ></component> </div>

But, by wrapping the dynamic component in a <keep-alive> tag, you are telling Vue to cache a reference to the home route's component.但是,通过将动态组件包装在<keep-alive>标记中,您是在告诉 Vue 缓存对主路由组件的引用。 So the mounted hook only gets called the first time the component is instantiated:所以mounted的钩子只会在组件第一次实例化时被调用:

 var tabs = [ { name: 'Home', component: function() { return new Promise((resolve, reject) => resolve({ template: '<div>Home component</div>', mounted() { console.log('mounted') } })) } }, { name: 'Posts', component: { template: '<div>Posts component</div>' } }, { name: 'Archive', component: { template: '<div>Archive component</div>', } } ] new Vue({ el: '#dynamic-component-demo', data: { tabs: tabs, currentTab: tabs[1] } })
 .tab-button { padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid #ccc; cursor: pointer; background: #f0f0f0; margin-bottom: -1px; margin-right: -1px; } .tab-button:hover { background: #e0e0e0; } .tab-button.active { background: #e0e0e0; } .tab { border: 1px solid #ccc; padding: 10px; }
 <script src="https://unpkg.com/vue"></script> <div id="dynamic-component-demo" class="demo"> <button v-for="tab in tabs" v-bind:key="tab.name" v-bind:class="['tab-button', { active: currentTab.name === tab.name }]" v-on:click="currentTab = tab" >{{ tab.name }}</button> <keep-alive> <component v-bind:is="currentTab.component" class="tab" ></component> </keep-alive> </div>

Here's the documentation on using the <keep-alive> tag with dynamic components. 这是有关将<keep-alive>标记与动态组件一起使用的文档。


As for your second question: if you want to add all of the tabs to the DOM initially and simply hide the inactive tab components, then render each tab using the v-for directive, and use the v-show directive to only show the active tab.至于您的第二个问题:如果您想最初将所有选项卡添加到 DOM 并简单地隐藏非活动选项卡组件,然后使用v-for指令呈现每个选项卡,并使用v-show指令仅显示活动标签。

Here's an example:这是一个例子:

 var tabs = [ { name: 'Home', component: function() { return new Promise((resolve, reject) => resolve({ template: '<div>Home component</div>', })) } }, { name: 'Posts', component: { template: '<div>Posts component</div>' } }, { name: 'Archive', component: { template: '<div>Archive component</div>', } } ] new Vue({ el: '#dynamic-component-demo', data: { tabs: tabs, currentTab: tabs[1] } })
 .tab-button { padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid #ccc; cursor: pointer; background: #f0f0f0; margin-bottom: -1px; margin-right: -1px; } .tab-button:hover { background: #e0e0e0; } .tab-button.active { background: #e0e0e0; } .tab { border: 1px solid #ccc; padding: 10px; }
 <script src="https://unpkg.com/vue"></script> <div id="dynamic-component-demo" class="demo"> <button v-for="tab in tabs" v-bind:key="tab.name" v-bind:class="['tab-button', { active: currentTab.name === tab.name }]" v-on:click="currentTab = tab" >{{ tab.name }}</button> <component v-for="tab in tabs" v-bind:key="'component-' + tab.name" v-bind:is="tab.component" class="tab" v-show="currentTab === tab" ></component> </div>

And, if I understand your last sentence correctly, if you really want to not create a tab component until the tab is initially active, but then want to hide the tab's HTML content when another tab is active, you'd need to keep track of which tabs have been activated in a data property and then use the v-if directive to initially prevent the component from initializing.而且,如果我正确理解了你的最后一句话,如果你真的不想在选项卡最初处于活动状态之前创建选项卡组件,但是想要在另一个选项卡处于活动状态时隐藏选项卡的 HTML 内容,你需要跟踪哪些选项卡已在数据属性中激活,然后使用v-if指令最初阻止组件初始化。

Something like this:像这样的东西:

 var tabs = [ { name: 'Home', component: function() { return new Promise((resolve, reject) => resolve({ template: '<div>Home component</div>', })) } }, { name: 'Posts', component: { template: '<div>Posts component</div>' } }, { name: 'Archive', component: { template: '<div>Archive component</div>', } } ] new Vue({ el: '#dynamic-component-demo', data: { tabs: tabs, currentTab: tabs[1], activatedTabs: {} }, watch: { currentTab: { immediate: true, handler(tab) { this.$set(this.activatedTabs, tab.name, true); } } } })
 .tab-button { padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border: 1px solid #ccc; cursor: pointer; background: #f0f0f0; margin-bottom: -1px; margin-right: -1px; } .tab-button:hover { background: #e0e0e0; } .tab-button.active { background: #e0e0e0; } .tab { border: 1px solid #ccc; padding: 10px; }
 <script src="https://unpkg.com/vue"></script> <div id="dynamic-component-demo" class="demo"> <button v-for="tab in tabs" v-bind:key="tab.name" v-bind:class="['tab-button', { active: currentTab.name === tab.name }]" v-on:click="currentTab = tab" >{{ tab.name }}</button> <component v-for="tab in tabs" v-if="activatedTabs[tab.name]" v-bind:key="'component-' + tab.name" v-bind:is="tab.component" class="tab" v-show="currentTab === tab" ></component> </div>

You need to wrap the component tag with the <keep-alive></keep-alive>您需要使用<keep-alive></keep-alive>包装组件标签

I have updated your Jsfiddle我已经更新了你的Jsfiddle

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM