基于VUE实用笔记(五),我们使用v-bind
and v-on
来制作一个实际的例子。
我想了解一下有人知道 vue-multiselect吗?这是 Damian Dulisz写的一个非常棒的组件。它可以非常灵活的用于很多场景中,甚至你完全自定义的场景。这真的是一个可重用的非常不错的第三方组件。
基于他的文档中的例子 ,我们来编译一个ImageSelect
组件。组件如下(下面的例子没有很好的利用VUE使用笔记(四)中的slot的新特性,我下面也会按照新特性去写一个):
<multiselect v-model="value" :options="options">
<template slot="singleLabel" slot-scope="{ option }">
<img class="option__image" :src="option.img" alt="Sth" />
<span class="option__desc">
<span class="option__title">{{ option.title }}</span>
</span>
</template>
<template slot="option" slot-scope="{ option }">
<img class="option__image" :src="option.img" alt="Sth" />
<span class="option__desc">
<span class="option__title">{{ option.title }}</span>
<span class="option__small">{{ option.desc }}</span>
</span>
</template>
</multiselect>
使用 v-slot
,上面的例子也可以这样写(当然这并不是本文章的重点,只是回顾一下):
<multiselect v-model="value" :options="options">
<template #singleLabel="{ option }">
<img class="option__image" :src="option.img" alt="Sth" />
<span class="option__desc">
<span class="option__title">{{ option.title }}</span>
</span>
</template>
<template #option="{ option }">
<img class="option__image" :src="option.img" alt="Sth" />
<span class="option__desc">
<span class="option__title">{{ option.title }}</span>
<span class="option__small">{{ option.desc }}</span>
</span>
</template>
</multiselect>
假如我们现在要基于上面的这个例子去实现一个ImageSelect
组件。
从VUE实用笔记(五)中,我们已经知道需要用v-bind="$props"
and v-on="$listeners"
来代理数据和监听事件。
我们也需要重新定义props从原始的vue-multiselect
组件。源码如下:
<template>
<multiselect v-bind="$props" v-on="$listeners">
<template slot="singleLabel" slot-scope="{ option }">
<img class="option__image" :src="option.img" alt="No Man’s Sky" />
<span class="option__desc">
<span class="option__title">{{ option.title }}</span>
</span>
</template>
<template slot="option" slot-scope="{ option }">
<img class="option__image" :src="option.img" alt="No Man’s Sky" />
<span class="option__desc">
<span class="option__title">{{ option.title }}</span>
<span class="option__small">{{ option.desc }}</span>
</span>
</template>
</multiselect>
</template>
<script>
import Multiselect from "vue-multiselect";
import MultiselectMixin from "vue-multiselect/src/multiselectMixin";
export default {
components: {
Multiselect
},
props: MultiselectMixin.props
};
</script>
在使用ImageSelect
组件时如何传递更少的参数呢,请看下面这个代码:
<template>
<ImageSelect
v-model="imageValue"
:options="imageOptions"
label="title"
track-by="title"
:show-labels="false"
/>
</template>
<script>
import ImageSelect from "./ImageSelect";
export default {
components: {
ImageSelect
},
data: () => ({
imageValue: null,
imageOptions: [
{ title: "Random img", img: "https://picsum.photos/300/150" },
{ title: "Cool image", img: "https://picsum.photos/300/151" }
]
})
};
</script>
但是如果你想传递一个非prop属性,那该怎么办呢?Vue的组件实例上还有一个 $attrs
属性。
如果你想两个同时传递,那就应该把这两个一起合并,用一个计算属性
来合并$props
and $attrs
,代码如下:
<template>
<multiselect v-bind="allBindings" v-on="$listeners">
<!-- ... -->
</multiselect>
</template>
<script>
import Multiselect from "vue-multiselect";
import MultiselectMixin from "vue-multiselect/src/multiselectMixin";
export default {
components: {
Multiselect
},
props: MultiselectMixin.props,
computed: {
allBindings() {
// Need to proxify both props and attrs, for example for showLabels
return { ...this.$props, ...this.$attrs };
}
}
};
</script>
我们可以在Alex准备的this Codesandbox example上尝试这个代码,还有其他的惊喜等着你,比如SingleSelect
and MultiSelect
,这两个组件的代码。
预告: 一些css的技巧将会在下个笔记中出现哦。
Remember you can read this tip online (with copy/pasteable code), and don’t forget to share VueDose with your colleagues, so they also know about these tips as well!
See you next week.
Alex