npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

vue-filter-box

v3.0.1

Published

vue-filter-box is a dynamic filter box base on view-design

Downloads

26

Readme

vue-filter-box

介绍

vue-filter-box 是一款基于 view-design 实现的动态筛选器组件, 通过传入筛选项结构 model, 可以帮助你快速生成一个筛选器!

如果你使用老版本的 vue-filter-box, 请移步这里: v2文档

快速开始

安装

# use npm
npm i vue-filter-box -s
# or yarn
yarn add vue-filter-box

注册

全局注册

import Vue from 'vue';
import ViewDesign from 'view-design';
import { VueFilterBox } from 'vue-filter-box';

import 'view-design/dist/styles/iview.css';

Vue.use(ViewDesign);
Vue.use(VueFilterBox);

组件内注册

注意: 请提前安装并引入 view-design!

<template>
  <vue-filter-box></vue-filter-box>
</template>

<script>
import { VueFilterBox } from '../packages/index';

export default {
  components: {
    VueFilterBox,
  },
};
</script>

使用

最简单的使用

model 表示筛选器结构, value 表示筛选器选中值:

<template>
  <div>
    <vue-filter-box :value="filterValue" :model="model"><vue-filter-box>
    <pre>{{ filterValue }}</pre>
  </div>
</template>

<script>
import { VueFilterBox } from 'vue-filter-box';

export default {
  components: {
    VueFilterBox,
  },
  data() {
    return {
      model: [
        {
          type: 'i-input',
          label: 'Keyword',
          key: 'keyword',
        },
        {
          type: 'i-select',
          label: 'Type',
          key: 'type',
          options: [
            { label: 'Type1', value: 'type1' },
            { label: 'Type2', value: 'type2' },
          ],
        },
      ],
      filterValue: {},
    };
  },
}
</script>

你也可以使用 v-model 来绑定 value, 这更加符合语义:

<vue-filter-box v-model="filterValue" :model="model" ></vue-filter-box>

筛选器默认选中值

你可以通过设置 value 的初始值来设置筛选器的默认选中值:

<template>
  <vue-filter-box :value="filterValue" :model="model">
</template>

<script>
export default {
  data() {
    return {
      model: [
        {
          type: 'i-input',
          label: 'Keyword',
          key: 'keyword',
        },
        {
          type: 'i-select',
          label: 'Type',
          key: 'type',
          options: [
            { label: 'Type1', value: 'type1' },
            { label: 'Type2', value: 'type2' },
          ],
        },
      ],
      filterValue: {
        keyword: '初始化设置的 keyword',
      },
    };
  },
}
</script>

在没有设置筛选项默认值时, vue-filter-box 可以做到一定程度的自动推导, 主要根据筛选项组件的 props.value 类型进行判断, 具体规则如下:

// 以下是筛选项 component props:
{
  props: {
    // 默认值`为 ''
    value: String,
    // 默认取第一个类型, 因此默认值为 0
    value: [Number, String],
    // 默认值为 ''
    value: {
      type: String,
    },
    // 默认取第一个类型, 因此默认值为 0
    value: {
      type: [Number, String],
    }
  }
}
// 当 props 为数组时, 因为无法判断 value 的类型, 因此默认设置 '', 这种情况最好是主动设置 vue-filter-box 的默认值:
props: ['value']

举个 🌰, 当 model 为以下结构时:

model: [
  {
    type: 'i-input',
    label: 'Keyword',
    key: 'keyword',
  },
  {
    type: 'checkbox-group',
    label: 'Type',
    key: 'type',
    options: [
      { label: 'Type1', value: 'type1' },
      { label: 'Type2', value: 'type2' },
    ],
  },
],

value 将自动推导成:

{
  keyword: '',
  type: [],
}

筛选项标题

modelItem 中, 通过设置 label 来定义你的筛选项标题, label 可以是 string 类型, 也可以是 function 类型:

<template>
  <vue-filter-box :model="model">
</template>

<script>
  export default {
    data() {
      return {
        model: [
          {
            type: 'i-input',
            label: 'Keyword',
            key: 'keyword',
          },
          {
            type: 'i-input',
            label: h => h('span', 'name'),
            key: 'name',
          },
        ],
      };
    },
  };
</script>

函数式 label 的格式为: (h: CreateElement) => VNode; CreateElement 格式具体可以查看 vue createElement 😊

筛选项组件

modelItem 中, 通过设置 type 来定义你的筛选项组件: type 可以是 string 类型, 如 i-select , 或者 i-input, 但请确保组件已经全局注册即可; type 也可以是 component 类型:

<template>
  <vue-filter-box :model="model">
</template>

<script>
  import YourFilterComponent from './your-filter-component.vue';
  export default {
    data() {
      return {
        model: [
          {
            type: YourFilterComponent,
            label: 'Keyword',
            key: 'keyword',
          },
        ],
      };
    },
  };
</script>

请确保你的组件可以使用 v-model 进行双向数据绑定!

筛选项宽度设置

vue-filter-box 默认每个筛选项的最大宽度为 300px, 你可以通过设置 max-width 来覆盖他:

<vue-filter-box v-model="filterValue" :model="model" max-width="200px"><vue-filter-box>

通过设置 widthmin-width, 可以分别设置筛选项的固定宽度和最小宽度, 值得注意的是: 设置 width 后, 默认的 max-width 将会失效, 如果你需要 widthmax-width 一同生效, 请在设置 width 的同时也设置 max-width:

<vue-filter-box v-model="filterValue" :model="model" width="20%" max-width="400px"><vue-filter-box>

若你需要为每个筛选项单独定制宽度, 可以在 modelItem 中进行定义:

{
  model: [
    {
      type: 'i-input',
      label: 'Keyword',
      key: 'keyword',
      width: '20%',
      maxWidth: '400px',
    },
    {
      type: 'i-select',
      label: 'Type',
      key: 'type',
      width: '250px',
      options: [
        { label: 'Type1', value: 'type1' },
        { label: 'Type2', value: 'type2' },
      ],
    },
  ],
}

宽度也可以是 number 类型, 单位为 px

筛选器标题宽度设置

vue-filter-box 默认每个筛选项的标题最大宽度为 120px, 当标题长度超出时展示省略号; 你可以通过传入 labelMaxWidth 覆盖他:

<vue-filter-box v-model="filterValue" :model="model" label-max-width="200px"><vue-filter-box>

同样的, 你也可以为标题设置一个固定值 label-width, 在设置 label-width 后默认的 label-max-width 将会失效:

<vue-filter-box v-model="filterValue" :model="model" label-width="200px"><vue-filter-box>

若你需要为每个筛选项标题定制宽度, 可以在 modelItem 进行定义:

{
  model: [
    {
      type: 'i-input',
      label: 'Keyword',
      key: 'keyword',
      labelWidth: '150px',
    },
  ],
}

筛选器布局模式

默认情况下布局模式为 horizontal, 你也可以设置为 vertical:

<vue-filter-box mode="vertical"></vue-filter-box>

loading 状态

通过设置 loading 可开启 vue-filter-box 的加载状态:

<vue-filter-box v-model="filterValue" :model="model" loading><vue-filter-box>

你可以通过设置 slot 来替换默认的 loading 样式:

<vue-filter-box v-model="filterValue" :model="model" :loading="true">
  <template v-slot:loading>
    <p>loading...</p>
  </template>
<vue-filter-box>

禁用状态

通过设置 disabled 可开启禁用筛选项状态:

<vue-filter-box disabled></vue-filter-box>

注意: 请确保筛选项组件支持 disabled prop!

筛选项组件大小

通过设置 size 设置筛选项组件大小:

<vue-filter-box size="small"></vue-filter-box>

注意: 请确保筛选项组件支持 size prop!

表单校验

通过设置 rules 可以定制你的表单规则:

<vue-filter-box :rules="rules" :model="model"></vue-filter-box>

<script>
  export default {
    data() {
      return {
        model: [
          {
            type: 'i-select',
            key: 'roleType',
            options: [
              { label: 'Type1', value: 'type1' },
            ],
          }
        ],
        rules: {
          roleType: [{ required: true, message: 'This field is required.' }],
        },
      };
    },
  };
</script>

具体校验规则可以查看: async-validator

底部栏

footer 插槽可以让你设置筛选器的底部栏, 一般是按钮组; 你可以通过调用 footer 插槽 props 中的 validate 以及 validField 进行表单校验, 也可以调用 reset 以及 resetField 进行表单重置:

<vue-filter-box>
  <template v-slot:footer="{ validate, reset, validateField, resetField }">
    <div>
      <i-button @click="validate(onSubmit)">提交</i-button>
      <i-button @click="validateField('prop', onSubmit)">校验 prop</i-button>
      <i-button @click="reset">重置</i-button>
      <i-button @click="resetField('prop')">重置 prop</i-button>
    </div>
  </template>
</vue-filter-box>

<script>
  export default {
    methods: {
      onSubmit(valid) {
        if (valid) {
					// ...submit your data
        }
      },
    },
  };
</script>

底部栏默认跟随最后一个筛选项, 若想要底部栏独占一行, 可以通过设置 footer-one-line 实现:

<vue-filter-box footer-one-line>
  <template v-slot:footer="{ validate, reset, validateField, resetField }">
    <div>
      <i-button @click="validate(onSubmit)">提交</i-button>
      <i-button @click="validateField('prop', onSubmit)">校验 prop</i-button>
      <i-button @click="reset">重置</i-button>
      <i-button @click="resetField('prop')">重置 prop</i-button>
    </div>
  </template>
</vue-filter-box>

API

Props

| 属性 | 类型 | 默认值 | 是否必填 | 描述 | | ------------- | ---------------------------------------------------------- | -------------- | -------- | ------------------------------------------------------------ | | model | modelItem[], modelItem 具体查看: ModelItem | [] | | 筛选器结构 | | value | object | {} | | 筛选器对应值 | | width | string, number | | | 筛选项宽度 | | maxWidth | string, number | 300 | | 筛选项最大宽度 | | minWidth | string, number | | | 筛选项最小宽度 | | labelWidth | string, number | | | 筛选项标题宽度, 超出展示省略号 | | labelMaxWidth | string, number | 120 | | 筛选项标题最大宽度 | | hiddenColon | boolean | false | | 是否隐藏筛选项标题后的冒号 | | mode | 'horizontal', 'vertical' | 'horizontal' | | 筛选器布局模式, horizontal 是平铺模式, vertical 是垂直模式 | | disabled | boolean | false | | 是否禁用筛选器 | | loading | boolean | false | | 是否展示加载状态 | | rules | object | | | 筛选器校验规则, 具体可查看 async-validator | | footerOneLine | boolean | false | | 底部栏是否独占一行 | | alias | object | {} | | 筛选项组件别名 | | size | default, small, large | default | | 筛选项组件大小 |

Slots

| 名称 | 描述 | | ------- | -------- | | footer | 底部栏 | | loading | 加载状态 |

footer 插槽 props:

| 属性 | 类型 | 描述 | | ------------- | ----------------------------------------------------------- | ------------------ | | validate | (callback: (valid: boolean) => void) => void | 表单校验函数 | | validateField | (key: string, callback: (valid: boolean) => void) => void | 单个表单项校验函数 | | reset | () => void | 表单重置函数 | | resetField | (key: string) => void | 单个表单项重置函数 | | loading | boolean | 加载状态 |

loading 插槽 props:

| 属性 | 类型 | 描述 | | ------- | --------- | -------- | | loading | boolean | 加载状态 |

ModelItem

筛选器结构描述对象, 多个 modelItem 构成 model:

| 属性名 | 类型 | 默认值 | 是否必填 | 描述 | | ------------- | ----------------------------------------- | ----------- | -------- | ------------------------------------------------------------ | | type | string, component | | 是 | 筛选项组件, 如 'i-input' | | label | string, (h: CreateElement) => VNode | '' | | 筛选项标题; CreateElement 可查看: vue createElement | | key | string | | 是 | 筛选项对应的 key | | width | string, number | | | 筛选项宽度 | | maxWidth | string, number | 300 | | 筛选项最大宽度 | | minWidth | string, number | | | 筛选项最小宽度 | | labelWidth | string, number | | | 筛选项标题宽度 | | labelMaxWidth | string, number | 120 | | 筛选项标题最大宽度 | | hiddenColon | boolean | false | | 是否隐藏筛选项标题后的冒号 | | disabled | boolean | false | | 是否禁用 | | rules | object, array | | | 筛选器校验规则, 具体可查看async-validator | | options | Array<{ label: string, value: string }> | [] | | 选项列表, 当 typei-select 或是 checkbox-group 时生效, label 为展示文本, value 为选项值 | | size | 'default', 'small', 'large' | 'default' | | 筛选项组件大小 | | props | object | {} | | 筛选项组件 props | | events | object | {} | | 筛选项组件事件回调 |

注意: modelItem 属性优先级比 props 高, 例如, 同时设置 width 时, 将会以 modelItem 的为准 😊

问题反馈

如果发现组件中存在的问题或是不足,可以提交你的问题到 github issue, 或提交一个 Pull Request, 感谢你的参与!