我正在使用Uikit处理响应式Vue.js应用。我必须创建2个菜单 - 一个用于桌面版,一个用于移动版。所以我必须定义相同的菜单项2次,首先是桌面链接插槽,第二次是移动设备。我不想要2x定义它。我怎样才能优雅地处理这个问题?有什么想法吗?
<template id="app">
<app-layout>
<template slot="navlinks-desktop">
<router-link to="/link1" tag="li" exact><a>Link 1</a></router-link>
<router-link to="/link2" tag="li" exact><a>Link 2</a></router-link>
</template>
<template slot="navlinks-mobile">
<router-link to="/link1" tag="li" exact><a>Link 1</a></router-link>
<router-link to="/link2" tag="li" exact><a>Link 2</a></router-link>
</template>
<transition name="fade" slot="content">
<router-view></router-view>
</transition>
<p slot="footer">Footer text</p>
</app-layout>
</template>
<template id="app-layout">
<div class="main-container">
<header class="uk-margin-bottom">
<nav class="uk-navbar uk-navbar-attached">
<div class="uk-navbar-brand uk-hidden-small">My Application</div>
<div class="uk-navbar-flip">
<ul class="uk-navbar-nav uk-hidden-small">
<slot name="navlinks-desktop"></slot>
</ul>
<div class="uk-navbar-toggle uk-button-dropdown uk-visible-small uk-dropdown-close" data-uk-dropdown="{mode: 'click'; justify: 'nav'}">
<div class="uk-dropdown uk-dropdown-navbar uk-dropdown-small">
<ul class="uk-nav uk-nav-dropdown">
<slot name="navlinks-mobile"></slot>
</ul>
</div>
</div>
</div>
<div class="uk-navbar-brand uk-navbar-center uk-visible-small">My Application</div>
</nav>
</header>
<div class="uk-container uk-container-center">
<main>
<slot name="content"></slot>
</main>
</div>
<footer class="uk-text-center fixed-bottom">
<slot name="footer"></slot>
</footer>
</div>
</template>
编辑:那么......经过一些研究并仔细研究文档后,我必须说,这个具体的问题没有解决方案......虽然可以重用插槽,但只是以编程方式呈现它,这是不可能的通过路由器链接重新使用SLOT。
示例 - 没有黑客 - 真实&#34; Vue方式&#34;重用插槽:
<template id="app">
<app-layout>
<template slot="myslot">
<li>THIS WORKS</li>
<li>WILL</li>
<li>WORK</li>
</template>
</app-layout>
</template>
<script>
Vue.component('app-layout', {
render: function (createElement) {
var myslot = this.$slots.myslot
return createElement('div', [
createElement('ul', myslot),
createElement('ul', myslot)
])
}
})
</script>
简单,优雅,可读。但是,遗憾的是,如果以编程方式呈现组件,则无法使用模板。所以像这样......
<template id="app-layout">
<div class="main-container">
<header class="uk-margin-bottom">
<nav class="uk-navbar uk-navbar-attached">
<div class="uk-navbar-brand uk-hidden-small">My Application</div>
<div class="uk-navbar-flip">
<ul class="uk-navbar-nav uk-hidden-small">
<slot name="myslot"></slot>
</ul>
</div>
</nav>
</header>
</div>
</template>
...你可以扔掉,你必须使用createElement函数以编程方式逐个创建整个结构,这非常痛苦且容易出错。是的,您可以使用JSX,但是您必须使用Babel进行转换。这不是我想要的......非工作的例子:
<template id="app">
<app-layout>
<template slot="navlinks">
<router-link to: "/">Home</router-link>
<router-link to: "/products">Products</router-link>
<router-link to: "/about">About</router-link>
</template>
</app-layout>
</template>
<script>
Vue.component('app-layout', {
render: function (createElement) {
var navlinks = this.$slots.navlinks
return createElement('div', [
createElement('ul', navlinks),
createElement('ul', navlinks)
])
}
})
</script>
在此示例中,第二个UL将为空。不幸的是,从事实的角度来看,在Vue中所有vNode必须是唯一的,这是完全正常的,它将保持空白......
结果是我不能使用上面的结构。我不能有模板应用程序布局,我有包装元素的模板。最后,我用这种方式重写了它:
<template id="app">
<div class="main-container">
<header class="uk-margin-bottom">
<nav class="uk-navbar uk-navbar-attached">
<div class="uk-navbar-brand uk-hidden-small">My Application</div>
<div class="uk-navbar-flip">
<ul class="uk-navbar-nav uk-hidden-small">
<router-link to="/link1" tag="li" exact><a>Link 1</a></router-link>
<router-link to="/link2" tag="li" exact><a>Link 2</a></router-link>
</ul>
<div class="uk-navbar-toggle uk-button-dropdown uk-visible-small uk-dropdown-close" data-uk-dropdown="{mode: 'click'; justify: 'nav'}">
<div class="uk-dropdown uk-dropdown-navbar uk-dropdown-small">
<ul class="uk-nav uk-nav-dropdown">
<router-link to="/link1" tag="li" exact><a>Link 1</a></router-link>
<router-link to="/link2" tag="li" exact><a>Link 2</a></router-link>
</ul>
</div>
</div>
</div>
<div class="uk-navbar-brand uk-navbar-center uk-visible-small">My Application</div>
</nav>
</header>
<div class="uk-container uk-container-center">
<main>
<transition name="fade" slot="content">
<router-view></router-view>
</transition>
</main>
</div>
<footer class="uk-text-center fixed-bottom">
<p slot="footer">Footer text</p>
</footer>
</div>
</template>
没有两个单独的模板,没有插槽。但是也没有程序化的模板渲染。所以我保持我的示例应用程序干净,易于理解。这就是重点......
PS:仍然,我会很高兴,如果我错了,有人会告诉我如何重新使用路由器连接插槽。EDIT2:我踢了Uikit并改用了Bulma。这使我能够创建更好,更易读的结构。
<!-- APPLICATION VIEW -->
<template id="app">
<app-layout>
<template slot="navbar-items">
<router-link to="/" class="navbar-item" exact>Home</router-link>
<router-link to="/about" class="navbar-item" exact>About</router-link>
</template>
<transition name="fade" mode="out-in" slot="content">
<keep-alive>
<router-view></router-view>
</keep-alive>
</transition>
<p slot="footer">©2017 Wal De Mar</p>
</app-layout>
</template>
<!-- APPLICATION VIEW -->
<!-- TEMPLATE FOR APP VIEW -->
<template id="app-layout">
<div class="container">
<header>
<nav class="navbar">
<div class="navbar-brand">
<a href="/" class="navbar-item">BRAND</a>
<div class="navbar-burger" data-target="main-menu">
<span></span>
<span></span>
<span></span>
</div>
</div>
<div id="main-menu" class="navbar-menu">
<div class="navbar-end">
<slot name="navbar-items"></slot>
</div>
</div>
</nav>
</header>
<main>
<slot name="content"></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
</template>
<!-- TEMPLATE FOR APP VIEW -->
<script>
Vue.component('app-layout', {
template: '#app-layout'
})
new Vue({
template: '#app',
router,
}).$mount('#app')
</script>
答案 0 :(得分:0)
您可以创建一个包含导航链接的单独组件,并使用它而不是插槽。
<!-- NavLinks.vue -->
<template>
<router-link to="/link1" tag="li" exact><a>Link 1</a></router-link>
<router-link to="/link2" tag="li" exact><a>Link 2</a></router-link>
</template>
<template id="app">
<app-layout>
<transition name="fade" slot="content">
<router-view></router-view>
</transition>
<p slot="footer">Footer text</p>
</app-layout>
</template>
<template id="app-layout">
<div class="main-container">
<header class="uk-margin-bottom">
<nav class="uk-navbar uk-navbar-attached">
<div class="uk-navbar-brand uk-hidden-small">My Application</div>
<div class="uk-navbar-flip">
<ul class="uk-navbar-nav uk-hidden-small">
<nav-links></nav-links>
</ul>
<div class="uk-navbar-toggle uk-button-dropdown uk-visible-small uk-dropdown-close" data-uk-dropdown="{mode: 'click'; justify: 'nav'}">
<div class="uk-dropdown uk-dropdown-navbar uk-dropdown-small">
<ul class="uk-nav uk-nav-dropdown">
<nav-links></nav-links>
</ul>
</div>
</div>
</div>
<div class="uk-navbar-brand uk-navbar-center uk-visible-small">My Application</div>
</nav>
</header>
<div class="uk-container uk-container-center">
<main>
<slot name="content"></slot>
</main>
</div>
<footer class="uk-text-center fixed-bottom">
<slot name="footer"></slot>
</footer>
</div>
</template>
答案 1 :(得分:0)
您可以多次使用命名插槽。在下面的代码段中,我有一个带有两个插槽的组件和另一个组件,它将两个插槽同时提供给它。
Vue.component('twoMenus', {
template: '#two-menu-template'
});
new Vue({
el: '#app',
components: {
slotDoubler: {
template: '#slot-doubler-template'
}
}
});
&#13;
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div id="app">
<two-menus>
<div slot="menu1">I am a menu</div>
<div slot="menu2">I am a different menu</div>
</two-menus>
<hr>
<slot-doubler>
<div slot="reusable">This menu appears twice!</div>
</slot-doubler>
</div>
<template id="two-menu-template">
<div>
<div>The first menu is here:
<slot name="menu1"></slot>
</div>
<div>And the second is here:
<slot name="menu2"></slot>
</div>
</div>
</template>
<template id="slot-doubler-template">
<div>
<two-menus>
<div slot="menu1">
<slot name="reusable"></slot>
</div>
<div slot="menu2">
<slot name="reusable"></slot>
</div>
</two-menus>
</div>
</template>
&#13;
答案 2 :(得分:0)
如果我需要使用一个数据填充两个菜单,我会选择另一个更容易和更好的方法。
您可以拥有一个javascript菜单对象,并通过v-for
填充菜单项。你可以完全访问你的dom并按你的意愿操纵它。我在下面为你写了一个小演示
如果您需要复制,可以将v-for
模板移至component
并将菜单对象传递给它
new Vue({
el:"#app",
data : {
menu : [
{
// have each menu item as js object
text : 'Home',
to : { name : 'somewhere'},
href : '/somewhere'
},
{
// you can even have a divider
divider : true
},
{
text : 'About',
to : { name : 'somewhere'},
href : '/somewhere'
},
{
// have each menu item as js object
text : 'Services',
to : { name : 'somewhere'},
href : '/somewhere',
children : [
// you can even have child menu
]
},
]
}
})
&#13;
.mobile-menu {
background : grey;
border : black solid 3px;
}
&#13;
<script src="https://unpkg.com/vue@2.2.6/dist/vue.js"></script>
<div id="app">
<ul class="desktop-menu">
<template v-for="item in menu">
<li v-if="item.divider">
<span class="divider" >--------</span>
</li>
<li v-else>
<router-link :to="item.to" v-text="item.text"></router-link>
</li>
</template>
</ul>
<ul class="mobile-menu">
<template v-for="item in menu">
<li v-if="item.divider">
<span class="divider" >--------</span>
</li>
<li v-else>
<router-link :to="item.to" v-text="item.text"></router-link>
</li>
</template>
</ul>
</div>
&#13;
答案 3 :(得分:0)
如果我理解您的要求,您可以在任何时间使用相同的插槽。
只需在两个地方复制并粘贴相同的插槽
```的html
<header class="uk-margin-bottom">
<nav class="uk-navbar uk-navbar-attached">
<div class="uk-navbar-brand uk-hidden-small">My Application</div>
<div class="uk-navbar-flip">
<ul class="uk-navbar-nav uk-hidden-small">
<slot name="navlinks-desktop"></slot>
</ul>
<div class="uk-navbar-toggle uk-button-dropdown uk-visible-small uk-dropdown-close" data-uk-dropdown="{mode: 'click'; justify: 'nav'}">
<div class="uk-dropdown uk-dropdown-navbar uk-dropdown-small">
<ul class="uk-nav uk-nav-dropdown">
<slot name="navlinks-desktop"></slot>
</ul>
</div>
</div>
</div>
<div class="uk-navbar-brand uk-navbar-center uk-visible-small">My Application</div>
</nav>
</header>
<div class="uk-container uk-container-center">
<main>
<slot name="content"></slot>
</main>
</div>
<footer class="uk-text-center fixed-bottom">
<slot name="footer"></slot>
</footer>
```