我正在使用此代码进行测试:
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>
和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]
}
})
我做了alert()测试,看看vue是否会重新渲染组件。我看到无论是否<component>
与<keep-alive>
进行包裹,只有在我第一次进入“主页”选项卡时才会调用alert()。所以我有两个问题:
1.究竟保持活力的作用是什么?因为无论如何组件只创建一次。
2. vue是否可以显示/隐藏选项卡,而不是替换单个DOM元素?但是在显示之前仍然不要加载组件。
答案 0 :(得分:1)
您已将alert()
调用放入异步返回组件定义的函数中。只有在第一次访问组件定义时才会调用此函数。
<keep-alive>
标记将缓存组件的实例,以便它不会被破坏并需要再次安装。
使用您的示例,您可以看到每次切换到“主页”标签时都会调用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>
但是,通过将动态组件包装在<keep-alive>
标记中,您告诉Vue缓存对主路由组件的引用。因此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.
关于你的第二个问题:如果你想最初将所有选项卡添加到DOM并简单地隐藏非活动选项卡组件,然后使用v-for
指令渲染每个选项卡,并使用{{1} }指令仅显示活动选项卡。
以下是一个例子:
v-show
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;
}
而且,如果我理解你的最后一句话,如果你真的想在标签最初处于活动状态之前不想创建标签组件,但是当另一个标签处于活动状态时想要隐藏标签的HTML内容,你需要跟踪数据属性中已激活哪些选项卡,然后使用<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>
指令初始阻止组件初始化。
这样的事情:
v-if
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;
}
答案 1 :(得分:1)
您需要使用<keep-alive></keep-alive>
我已更新您的Jsfiddle