阅读 4564

合格前端系列第八弹-造一个属于自己的 UI 库

轮子嘛~总得造上一造~

项目介绍

vui:一个私人的vue ui 组件库(移动端为主)

It's a A personal Vue UI component library .

文档官网

进入 PC 端直接是文档界面,想查看 demo 效果直接将浏览器调成手机模式即可,如果喜欢,还请不要吝惜你的 star 哦~~

在线效果预览

请扫描以下二维码

已有组件

安装

npm i x-vui -S
复制代码

快速开始

构建项目(配合 vue-cli)

# 全局安装 vue-cli
npm install --global vue-cli
# 创建一个基于 webpack 模板的新项目
vue init webpack my-vui-project
# 安装依赖,并下载x-vui
cd my-vui-project
npm install && npm install x-vui
# 项目启动 默认端口localhost:8080
npm run dev
复制代码

完整引入

import Vue from 'vue'
import vui from 'x-vui'
import 'x-vui/lib/vui-css/index.css';

Vue.use(vui)
复制代码

部分引入

import Vue from 'vue'
import {
  Scroller,
  Select
  // ...
} from 'x-vui'
import 'x-vui/lib/vui-css/scroller.css';
import 'x-vui/lib/vui-css/select.css';

Vue.component(Scroller.name, Scroller)
Vue.component(Select.name, Select)
复制代码

引入插件

注:完整引入了vui,则无需再注册插件

import Vue from 'vue';
import { 
  $Toast, 
  $Dialog 
  // ...
} from 'x-vui';

Vue.prototype.$toast = $Toast
Vue.prototype.$dialog = $Dialog
复制代码

组件用法

1. swiper

目前这里默认为 swiper 轮播图,如果你有特殊需要,也可以使用swipe和swipe-item组合出自己的swiper

基本用法

<template>
  <div class="swiper-page">
    <p>正常swiper</p>
    <v-swiper :items='items' :styles="{height: '200px'}" @change="changeHandle"></v-swiper>
    <p>缩略swiper</p>
    <v-swiper type='thum' :items='items' :styles="{height: '240px'}"></v-swiper>
  </div>
</template>
<script>
export default {
  data () {
    return {
      items: [
        require('../assets/beauty_1.png'),
        require('../assets/beauty_2.png'),
        require('../assets/beauty_3.png'),
        require('../assets/beauty_4.png'),
        require('../assets/beauty_5.png')
      ],
    }
  },
  methods: {
    changeHandle (index) {
      console.log(index);
    }
  }
}
</script>
复制代码

Attributes

参数 说明 类型 可选值 默认值
type swiper类型 string swiper(正常)/thum(缩略) swiper
auto 自动播放时长 number 5000
items swiper展示的列表 array []
showIndicators 是否展示swiper小圆点 boolean true
styles swiper样式控制 object {}
resetTitle 重置title内容 string

Events

事件名称 说明 回调参数
change swiper滑动回调 当前swiper item索引

2. scroller(下拉刷新上拉加载)

经常用来做手机端的分页功能,下拉刷新,上拉加载

基本用法

<template>
  <div class="scroller-page">
    <v-scroller
      :on-refresh="refresh"
      :on-infinite="infinite"
    >
      <ul>
        <li v-for="(list, index) in lists" :key="index">{{list}}</li>
      </ul>
    </v-scroller>
  </div>
</template>
<script>
export default {
  data () {
    return {
      len: 6,
    }
  },
  computed: {
    lists () {
      let arr = []
      for (let i = 1; i < this.len + 1; i++) {
        arr.push('列表' + i)
      }
      return arr
    }
  },
  methods: {
    // 下拉刷新
    refresh (done) {
      setTimeout(() => {
        this.len = 6
        done()
      }, 1000)
    },
    // 上拉加载
    infinite (done) {
      setTimeout(() => {
        if (this.len >= 7) {
          done(true)
          return
        }
        this.len++
        done()
      }, 1000)
    }
  }
}
</script>
复制代码

Attributes

参数 说明 类型 可选值 默认值
onRefresh 下拉回调 function
onInfinite 上拉回调 function
width scroller宽度 string 100%
height scroller高度 string 100%
isLoadMore 是否展示上拉加载 boolean true
refreshText 下拉文本内容 string 下拉刷新
noDataText 无数据文本 string 没有更多数据啦~
refreshLayerColor 下拉文本颜色 string #AAA
loadingLayerColor 上拉文本颜色 string #AAA
animating 是否有动画 boolean true
animationDuration 动画间隔 number 250
bouncing 是否有反弹效果 string true
cssClass content css class string

Events

事件名称 说明 回调参数
onRefresh 下拉回调 里面有个done callback用于结束loading效果
onInfinite 上拉回调 里面有个done callback用于结束loading效果

3. search

常用于手机端搜索关键字,有时候还会进行高亮匹配

基本用法

1、只有搜索框

<template>
  <v-search
    placeholder="请输入搜索关键字"
    @search="searchFn"
    @enter="searchEnter"
  ></v-search>
</template>
<script>
export default {
  methods: {
    searchFn (query) {
      console.log('search', query)
    },
    searchEnter (query) {
      console.log('enter', query)
    }
  }
}
</script>
复制代码

2、搭配 SearchList 搜索结果列表

<template>
  <v-search
    placeholder="请输入搜索关键字"
    :async="false"
    @search="searchFn"
  >
    <v-search-list :result="filterResult" @listSearch="listSearch" v-show="visible"></v-search-list>
  </v-search>
</template>
<script>
export default {
  data () {
    return {
      keyword: '',
      visible: false, // 点击列表,列表是否消失
      defaultResult: [
        'Apple',
        'Banana',
        'Orange',
        'Durian',
        'Lemon',
        'Peach',
        'Cherry',
        'Berry',
        'Core',
        'Fig',
        'Haw',
        'Melon',
        'Plum',
        'Pear',
        'Peanut',
        'Other'
      ]
    }
  },
  watch: {
    keyword (val) {
      if (!val) {
        this.visible = false;
      }
    }
  },
  methods: {
    searchFn (query) {
      this.keyword = query;
      this.visible = true;
    }
  },
  computed: {
    filterResult() {
      return this.defaultResult.filter(item => new RegExp(this.keyword, 'i').test(item));
    }
  }
}
</script>
复制代码

高阶用法

3、定制化结果列表,关键字高亮匹配

<template>
  <v-search
    placeholder="请输入搜索关键字"
    :async="false"
    @search="searchFn"
  >
    <v-search-list :result="filterResult" @listSearch="listSearch" v-show="visible">
      <div class="search-result" slot="list-item" slot-scope="props">
        <p class="l" v-html="props.slotValue.name"></p>
        <p class="gray" v-show="props.slotValue.price">¥{{props.slotValue.price}}/斤</p>
        <div class="gray r" v-show="props.slotValue.amount">剩余{{props.slotValue.amount}}斤</div>
      </div>
    </v-search-list>
  </v-search>
</template>
<script>
export default {
  data () {
    return {
      keyword: '',
      visible: false,
      defaultResult: [
        {name: 'Apple', price: 5, amount: 20},
        {name: 'Banana', price: 5, amount: 30},
        {name: 'Orange', price: 3, amount: 10},
        {name: 'Durian', price: 10, amount: 25},
        {name: 'Lemon', price: 4, amount: 30},
        {name: 'Peach', price: 5, amount: 40},
        {name: 'Cherry', price: 20, amount: 50},
        {name: 'Berry', price: 15, amount: 60},
        {name: 'Core', price: 10, amount: 21},
        {name: 'Fig', price: 10, amount: 22},
        {name: 'Haw', price: 10, amount: 23},
        {name: 'Melon', price: 10, amount: 24},
        {name: 'Plum', price: 10, amount: 25},
        {name: 'Pear', price: 10, amount: 26},
        {name: 'Peanut', price: 10, amount: 27},
        {name: 'Other'}
      ],
      // 防止defaultResult值被污染
      copy: []
    }
  },
  watch: {
    keyword (val) {
      if (!val) {
        this.visible = false;
      }
    }
  },
  methods: {
    searchFn (query) {
      this.keyword = query;
      this.visible = true;
    },
    listSearch (index) {
      this.visible = false;
      console.log(index, this.defaultResult[index].name)
    }
  },
  computed: {
    filterResult() {
      // i 忽略大小写
      let result = this.defaultResult.filter(item => new RegExp(this.keyword, 'i').test(item.name));
      // 关键字高亮匹配
      this.copy = JSON.parse(JSON.stringify(result))
      this.copy.forEach((item, index) => {
        let name = item.name, word = this.keyword;
        name = name.toLowerCase();
        word = word.toLowerCase();

        if (word && name.indexOf(word) !== -1) {
          let arr    = item.name.split('')
          let i      = name.indexOf(word);
          let len    = word.length;
          let active = '<span class="price">' + arr.splice(i, len).join('') + '</span>';
          arr.splice(i, 0, active);
          item.name  = arr.join('');
        }
      })
      return this.copy;
    }
  }
}
</script>
复制代码

Attributes

参数 说明 类型 可选值 默认值
async 是否进行节流 boolean true
timeout 搜索节流时长 number 100
styles search样式 object
placeholder placeholder string '搜索'
autofocus 是否自动聚焦(iOS端autofocus无效) boolean
clear 进行搜索是否清空search框内容 boolean false

Events

事件名称 说明 回调参数
search search搜索回调 搜索文本
enter enter时搜索回调 搜索文本
close 点击搜索关闭按钮回调 ''

4. Dialog 弹框

基本用法

<template>
  <example-block title="基础用法">
    <button @click="showSimpleDialog">普通 Dialog</button>
  </example-block>
</template>
<script>
export default {
  methods: {
    showSimpleDialog () {
      this.$dialog({
        title: '普通 Dialog',
        cancelText: '取消',
        okText: '确定',
        content: '测试 Dialog,测试 Dialog,测试 Dialog~~~'
      })
    }
  }
}
</script>
复制代码

自定义 HTML

<template>
  <example-block title="自定义 HTML">
    <button @click="showHtmlDialog">HTML Dialog</button>
  </example-block>
</template>
<script>
export default {
  methods: {
    showHtmlDialog () {
      this.$dialog({
        title: '自定义 HTML',
        cancelText: '取消',
        okText: '确定',
        content: '<strong style="color: green">测试 Dialog,测试 Dialog,测试 Dialog~~~</strong style="color: green">'
      })
    }
  }
}
</script>
复制代码

高阶Dialog组件用法

<template>
  <div>
    <example-block title="Dialog 模板">
      <button @click="showDialogTpl">Dialog Template</button>
    </example-block>
    <v-dialog
    title="Dialog 模板"
    cancelText="取消"
    okText="确认"
    content="测试 Dialog,测试 Dialog,测试 Dialog~~~"
    :show="showDialog"
    :onCancel="close"
    :onOk="close"
    >
      <p class="modal-text">Dialog Template slot !!!</p>
    </v-dialog>
  </div>
</template>

<script>
export default {
  data () {
    return {
      showDialog: false
    }
  },
  methods: {
    showDialogTpl () {
      this.showDialog = true
    },
    close () {
      this.showDialog = false
    }
  }
}
</script>

复制代码

Attributes(modal)

参数 说明 类型 可选值 默认值
show modal是否显示 boolean
title modal标题 string
content modal内容 string
onOk 确定按钮回调 function
onCancel 取消按钮回调 function
okText 确定按钮内容 string
cancelText 取消按钮内容 string
showCloseIcon 是否显示关闭icon boolean true

5. Toast 轻提示

基本用法

<template>
  <example-block title="基础用法">
    <button @click="showSimpleToast">普通文字提示</button>
  </example-block>
</template>
<script>
export default {
  methods: {
    showSimpleToast () {
      this.$toast({msg: '我是文字提示~'});
    }
  }
}
</script>
复制代码

自定义 HTML

<template>
  <example-block title="自定义HTML">
    <button @click="showHtmlToast">自定义HTML文本提示</button>
  </example-block>
</template>
<script>
export default {
  methods: {
    showHtmlToast () {
      this.$toast('<strong style="font-size: 20px;">HTML文字提示~</strong>');
    }
  }
}
</script>
复制代码

Attributes

参数 说明 类型 可选值 默认值
msg msg文本内容 string
timeout msg显示时长 number 2000
callback 回调函数 function
icon 特殊icon string

6. Picker 选择器

包含常用的 4 种选择器,时间,日期,时间与日期,以及普通选择器

基本用法

1、时间类型选择器(切换 type 即可)

<template>
  <x-picker 
    title="选择日期"
    placeholder="请选择日期" 
    v-model="now_date" 
    type="date"
  ></x-picker>
</template>
<script>
export default {
  data() {
    return {
      now_date: null // new Date().getTime()/1000
    };
  }
};
</script>
复制代码

2、custom 普通选择器

<template>
  <x-picker 
    v-model="gender.value" 
    placeholder="请选择性别" 
    :default="gender.default" 
    title="选择性别" 
    type="custom"
  ></x-picker>
</template>
<script>
export default {
  data() {
    return {
     gender: {
        default: -1,
        value: [
          { name: "保密", value: 0 },
          { name: "男", value: 1 },
          { name: "女", value: 2 }
        ]
      }
    };
  }
};
</script>
复制代码

高阶用法

使用 timeStep 进行分钟的粒度选择

<template>
  <x-picker 
    title="选择日期"
    placeholder="请选择日期" 
    v-model="now_date" 
    type="date"
    :timeStep="20"
  ></x-picker>
</template>
<script>
export default {
  data() {
    return {
      now_date: null // new Date().getTime()/1000
    };
  }
};
</script>
复制代码

使用 startYear,endYear,startDate,endDate,startMinute,endMinute 进行时间的范围选择。(更多的可看实际情况进行搭配)

<template>
  <x-picker 
    title="选择日期"
    placeholder="请选择日期" 
    v-model="now_date" 
    type="date"
    startMinute="2" endMinute="30"
  ></x-picker>
</template>
<script>
export default {
  data() {
    return {
      now_date: null // new Date().getTime()/1000
    };
  }
};
</script>
复制代码

Attributes

参数 说明 类型 可选值 默认值
default picker默认选中的值 string/number
type picker类型 string date/time/datetime/custom datetime
title 选择器弹窗标题 string
placeholder placeholder string 请选择时间
timeStep 时间选择粒度(有分钟的选择器) number 1
startYear 起始年份 number/string 今年
endYear 结束年份 number/string 10年的范围
startDate 起始日期 string
endDate 结束日期 string
startHour 起始时间 number/string 0
endHour 结束时间 number/string 23
startMinute 起始分钟 number/string 0
endMinute 结束分钟 number/string 59
yearFormat “年“的格式化 string {value}年
monthFormat “月“的格式化 string {value}月
dayFormat “日“的格式化 string {value}日
hourFormat “时“的格式化 string {value}时
minuteFormat “分“的格式化 string {value}分

7. Select 选择器

当选项过多时,使用下拉菜单展示并选择内容。

基础用法

只有一个select

<template>
  <div>
    <x-select
    title="LIST ONE"
    defaultValue="0"
    :selectData="selectData"
    :alwaysShowTitle="false"
    @search="searchFn"
    ></x-select>
  </div>
</template>
<script>
export default {
  data() {
    return {
      selectData: [
        { id: 1, name: "LIST ONE 1" },
        { id: 2, name: "LIST ONE 2" },
        { id: 3, name: "LIST ONE 3" },
        { id: 4, name: "LIST ONE 4" },
        { id: 5, name: "LIST ONE 5" }
      ],
    };
  },
  methods: {
    searchFn(index, id) {
      console.log(index, id);
    }
  }
};
</script>
复制代码

两个及多个(需设置width属性)

<template>
  <div>
    <!-- first -->
    <v-select
    title="LIST ONE"
    width="50%"
    defaultValue="0"
    @search="searchFn"
    :selectData="selectData"
    :alwaysShowTitle="false"
    ></v-select>
    <!-- second -->
    <v-select
    title="LIST TWO"
    width="50%"
    ellipsisWidth="65px"
    defaultValue="1"
    @search="searchFn1"
    :selectData="selectData1"
    ></v-select>
  </div>
</template>
<script>
export default {
  data() {
    return {
      selectData: [
        { id: 1, name: "LIST ONE 1" },
        { id: 2, name: "LIST ONE 2" },
        { id: 3, name: "LIST ONE 3" },
        { id: 4, name: "LIST ONE 4" },
        { id: 5, name: "LIST ONE 5" }
      ],
      selectData1: [
        { id: 1, name: "LIST TWO 1" },
        { id: 2, name: "LIST TWO 2" },
        { id: 3, name: "LIST TWO 3" },
        { id: 4, name: "LIST TWO 4" },
        { id: 5, name: "LIST TWO 5" }
      ]
    };
  },
  methods: {
    searchFn(index, id) {
      console.log(index, id);
    },
    searchFn1(index, id) {
      console.log(index, id);
    }
  }
};
</script>
复制代码

Attributes

参数 说明 类型 可选值 默认值
selectData 下拉数据 array []
title 默认显示的标题 string
alwaysShowTitle 是否一直显示默认标题 boolean false
defaultValue 默认选中的值 number/string 0
width select组件的宽度 string 100%
ellipsisWidth select文字超过多出省略号的宽度 string 120px

Events

事件名称 说明 回调参数
search select 选择时的回调函数 参数1:索引,参数2:所中项的id值

8. switch

表示两种相互对立的状态间的切换,多用于触发「开/关」。

基本用法

注:如果未使用v-model指令进行值的双向绑定,则switch会显示value值对应的位置,但不能进行on-off操作

<template>
  <ul class='v-list'>
    <li><label>默认switch,值:{{val1}}</label><v-switch v-model="val1"></v-switch></li>
    <li><label>设置宽高,默认选中,值:{{val2}}</label><v-switch @change="handleChange" v-model="val2" width="50" height="30"></v-switch></li>
    <li><label>禁止点击,值:{{val3}}</label><v-switch :disabled="true"></v-switch></li>
    <li><label>禁止点击,默认选中,值:{{val4}}</label><v-switch :disabled="true" v-model="val4"></v-switch></li>
  </ul>
</template>
<script>
export default {
  data () {
    return {
      val1: false,
      val2: true,
      val3: false,
      val4: true
    }
  },
  methods: {
    handleChange (val, oldVal) {
      console.log(val, oldVal);
    }
  }
}
</script>
复制代码

Attributes

参数 说明 类型 可选值 默认值
width switch的宽度(像素) number/string 60
height switch的高度(像素) number/string
disabled 是否禁用 boolean false
value switch初始化选择状态 boolean/number/string 0
activeClass switch 打开时的class string avtive
inactiveClass switch 关闭时的class string inactive

Events

事件名称 说明 回调参数
change switch 状态发生变化时的回调函数 新状态的值

以上组件便是目前vui所有的组件了,后期会不断的进行维护并进行新组件的开发。

vui github传送门:github.com/Brickies/vu…

vui npm传送门:www.npmjs.com/package/x-v…

vui 文档官网传送门:brickies.github.io/vui

如果小伙伴们喜欢我的vui,欢迎 star

如果有什么问题欢迎小伙伴们随时提 Issue

如果有好的组件欢迎小伙伴们随时提PR,我会不定期进行merge

后期展望

组件库基本组件完成的差不多,我会做一个该项目搭建以及组件开发的分享,敬请期待~~~

个人准备重新捡回自己的公众号了,之后每周保证一篇高质量好文,感兴趣的小伙伴可以关注一波。