vue.js学习

vuedose.tips(系列翻译七)

2019-10-05  本文已影响0人  知识文青

Create an ImageSelect component on top of vue-multiselect

在学习自适应组件的概念之前,有两个技巧,以及如何通过使用v-bind和v-on代理 props 和 events 来建立其基础。

现在是时候展示它了。 您有任何机会了解vue-multiselect吗? 这是Damian Dulisz构建的出色选择组件。 鉴于vue-multiselect的灵活性和可定制性,它可以以多种不同方式使用。 实际上,这是一种很好的第三方组件,以便可以重复使用。

根据其文档中的示例,我们构建一个ImageSelect组件。为此,该示例重新定义了vue-multiselect公开的一些作用域插槽:

Now it’s time to show it in action. By any chance, do you know aboutvue-multiselect? It’s an amazing select component built byDamian Dulisz. vue-multiselect can be used in many different ways given how flexible and customisable it is. That’s really how a fine third-party component should be in order to be reusable.

Based onthis examplefrom its documentation, let’s build an ImageSelect component. To do that, the example redefines some scoped slots that vue-multiselect exposes:

<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>

我不会进入作用域插槽,只是假设代码可以正常工作,以防您不了解它们。这里的事情是我想在该代码之上构建一个ImageSelect组件。

从上一个技巧开始,您可能已经知道您需要使用v-bind =“ props”和v-on =“ listeners”才能使对 props 和 events 的代理发生。

您还需要从原始的vue-multiselect组件中重新声明 propd,并且可以从其源代码的MultiselectMixin中获取它们:

<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>

如果运行此代码,您会发现有些东西无法正常工作。特别是show-labels属性。事实是,这不是 props,而是 attrs!并且可以通过$ attrs组件实例选项进行访问。

基本上,我们不仅需要代理 props,还需要代理 attrs 以使其工作。

为此,我将使用计算属性将props和 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>

You can try yourself and run the code on this Codesandbox example I’ve prepared for you. You’ll see it has some additional Adaptive Components, such as SingleSelect and MultiSelect.

Pss: they have some CSS tricks we’ll cover on the next tips

上一篇下一篇

猜你喜欢

热点阅读