我是使用Vue.js的新手,我在创建Button
组件时遇到了困难。
如何将此组件编程为条件渲染?换句话说,也许应该将router-link
呈现为button
?像那样:
<Button type="button" @click="alert('hi!')">It's a button.</Button>
// -> Should return as a <button>.
<Button :to="{ name: 'SomeRoute' }">It's a link.</Button>
// -> Should return as a <router-link>.
答案 0 :(得分:7)
您可以在render()
内切换代码,也可以只使用<component>
。
根据official specification for Dynamic Components:
您可以使用相同的挂载点,并使用保留的
<component>
元素在多个组件之间动态切换,并动态绑定到它的is
属性。
以下是您案例的示例:
<强> ButtonControl.vue 强>
<template>
<component :is="type" :to="to">
{{ value }}
</component>
</template>
<script>
export default {
computed: {
type () {
if (this.to) {
return 'router-link'
}
return 'button'
}
},
props: {
to: {
required: false
},
value: {
type: String
}
}
}
</script>
现在您可以轻松地将其用于button
:
<button-control value="Something"></button-control>
或router-link
:
<button-control to="/" value="Something"></button-control>
在创建可能包含链接或不具有链接的元素(例如按钮或卡片)时,请记住这是一个很好的行为。
答案 1 :(得分:3)
您可以通过render functions实现这一目标。
render: function (h) {
if(this.to){ // i am not sure if presence of to props is your condition
return h(routerLink, { props: { to: this.to } },this.$slots.default)
}
return h('a', this.$slots.default)
}
这应该可以帮助你开始正确的方向
答案 2 :(得分:3)
您可以使用v-if
,v-else-if
和v-else
指令创建可以动态呈现为不同标记的自定义组件。只要Vue可以告诉自定义组件在渲染后将具有单个根元素,它就不会抱怨。
但首先,您不应该使用&#34;内置或保留的HTML元素&#34;来命名自定义组件,因为您将获得的Vue警告会告诉您。
对我来说,为什么你希望单个组件有条件地呈现为<button>
或<router-link>
(它本身默认呈现为<a>
元素,这对我没有意义。 )。但如果你真的想这样做,这就是一个例子:
Vue.use(VueRouter);
const router = new VueRouter({
routes: [ { path: '/' } ]
})
Vue.component('linkOrButton', {
template: `
<router-link v-if="type === 'link'" :to="to">I'm a router-link</router-link>
<button v-else-if="type ==='button'">I'm a button</button>
<div v-else>I'm a just a div</div>
`,
props: ['type', 'to']
})
new Vue({ el: '#app', router })
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.1/vue-router.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.9/vue.js"></script>
<div id="app">
<link-or-button type="link" to="/"></link-or-button>
<link-or-button type="button"></link-or-button>
<link-or-button></link-or-button>
</div>
&#13;
如果您只是尝试将<router-link>
呈现为<button>
而不是<a>
,那么您可以通过tag
道具来指定<router-link>
本身:
Vue.use(VueRouter);
const router = new VueRouter({
routes: [ { path: '/' } ]
})
new Vue({ el: '#app', router })
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-router/3.0.1/vue-router.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.9/vue.js"></script>
<div id="app">
<router-link to="/">I'm an a</router-link>
<router-link to="/" tag="button">I'm a button</router-link>
</div>
&#13;
答案 3 :(得分:1)
我认为您无法在没有父元素的情况下有条件地呈现<router-link>
或<button>
。
您可以做的是决定在点击上做什么,以及根据传递的道具为您的元素设置样式。
template: `<a :class="{btn: !isLink, link: isLink}" @click="handleClick"><slot>Default content</slot></a>`,
props: ['to'],
computed: {
isLink () { return !!this.to }
},
methods: {
handleClick () {
if (this.isLink) {
this.$router.push(this.to)
}
this.$emit('click') // edited this to always emit
}
}
答案 4 :(得分:1)
我会遵循@Phil的建议并使用v-if
,但如果您更喜欢使用一个组件,则可以在点击方式中programmatically navigate。
您的代码可能如下所示:
<template>
<Button type="button" @click="handleLink">It's a button.</Button>
</template>
<script>
export default {
name: 'my-button',
props: {
routerLink: {
type: Boolean,
default: false
}
},
methods: {
handleLink () {
if (this.routerLink) {
this.$router.push({ name: 'SomeRoute' })
} else {
alert("hi!")
}
}
}
}
</script>