合格前端系列第八弹-造一个属于自己的 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

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

Events

事件名称说明回调参数
changeswiper滑动回调当前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
widthscroller宽度string100%
heightscroller高度string100%
isLoadMore是否展示上拉加载booleantrue
refreshText下拉文本内容string下拉刷新
noDataText无数据文本string没有更多数据啦~
refreshLayerColor下拉文本颜色string#AAA
loadingLayerColor上拉文本颜色string#AAA
animating是否有动画booleantrue
animationDuration动画间隔number250
bouncing是否有反弹效果stringtrue
cssClasscontent css classstring

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是否进行节流booleantrue
timeout搜索节流时长number100
stylessearch样式object
placeholderplaceholderstring'搜索'
autofocus是否自动聚焦(iOS端autofocus无效)boolean
clear进行搜索是否清空search框内容booleanfalse

Events

事件名称说明回调参数
searchsearch搜索回调搜索文本
enterenter时搜索回调搜索文本
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)

参数说明类型可选值默认值
showmodal是否显示boolean
titlemodal标题string
contentmodal内容string
onOk确定按钮回调function
onCancel取消按钮回调function
okText确定按钮内容string
cancelText取消按钮内容string
showCloseIcon是否显示关闭iconbooleantrue

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

参数说明类型可选值默认值
msgmsg文本内容string
timeoutmsg显示时长number2000
callback回调函数function
icon特殊iconstring

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

参数说明类型可选值默认值
defaultpicker默认选中的值string/number
typepicker类型stringdate/time/datetime/customdatetime
title选择器弹窗标题string
placeholderplaceholderstring请选择时间
timeStep时间选择粒度(有分钟的选择器)number1
startYear起始年份number/string今年
endYear结束年份number/string10年的范围
startDate起始日期string
endDate结束日期string
startHour起始时间number/string0
endHour结束时间number/string23
startMinute起始分钟number/string0
endMinute结束分钟number/string59
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是否一直显示默认标题booleanfalse
defaultValue默认选中的值number/string0
widthselect组件的宽度string100%
ellipsisWidthselect文字超过多出省略号的宽度string120px

Events

事件名称说明回调参数
searchselect 选择时的回调函数参数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

参数说明类型可选值默认值
widthswitch的宽度(像素)number/string60
heightswitch的高度(像素)number/string
disabled是否禁用booleanfalse
valueswitch初始化选择状态boolean/number/string0
activeClassswitch 打开时的classstringavtive
inactiveClassswitch 关闭时的classstringinactive

Events

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

以上组件便是目前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

后期展望

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值