Vue.js 3 个可选的 v-scroll-to
Vue.js 3 optional v-scroll-to
这是我使用的代码。
<template>
<div class="button-layout" :style="`margin: ${margin}; text-align: ${align};`">
<component
:is="buttonComponent"
v-for="(button, index) in buttons.filter(btn => btn.url)"
:key="button.label"
:label="button.label"
v-scroll-to="button.url"
:style="`margin-left: ${index === 0 ? '' : space};`" />
<component
:is="buttonComponent"
v-for="(button, index) in buttons.filter(btn => !btn.url)"
:key="button.label"
:label="button.label"
:type="button.type"
:style="`margin-left: ${index === 0 ? '' : space};`" />
</div>
</template>
<script>
export default {
name: "ButtonLayout",
components: { },
props: {
button: String,
margin: String,
align: String,
space: String,
buttons: Array
},
computed: {
buttonComponent() {
return () => import(`./button/${this.button}`)
}
}
};
</script>
我可以使用这两个对象结构列表,而且效果很好。
[
{ url: '#video', label: lang.video },
{ url: '#info', label: lang.info }
]
[
{ type: 'reset', label: lang.clear },
{ type: 'submit', label: lang.send }
]
因为我不喜欢重复我的代码,所以我尝试根据列表中的第一个对象动态添加属性 type
和 v-scroll-to
,但是,它不起作用。实现它的最佳方法是什么? (见下方代码)
<template>
<div class="button-layout" :style="`margin: ${margin}; text-align: ${align};`">
<component
:is="buttonComponent"
v-for="(button, index) in buttons"
:key="button.label"
:label="button.label"
v-bind:[optionalDirective.directive]="button[optionalDirective.key]"
:style="`margin-left: ${index === 0 ? '' : space};`" />
</div>
</template>
<script>
export default {
name: "ButtonLayout",
components: { },
props: {
button: String,
margin: String,
align: String,
space: String,
buttons: Array
},
computed: {
buttonComponent() {
return () => import(`./button/${this.button}`)
},
optionalDirective(){
if(this.buttons[0].url) {
return {
directive: 'v-scroll-to',
key: 'url'
}
} else {
return {
directive: 'type',
key: 'type'
}
}
}
}
};
</script>
您可以将对象传递给 v-bind
,它将根据对象的键创建 html 属性。
像这样的东西应该可以工作
<component
:is="buttonComponent"
v-for="(button, index) in buttons"
:key="button.label"
:label="button.label"
v-bind="{[button.url ? 'v-scroll-to' : 'type' ] : (button.url || button.type} }"
:style="`margin-left: ${index === 0 ? '' : space};`" />
或者您可以声明一个新方法,returns 所需的对象
methods: {
buttonDirective (button) {
if (button.url) {
return {
'v-scroll-to': button.url
}
} else {
return {
'type': button.type
}
}
}
}
然后在component
中调用
<component
:is="buttonComponent"
v-for="(button, index) in buttons"
:key="button.label"
:label="button.label"
v-bind="buttonDirective(button)"
:style="`margin-left: ${index === 0 ? '' : space};`" />
由于 v-scroll-to
不能绑定到 v-bind
,我发现了一些实际解决我的问题并避免重复代码两次的变通办法。我将 @click
绑定到检查 url
值和 $scollTo
(如果需要)的方法,它解决了我的问题。
<template>
<div class="button-layout" :style="`margin: ${margin}; text-align: ${align};`">
<component
:is="buttonComponent"
v-for="(button, index) in buttons"
:key="button.label"
:label="button.label"
v-bind="type(button.type)"
@click="scrollTo(button.url)"
:style="`margin-left: ${index === 0 ? '' : space};`"
/>
</div>
</template>
<script>
export default {
name: "ButtonLayout",
components: {},
props: {
button: String,
margin: String,
align: String,
space: String,
buttons: Array
},
methods: {
type(type) {
return type ? { type } : {}
},
scrollTo(url) {
if (url) this.$scrollTo(url)
}
},
computed: {
buttonComponent() {
return () => import(`./button/${this.button}`);
}
}
};
</script>
这是我使用的代码。
<template>
<div class="button-layout" :style="`margin: ${margin}; text-align: ${align};`">
<component
:is="buttonComponent"
v-for="(button, index) in buttons.filter(btn => btn.url)"
:key="button.label"
:label="button.label"
v-scroll-to="button.url"
:style="`margin-left: ${index === 0 ? '' : space};`" />
<component
:is="buttonComponent"
v-for="(button, index) in buttons.filter(btn => !btn.url)"
:key="button.label"
:label="button.label"
:type="button.type"
:style="`margin-left: ${index === 0 ? '' : space};`" />
</div>
</template>
<script>
export default {
name: "ButtonLayout",
components: { },
props: {
button: String,
margin: String,
align: String,
space: String,
buttons: Array
},
computed: {
buttonComponent() {
return () => import(`./button/${this.button}`)
}
}
};
</script>
我可以使用这两个对象结构列表,而且效果很好。
[
{ url: '#video', label: lang.video },
{ url: '#info', label: lang.info }
]
[
{ type: 'reset', label: lang.clear },
{ type: 'submit', label: lang.send }
]
因为我不喜欢重复我的代码,所以我尝试根据列表中的第一个对象动态添加属性 type
和 v-scroll-to
,但是,它不起作用。实现它的最佳方法是什么? (见下方代码)
<template>
<div class="button-layout" :style="`margin: ${margin}; text-align: ${align};`">
<component
:is="buttonComponent"
v-for="(button, index) in buttons"
:key="button.label"
:label="button.label"
v-bind:[optionalDirective.directive]="button[optionalDirective.key]"
:style="`margin-left: ${index === 0 ? '' : space};`" />
</div>
</template>
<script>
export default {
name: "ButtonLayout",
components: { },
props: {
button: String,
margin: String,
align: String,
space: String,
buttons: Array
},
computed: {
buttonComponent() {
return () => import(`./button/${this.button}`)
},
optionalDirective(){
if(this.buttons[0].url) {
return {
directive: 'v-scroll-to',
key: 'url'
}
} else {
return {
directive: 'type',
key: 'type'
}
}
}
}
};
</script>
您可以将对象传递给 v-bind
,它将根据对象的键创建 html 属性。
像这样的东西应该可以工作
<component
:is="buttonComponent"
v-for="(button, index) in buttons"
:key="button.label"
:label="button.label"
v-bind="{[button.url ? 'v-scroll-to' : 'type' ] : (button.url || button.type} }"
:style="`margin-left: ${index === 0 ? '' : space};`" />
或者您可以声明一个新方法,returns 所需的对象
methods: {
buttonDirective (button) {
if (button.url) {
return {
'v-scroll-to': button.url
}
} else {
return {
'type': button.type
}
}
}
}
然后在component
<component
:is="buttonComponent"
v-for="(button, index) in buttons"
:key="button.label"
:label="button.label"
v-bind="buttonDirective(button)"
:style="`margin-left: ${index === 0 ? '' : space};`" />
由于 v-scroll-to
不能绑定到 v-bind
,我发现了一些实际解决我的问题并避免重复代码两次的变通办法。我将 @click
绑定到检查 url
值和 $scollTo
(如果需要)的方法,它解决了我的问题。
<template>
<div class="button-layout" :style="`margin: ${margin}; text-align: ${align};`">
<component
:is="buttonComponent"
v-for="(button, index) in buttons"
:key="button.label"
:label="button.label"
v-bind="type(button.type)"
@click="scrollTo(button.url)"
:style="`margin-left: ${index === 0 ? '' : space};`"
/>
</div>
</template>
<script>
export default {
name: "ButtonLayout",
components: {},
props: {
button: String,
margin: String,
align: String,
space: String,
buttons: Array
},
methods: {
type(type) {
return type ? { type } : {}
},
scrollTo(url) {
if (url) this.$scrollTo(url)
}
},
computed: {
buttonComponent() {
return () => import(`./button/${this.button}`);
}
}
};
</script>