轮子嘛~总得造上一造~javascript
It's a A personal Vue UI component library .css
进入 PC 端直接是文档界面,想查看 demo 效果直接将浏览器调成手机模式便可,若是喜欢,还请不要吝惜你的 star 哦~~html
请扫描如下二维码vue
npm i x-vui -S
复制代码
# 全局安装 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,则无需再注册插件java
import Vue from 'vue';
import {
$Toast,
$Dialog
// ...
} from 'x-vui';
Vue.prototype.$toast = $Toast
Vue.prototype.$dialog = $Dialog
复制代码
目前这里默认为 swiper 轮播图,若是你有特殊须要,也可使用swipe和swipe-item组合出本身的swiperwebpack
<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>
复制代码
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
type | swiper类型 | string | swiper(正常)/thum(缩略) | swiper |
auto | 自动播放时长 | number | — | 5000 |
items | swiper展现的列表 | array | — | [] |
showIndicators | 是否展现swiper小圆点 | boolean | — | true |
styles | swiper样式控制 | object | — | {} |
resetTitle | 重置title内容 | string | — | — |
事件名称 | 说明 | 回调参数 |
---|---|---|
change | swiper滑动回调 | 当前swiper item索引 |
常常用来作手机端的分页功能,下拉刷新,上拉加载git
<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>
复制代码
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
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 | — | — |
事件名称 | 说明 | 回调参数 |
---|---|---|
onRefresh | 下拉回调 | 里面有个done callback用于结束loading效果 |
onInfinite | 上拉回调 | 里面有个done callback用于结束loading效果 |
经常使用于手机端搜索关键字,有时候还会进行高亮匹配github
一、只有搜索框web
<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>
复制代码
二、搭配 SearchList 搜索结果列表vue-cli
<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>
复制代码
三、定制化结果列表,关键字高亮匹配
<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>
复制代码
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
async | 是否进行节流 | boolean | — | true |
timeout | 搜索节流时长 | number | — | 100 |
styles | search样式 | object | — | — |
placeholder | placeholder | string | — | '搜索' |
autofocus | 是否自动聚焦(iOS端autofocus无效) | boolean | — | — |
clear | 进行搜索是否清空search框内容 | boolean | — | false |
事件名称 | 说明 | 回调参数 |
---|---|---|
search | search搜索回调 | 搜索文本 |
enter | enter时搜索回调 | 搜索文本 |
close | 点击搜索关闭按钮回调 | '' |
<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>
复制代码
<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>
复制代码
<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>
复制代码
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
show | modal是否显示 | boolean | — | — |
title | modal标题 | string | — | — |
content | modal内容 | string | — | — |
onOk | 肯定按钮回调 | function | — | — |
onCancel | 取消按钮回调 | function | — | — |
okText | 肯定按钮内容 | string | — | — |
cancelText | 取消按钮内容 | string | — | — |
showCloseIcon | 是否显示关闭icon | boolean | — | true |
<template>
<example-block title="基础用法">
<button @click="showSimpleToast">普通文字提示</button>
</example-block>
</template>
<script> export default { methods: { showSimpleToast () { this.$toast({msg: '我是文字提示~'}); } } } </script>
复制代码
<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>
复制代码
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
msg | msg文本内容 | string | — | — |
timeout | msg显示时长 | number | — | 2000 |
callback | 回调函数 | function | — | — |
icon | 特殊icon | string | — | — |
包含经常使用的 4 种选择器,时间,日期,时间与日期,以及普通选择器
一、时间类型选择器(切换 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>
复制代码
二、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>
复制代码
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
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}分 |
当选项过多时,使用下拉菜单展现并选择内容。
只有一个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>
复制代码
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
selectData | 下拉数据 | array | — | [] |
title | 默认显示的标题 | string | — | — |
alwaysShowTitle | 是否一直显示默认标题 | boolean | — | false |
defaultValue | 默认选中的值 | number/string | — | 0 |
width | select组件的宽度 | string | — | 100% |
ellipsisWidth | select文字超过多出省略号的宽度 | string | — | 120px |
事件名称 | 说明 | 回调参数 |
---|---|---|
search | select 选择时的回调函数 | 参数1:索引,参数2:所中项的id值 |
表示两种相互对立的状态间的切换,多用于触发「开/关」。
注:若是未使用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>
复制代码
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
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 |
事件名称 | 说明 | 回调参数 |
---|---|---|
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
组件库基本组件完成的差很少,我会作一个该项目搭建以及组件开发的分享,敬请期待~~~
我的准备从新捡回本身的公众号了,以后每周保证一篇高质量好文,感兴趣的小伙伴能够关注一波。