扩展Vue.js SFC组件
我还没有找到扩展Vue.js组件的好资源。在我参与的每个项目中,不管使用的是什么UI组件库,都有一些应用程序基础组件,它们扩展UI库组件以强制执行公司/应用程序默认值和标准 我正在尝试扩展Vue Multiselect:它有大约30个道具和12个插槽。我正在扩展的组件并不重要——我之所以提到它,是因为理想情况下,我不想在我的实现中重复30个道具和12个插槽 我只想对组件的行为进行两个更改: 使扩展Vue.js SFC组件,vue.js,vue-component,Vue.js,Vue Component,我还没有找到扩展Vue.js组件的好资源。在我参与的每个项目中,不管使用的是什么UI组件库,都有一些应用程序基础组件,它们扩展UI库组件以强制执行公司/应用程序默认值和标准 我正在尝试扩展Vue Multiselect:它有大约30个道具和12个插槽。我正在扩展的组件并不重要——我之所以提到它,是因为理想情况下,我不想在我的实现中重复30个道具和12个插槽 我只想对组件的行为进行两个更改: 使禁用道具更智能一点 Vue Multiselect组件有一个标准的禁用的道具,该道具按预期工作: <
禁用
道具更智能一点
Vue Multiselect组件有一个标准的禁用的道具,该道具按预期工作:
<Multiselect :disabled="isDisabled" ...>
在我们的应用程序中,Vuex中有全局状态,用于确定应用程序是否为只读。我想要避免的是要求开发人员将此状态传递给每个表单字段:
<Multiselect :disabled="readOnly || isDisabled" ...>
<OtherComponent :disabled="readOnly || someOtherCondition" ...>
...
...
因此,my base component的用户只需关心影响禁用状态的本地UI状态:
<BaseCombo :disabled="!emailValid" ...>
这将处理90%的表单字段在应用程序为只读时被锁定的情况,对于我们希望忽略全局只读状态的情况,我可以使用额外的道具
<BaseCombo :disabled="!emailValid" :ignoreReadOnly="true" ...>
提供默认值
其次,我只想覆盖一些默认的prop值。这篇文章讨论了提供默认值的问题:
在我试图修改我前面提到的残疾人道具的行为之前,这是非常有效的
我试图解决这个问题的方法是包装或扩展组件。如果可能的话,我真的想避免重新说明所有的道具
<template>
<Multiselect
:disabled="myCustomDisabled"
:value="value"
@input="$emit('input', $event)"
:options="options"
:label="label"
:track-by="trackBy"
:placeholder="placeholder"
... repeat for all 30 options
<script>
import Multiselect from 'vue-multiselect'
export default {
name: "BaseCombo",
extends: Multiselect, // extend or simply wrap?
computed: {
myCustomDisabled() {
this.props.disabled || ... use disabled from Vuex state
}
},
props: {
disabled: Boolean,
placeholder: {
type: String,
default: 'My Default Value',
},
... repeat for all props
您可以使用this.$props
访问props属性中定义的道具。同样,您可以使用this.$attrs
访问属性(您没有定义为道具的东西)。最后,您可以使用v-bind=“someVariable”
绑定道具
如果将这些结合起来,您可以执行以下操作:
<!-- App.vue -->
<template>
<component-a msg="Hello world" :fancy="{ test: 1 }" />
</template>
导出默认值{
名称:“组件A”
}
{{msg}}
{{fancy}
导出默认值{
道具:{
msg:String,
幻想:对象
},
挂载(){
console.log(这是$props);
}
}
在本例中,组件B将是您尝试扩展的组件。您可以使用this.$props
访问props属性中定义的props。同样,您可以使用this.$attrs
访问属性(您没有定义为道具的东西)。最后,您可以使用v-bind=“someVariable”
绑定道具
如果将这些结合起来,您可以执行以下操作:
<!-- App.vue -->
<template>
<component-a msg="Hello world" :fancy="{ test: 1 }" />
</template>
导出默认值{
名称:“组件A”
}
{{msg}}
{{fancy}
导出默认值{
道具:{
msg:String,
幻想:对象
},
挂载(){
console.log(这是$props);
}
}
在本例中,组件B将是您尝试扩展的组件。以下是一个基于Sumurai8的答案和motia的评论的完整示例
<template>
<Multiselect v-bind="childProps" v-on="$listeners">
<slot v-for="(_, name) in $slots" :name="name" :slot="name" />
<template v-for="(_, name) in $scopedSlots" :slot="name" slot-scope="slotData">
<slot :name="name" v-bind="slotData" />
</template>
</Multiselect>
</template>
<script>
import Multiselect from 'vue-multiselect'
export default {
name: "BaseCombo",
props: {
placeholder: {
type: String,
default: 'This is my default',
},
disabled: {
type: Boolean,
default: false,
},
},
components: {
Multiselect,
},
computed: {
childProps() {
return { ...this.$props, ...this.$attrs, disabled: this.isDisabled };
},
appReadOnly() {
return this.$store.state.appReadOnly;
},
isDisabled() {
return this.disabled || this.appReadOnly;
}
},
}
</script>
从“vue Multiselect”导入Multiselect
导出默认值{
名称:“BaseCombo”,
道具:{
占位符:{
类型:字符串,
默认值:“这是我的默认值”,
},
残疾人士:{
类型:布尔型,
默认值:false,
},
},
组成部分:{
多选,
},
计算:{
儿童道具(){
返回{…this.$props,…this.$attrs,disabled:this.isDisabled};
},
appReadOnly(){
返回此。$store.state.appReadOnly;
},
isDisabled(){
返回this.disabled | | this.appReadOnly;
}
},
}
以下是一个基于Sumurai8答案和motia评论的完整示例
<template>
<Multiselect v-bind="childProps" v-on="$listeners">
<slot v-for="(_, name) in $slots" :name="name" :slot="name" />
<template v-for="(_, name) in $scopedSlots" :slot="name" slot-scope="slotData">
<slot :name="name" v-bind="slotData" />
</template>
</Multiselect>
</template>
<script>
import Multiselect from 'vue-multiselect'
export default {
name: "BaseCombo",
props: {
placeholder: {
type: String,
default: 'This is my default',
},
disabled: {
type: Boolean,
default: false,
},
},
components: {
Multiselect,
},
computed: {
childProps() {
return { ...this.$props, ...this.$attrs, disabled: this.isDisabled };
},
appReadOnly() {
return this.$store.state.appReadOnly;
},
isDisabled() {
return this.disabled || this.appReadOnly;
}
},
}
</script>
从“vue Multiselect”导入Multiselect
导出默认值{
名称:“BaseCombo”,
道具:{
占位符:{
类型:字符串,
默认值:“这是我的默认值”,
},
残疾人士:{
类型:布尔型,
默认值:false,
},
},
组成部分:{
多选,
},
计算:{
儿童道具(){
返回{…this.$props,…this.$attrs,disabled:this.isDisabled};
},
appReadOnly(){
返回此。$store.state.appReadOnly;
},
isDisabled(){
返回this.disabled | | this.appReadOnly;
}
},
}
谢谢。如果组件B有插槽呢?Multiselect组件有12个插槽。除了现在的this.$slots
之外,其他都是相同的想法。我不久前在“谢谢”上写了一个关于这个问题的答案,它似乎工作得很好。我借用了这个要点中的scopedSlot示例,它与您的帖子类似:@nogridbag,我认为您还需要公开Mulitselect发出的事件。谢谢。我贴出了一个答案,看起来很有效。我相信唯一剩下的事情就是像你说的那样揭露剩下的事件。谢谢。如果组件B有插槽呢?Multiselect组件有12个插槽。除了现在的this.$slots
之外,其他都是相同的想法。我不久前在“谢谢”上写了一个关于这个问题的答案,它似乎工作得很好。我借用了这个要点中的scopedSlot示例,它与您的帖子类似:@nogridbag,我认为您还需要公开Mulitselect发出的事件。谢谢。我贴出了一个答案,看起来很有效。我相信剩下的事情就是像你说的那样公开剩下的事件。当使用扩展:Multiselect时,你不需要。。。对所有道具重复此操作
,因为扩展中给出的道具与原始道具合并。模板更改确实需要重复所有属性,但对于您的场景,您可能不必触摸模板(只需在扩展组件中忽略它)。相反,你可能会成功