Vue.js 中的条件 <router-link> 取决于 prop 值?
Conditional <router-link> in Vue.js dependant on prop value?
希望这是一个相当简单的问题/答案,但我在文档中找不到太多信息。
有没有办法根据是否传入 prop 来启用或禁用 [=13=] 生成的锚点?
<router-link class="Card__link" :to="{ name: 'Property', params: { id: id }}">
<h1 class="Card__title">{{ title }}</h1>
<p class="Card__description">{{ description }}</p>
</router-link>
如果没有 id
传递给此组件,我想禁用任何正在生成的 link。
有没有办法在不将内容加倍成 v-if
的情况下做到这一点?
谢谢!
假设您想要禁用锚标记,因为不可点击且看起来已禁用,该选项正在使用 CSS。 isActive 应该 return 通过检查 prop id 为真。
<router-link class="Card__link" v-bind:class="{ disabled: isActive }" :to="{ name: 'Property', params: { id: id }}">
<h1 class="Card__title">{{ title }}</h1>
<p class="Card__description">{{ description }}</p>
</router-link>
<style>
.disabled {
pointer-events:none;
opacity:0.6;
}
<style>
如果只想禁用导航,可以使用路由守卫。
beforeEnter: (to, from, next) => {
next(false);
}
问题是 router-link
呈现为 html 锚标签,而锚标签不支持 disabled
属性。但是,您可以将 tag="button"
添加到 router-link
:
<router-link :to="myLink" tag="button" :disabled="isDisabled" >
Vue 然后会将你的 link 呈现为一个按钮,这自然支持 disabled
属性。问题解决了!缺点是您必须提供额外的样式以使其看起来像 link。然而,这是实现此功能的最佳方式,并且不依赖于任何 pointer-events
hack。
如果您需要经常使用它,请考虑:
创建新组件
<template>
<router-link
v-if="!disabled"
v-bind="$attrs"
>
<slot/>
</router-link>
<span
v-else
v-bind="$attrs"
>
<slot/>
</span>
</template>
<script>
export default {
name: 'optional-router-link',
props: {
params: Object,
disabled: {
type: Boolean,
default: false,
},
},
};
</script>
可选,全局注册:
Vue.component('optional-router-link', OptionalRouterLink);
使用方法如下:
<optional-router-link
:disabled="isDisabled"
:to="whatever"
>
My link
</optional-router-link>
您还可以使用以下内容:
<router-link class="Card__link" :to="id ? { name: 'Property', params: { id: id }} : {}">
<h1 class="Card__title">{{ title }}</h1>
<p class="Card__description">{{ description }}</p>
</router-link>
如果 id 未定义,路由器不会将页面重定向到 link。
我有时会这样做:
<component
:is="hasSubLinks ? 'button' : 'router-link'"
:to="hasSubLinks ? undefined : href"
:some-prop="computedValue"
@click="hasSubLinks ? handleClick() : navigate"
>
<!-- arbitrary markup -->
</component>
...
computed: {
computedValue() {
if (this.hasSubLinks) return 'something';
if (this.day === 'Friday') return 'tgif';
return 'its-fine';
},
},
但我基本上总是包装 router-link,这样你就可以控制禁用状态,或者在渲染 link 之前预先检查任何状态或道具,像这样:
<template>
<router-link
v-slot="{ href, route, navigate, isActive, isExactActive }"
:to="to"
>
<a
:class="['nav-link-white', {
'nav-link-white-active': isActive,
'opacity-50': isDisabled,
}]"
:href="isDisabled ? undefined : href"
@click="handler => handleClick(handler, navigate)"
>
<slot></slot>
</a>
</router-link>
</template>
<script>
export default {
name: 'top-nav-link',
props: {
isDisabled: {
type: Boolean,
required: false,
default: () => false,
},
to: {
type: Object,
required: true,
},
},
data() {
return {};
},
computed: {},
methods: {
handleClick(handler, navigate) {
if (this.isDisabled) return undefined;
return navigate(handler);
},
},
};
</script>
现在在我的应用程序中,我注意到 @click="handler => handleClick(handler, navigate)"
的某些组合在性能上受到严重影响。
例如,这改变路由非常慢:
@click="isDisabled ? undefined : handler => navigate(handler)"
但是我上面的完整示例代码中的模式有效并且没有性能问题。
一般来说,@click
中的三元运算符可能非常冒险,所以如果遇到问题,请不要立即放弃,尝试许多不同的方法来分叉谓词或切换 <component :is=""
基于状态。 navigate 本身很烦人,因为它需要隐式的第一个参数才能工作。
我没试过,但你应该可以使用 Function.prototype.call()
、Function.prototype.apply()
或 Function.prototype.bind()
.
例如,您可以这样做:
@click="handler => setupNavigationTarget(handler, navigate)"
...
setupNavigationTarget(handler, cb) {
if (this.isDisabled) return undefined;
return this.$root.$emit('some-event', cb.bind(this, handler));
},
...
// another component
mounted() {
this.$root.$on('some-event', (navigate) => {
if (['Saturday', 'Sunday'].includes(currentDayOfTheWeek)) {
// halt the navigation event
return undefined;
}
// otherwise continue (and notice how downstream logic
// no longer has to care about the bound handler object)
return navigate();
});
},
我尝试过不同的解决方案,但只有一个对我有用,也许是因为我 运行 来自 Nuxt?尽管理论上 nuxt-link
应该与 router-link
.
完全相同
无论如何,这是解决方案:
<template>
<router-link
v-slot="{ navigate }"
custom
:to="to"
>
<button
role="link"
@click="onNavigation(navigate, $event)"
>
<slot></slot>
</button>
</router-link>
</template>
<script>
export default {
name: 'componentName',
props: {
to: {
type: String,
required: true,
},
},
methods: {
onNavigation(navigate, event) {
if (this.to === '#other-action') {
// do something
} else {
navigate(event);
}
return false;
},
};
</script>
希望这是一个相当简单的问题/答案,但我在文档中找不到太多信息。
有没有办法根据是否传入 prop 来启用或禁用 [=13=] 生成的锚点?
<router-link class="Card__link" :to="{ name: 'Property', params: { id: id }}">
<h1 class="Card__title">{{ title }}</h1>
<p class="Card__description">{{ description }}</p>
</router-link>
如果没有 id
传递给此组件,我想禁用任何正在生成的 link。
有没有办法在不将内容加倍成 v-if
的情况下做到这一点?
谢谢!
假设您想要禁用锚标记,因为不可点击且看起来已禁用,该选项正在使用 CSS。 isActive 应该 return 通过检查 prop id 为真。
<router-link class="Card__link" v-bind:class="{ disabled: isActive }" :to="{ name: 'Property', params: { id: id }}">
<h1 class="Card__title">{{ title }}</h1>
<p class="Card__description">{{ description }}</p>
</router-link>
<style>
.disabled {
pointer-events:none;
opacity:0.6;
}
<style>
如果只想禁用导航,可以使用路由守卫。
beforeEnter: (to, from, next) => {
next(false);
}
问题是 router-link
呈现为 html 锚标签,而锚标签不支持 disabled
属性。但是,您可以将 tag="button"
添加到 router-link
:
<router-link :to="myLink" tag="button" :disabled="isDisabled" >
Vue 然后会将你的 link 呈现为一个按钮,这自然支持 disabled
属性。问题解决了!缺点是您必须提供额外的样式以使其看起来像 link。然而,这是实现此功能的最佳方式,并且不依赖于任何 pointer-events
hack。
如果您需要经常使用它,请考虑:
创建新组件
<template>
<router-link
v-if="!disabled"
v-bind="$attrs"
>
<slot/>
</router-link>
<span
v-else
v-bind="$attrs"
>
<slot/>
</span>
</template>
<script>
export default {
name: 'optional-router-link',
props: {
params: Object,
disabled: {
type: Boolean,
default: false,
},
},
};
</script>
可选,全局注册:
Vue.component('optional-router-link', OptionalRouterLink);
使用方法如下:
<optional-router-link
:disabled="isDisabled"
:to="whatever"
>
My link
</optional-router-link>
您还可以使用以下内容:
<router-link class="Card__link" :to="id ? { name: 'Property', params: { id: id }} : {}">
<h1 class="Card__title">{{ title }}</h1>
<p class="Card__description">{{ description }}</p>
</router-link>
如果 id 未定义,路由器不会将页面重定向到 link。
我有时会这样做:
<component
:is="hasSubLinks ? 'button' : 'router-link'"
:to="hasSubLinks ? undefined : href"
:some-prop="computedValue"
@click="hasSubLinks ? handleClick() : navigate"
>
<!-- arbitrary markup -->
</component>
...
computed: {
computedValue() {
if (this.hasSubLinks) return 'something';
if (this.day === 'Friday') return 'tgif';
return 'its-fine';
},
},
但我基本上总是包装 router-link,这样你就可以控制禁用状态,或者在渲染 link 之前预先检查任何状态或道具,像这样:
<template>
<router-link
v-slot="{ href, route, navigate, isActive, isExactActive }"
:to="to"
>
<a
:class="['nav-link-white', {
'nav-link-white-active': isActive,
'opacity-50': isDisabled,
}]"
:href="isDisabled ? undefined : href"
@click="handler => handleClick(handler, navigate)"
>
<slot></slot>
</a>
</router-link>
</template>
<script>
export default {
name: 'top-nav-link',
props: {
isDisabled: {
type: Boolean,
required: false,
default: () => false,
},
to: {
type: Object,
required: true,
},
},
data() {
return {};
},
computed: {},
methods: {
handleClick(handler, navigate) {
if (this.isDisabled) return undefined;
return navigate(handler);
},
},
};
</script>
现在在我的应用程序中,我注意到 @click="handler => handleClick(handler, navigate)"
的某些组合在性能上受到严重影响。
例如,这改变路由非常慢:
@click="isDisabled ? undefined : handler => navigate(handler)"
但是我上面的完整示例代码中的模式有效并且没有性能问题。
一般来说,@click
中的三元运算符可能非常冒险,所以如果遇到问题,请不要立即放弃,尝试许多不同的方法来分叉谓词或切换 <component :is=""
基于状态。 navigate 本身很烦人,因为它需要隐式的第一个参数才能工作。
我没试过,但你应该可以使用 Function.prototype.call()
、Function.prototype.apply()
或 Function.prototype.bind()
.
例如,您可以这样做:
@click="handler => setupNavigationTarget(handler, navigate)"
...
setupNavigationTarget(handler, cb) {
if (this.isDisabled) return undefined;
return this.$root.$emit('some-event', cb.bind(this, handler));
},
...
// another component
mounted() {
this.$root.$on('some-event', (navigate) => {
if (['Saturday', 'Sunday'].includes(currentDayOfTheWeek)) {
// halt the navigation event
return undefined;
}
// otherwise continue (and notice how downstream logic
// no longer has to care about the bound handler object)
return navigate();
});
},
我尝试过不同的解决方案,但只有一个对我有用,也许是因为我 运行 来自 Nuxt?尽管理论上 nuxt-link
应该与 router-link
.
无论如何,这是解决方案:
<template>
<router-link
v-slot="{ navigate }"
custom
:to="to"
>
<button
role="link"
@click="onNavigation(navigate, $event)"
>
<slot></slot>
</button>
</router-link>
</template>
<script>
export default {
name: 'componentName',
props: {
to: {
type: String,
required: true,
},
},
methods: {
onNavigation(navigate, event) {
if (this.to === '#other-action') {
// do something
} else {
navigate(event);
}
return false;
},
};
</script>