一、项目介绍
vui : 一个私人的vue ui 组件库(移动端为主)
已有组件
二、安装下载
npm install x-vui -S
三、快速开始
3.1 构建项目(配合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
3.2 引入vui组件库
你可以引入整个 vui,或是根据需要仅引入部分组件。我们先介绍如何引入完整的 vui。
3.2.1 完整引入
在main.js中写入
import { VUICOMS } from 'x-vui' VUICOMS.map(component => { Vue.component(component.name, component) })
3.2.2 按需部分引入
在main.js中写入(假如我只需要Scroller和Select组件)
import { Scroller, Select // ... } from 'x-vui' Vue.component(Scroller.name, Scroller) Vue.component(Select.name, Select)
3.2.3 全局注册vui插件
import { $msg, $modal } from 'x-vui' Vue.prototype.$dialog = { msg: $msg, modal: $modal }
四、组件用法
4.1 swiper
可以自己调配自己想要的swiper,不一定得是轮播图
组件props
props: { // 'swiper' => 正常swiper 'thum' => 缩略swiper type: String, // 自动播放时长,默认3000ms auto: Number, // 轮播展示的列表 items: Array, // 是否展示轮播小圆点 showIndicators: Boolean, // 轮播图样式控制 styles: Object, // 重置title内容 resetTitle: String },
组件用法
<template> <div class="swiper-page"> <p>正常swiper</p> <x-swiper type='swiper' :items='items' :styles="{height: '180px'}"></x-swiper> <p>缩略swiper</p> <x-swiper type='swiper' :items='items' :type="'thum'" :styles="{height: '208px'}"></x-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') ], } } } </script> <style lang="stylus" scoped> .swiper-page { height auto } </style>
4.2 scroller(下拉刷新上拉加载)
组件props
// 常用 props,更多的属性可以转到我github的项目vui进行查看 props: { // 下拉回调 onRefresh: Function, // 上拉回调 onInfinite: Function, // 是否展示上拉加载 isLoadMore: { type: Boolean, default: true }, // 下拉文本内容 refreshText: { type: String, default: '下拉刷新' }, // 无数据文本 noDataText: { type: String, default: '没有更多数据啦~' } },
组件用法
<style scoped> .scroller-page { height: 330px } ul { padding: 20px 0 } li { width: 100%; height: 35px; line-height: 35px; border-bottom: 1px solid #eee; text-align: center; } </style> <template> <div class="scroller-page"> <x-scroller :on-refresh="refresh" :on-infinite="infinite" :noDataText="noDataText" > <!-- content is here --> <ul> <li>数据1</li> <li>数据2</li> <li>数据3</li> <li>数据4</li> <li>数据5</li> <li>数据6</li> </ul> </x-scroller> </div> </template> <script> export default { data () { return { noDataText: '没有更多数据啦~' } }, methods: { refresh (done) { setTimeout(done, 1000) this.noDataText = '' console.log('refresh'); }, infinite (done) { setTimeout(done, 1000, true) this.noDataText = '没有更多数据啦~' console.log('infinite'); } } } </script>
4.3 search
组件props
props: { // 搜索节流时长 timeout: { type: Number, default: 100 }, // 是否进行节流 async: { type: Boolean, default: true }, // search样式 styles: Object, placeholder: { type: String, default: '搜索' }, // 是否自动聚焦 autofocus: Boolean, // iOS移动端autofocus无效 // 进行搜索是否清空search框内容 clear: { type: Boolean, default: false }, },
组件用法
1、只有搜索框
<style lang="stylus"> .search-page { padding: 0 10px; margin-top: 10px; } </style> <template> <div> <x-search placeholder="请输入搜索关键字" @search="searchFn" @enter="searchEnter" @close="closeFn" ></x-search> </div> </template> <script> export default { methods: { searchFn (query) { console.log('search', query) }, searchEnter (query) { console.log('enter', query) }, closeFn (query) { console.log('close', query) } } } </script>
2、拥有默认的搜索结果列表
<style lang="stylus"> .search-page { padding: 0 10px; margin-top: 10px; } </style> <template> <div class="search-page" v-title data-title="search"> <x-search placeholder="请输入搜索关键字" :autofocus="true" :async="false" @search="searchFn" @enter="searchEnter" @close="closeFn" > <x-search-list :result="filterResult" @listSearch="listSearch" v-show="visible"></x-search-list> </x-search> </div> </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; console.log('search', query) }, searchEnter (query) { this.keyword = query; console.log('enter', query) }, closeFn (query) { this.keyword = query; console.log('close', query) }, listSearch (index) { this.visible = false; console.log(index, this.defaultResult[index]) } }, computed: { filterResult() { return this.defaultResult.filter(item => new RegExp(this.keyword, 'i').test(item)); } } } </script>
3、定制化结果列表,关键字高亮匹配
<style lang="stylus"> .search-page { padding: 0 10px; margin-top: 10px; .search-result { position: relative; overflow: hidden; .l { width: 100%; margin-bottom: 5px; } .r { position: absolute; right: 0; top: 50%; margin-top: -10px; line-height: 20px; } .price { color: #ff6f5c; } .gray { font-size: 12px; } } } </style> <template> <div class="search-page" v-title data-title="search"> <x-search placeholder="请输入搜索关键字" :autofocus="true" :async="false" @search="searchFn" @enter="searchEnter" @close="closeFn" > <x-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> </x-search-list> </x-search> </div> </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; console.log('search', query) }, searchEnter (query) { this.keyword = query; console.log('enter', query) }, closeFn (query) { this.keyword = query; console.log('close', query) }, 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>
4.4 dialog
4.4.1 msg
/** * props { * msg: String, // 消息 * timeout: { * type: Number, * default: 2000 * }, // message消失延时时长 * callback: Function, // 回调 * icon: String, // 信息开头是否有特殊icon * } */ this.$dialog.msg({msg: 'hello message components ~'})
4.4.2 modal
/** * * show: Boolean, * title: String, * onOk: Function, * content: String, * onCancel: Function, * cancelText: String, * okText: String, * showCloseIcon: { * type: Boolean, * default: true * } */ this.$dialog.modal({ title: 'Demo Modal', cancelText: '取消', okText: '确定', content: '测试,测试,测试,测试,测试,测试,测试,测试,测试', onOk () { console.log('click ok btn to do someting'); }, onCancel () { console.log('click cancel btn to do someting'); } })
注册全局modal组件, 试用自己特制的modal组件
<style lang="stylus"> .dialog-page { .dialog-btn { width 100% position absolute top 50% left 0 transform translateY(-50%) > p { width 80% height 50px line-height 50px margin 40px auto 0 border 1px solid #CCC border-radius 10px font-size 16px font-weight bold letter-spacing 2px text-align center &:first-child { margin-top 0 } } } .modal-text { text-align: center; } } </style> <template> <div class="dialog-page"> <div class="dialog-btn"> <p @click="message">message dialog</p> <p @click="open">modal dialog</p> </div> <x-modal title="Demo Modal" cancelText="取消" :onCancel="close" :show="selectModel" okText="确认" :onOk="close"> <p class="modal-text">modal components test is awesome!!!</p> </x-modal> </div> </template> <script> export default { data () { return { selectModel: false } }, methods: { message () { return this.$dialog.msg({msg: 'this is a message dialog'}) }, open () { this.selectModel = true }, close () { this.selectModel = false } } } </script>
4.5 table
配合scroller进行展示(注:目前table较为简单,后期将进行完善,使得其可以应对不同场景)
<template> <div class="table" v-title data-title="table"> <x-scroller :on-refresh="refresh" :on-infinite="infinite" :noDataText="noDataText" class="table-content" > <x-table :tableData="items"> <x-table-column prop="list_1" label="LIST ONE"></x-table-column> <x-table-column prop="list_2" label="LIST TWO"></x-table-column> <x-table-column prop="list_3" label="LIST THREE"></x-table-column> <x-table-column prop="list_4" label="LIST FOUR"></x-table-column> </x-table> </x-scroller> </div> </template> <script> export default { data () { return { items: [ { list_1: '2017.12.09', list_2: '路人1', list_3: '爱过', list_4: '有' }, { list_1: '2017.12.10', list_2: '路人2', list_3: '爱过', list_4: '有' }, { list_1: '2017.12.11', list_2: '路人3', list_3: '爱过', list_4: '没有' }, { list_1: '2017.12.12', list_2: '路人4', list_3: '爱过', list_4: '没有' } ], noDataText: '没有更多数据啦~' } }, methods: { refresh (done) { setTimeout(done, 1000) this.noDataText = '' console.log('refresh'); }, infinite (done) { setTimeout(done, 1000, true) this.noDataText = '没有更多数据啦~' console.log('infinite'); } } } </script>
4.6 picker
组件props
/** * type = 'date' 日期选择器 * type = 'time' 时间选择器 * type = 'datetime' 日期时间选择器 * type = 'custom' 普通选择器 **/ props: { // 时间选择粒度,仅限有时间的选择器,默认为1分钟的粒度 timeStep: Number, // 选择器弹窗标题 title: String, // 起始年份 默认为今年 startYear: [Number, String], // 结束年份 默认起始开始算10年的范围 endYear: [Number, String], // 起始日期 类似 '2017-12-10' startDate: String, // 结束日期 验证同起始日期 endDate: String // 起始时间 0-23 startHour: [Number, String], // 结束时间 1-23 endHour: [Number, String], // 起始分钟 0-59 startMinute: [Number, String], // 结束分钟 1-59 endMinute: [Number, String] }
组件用法
<style lang="stylus"> .picker-page { .x-list { padding: 0 0.32rem; background: #fff; color: #333; font-size: 14px; > li { min-height: 60px; padding-top: 21px; border-bottom: 1px solid #f2f2f2; overflow: hidden; > label { float: left; } > div { float: right; } .x-list-arrow { min-width: 100px; margin-right: 10px; position: relative; > div { float: right; text-align: right; margin-right: 10px; } &:after { content: ''; position: absolute; top: 4px; right: -5px; width: 10px; height: 10px; border-top: 1px solid #ccc; border-right: 1px solid #ccc; transform: rotate(45deg); -webkit-transform: rotate(45deg); } } } } } </style> <template> <div class="picker-page" v-title data-title="picker"> <ul class='x-list'> <li> <label>日期选择</label> <div class="x-list-arrow"> <x-picker title="选择日期" startYear="2016" startDate="2015-01-01" endDate="2019-12-01" placeholder="请选择日期" v-model="now_date" type="date"></x-picker> </div> </li> <li> <label>时间选择</label> <div class="x-list-arrow"> <x-picker title="选择时间" placeholder="请选择时间" startMinute="2" endMinute="30" v-model="now_time" type="time"></x-picker> </div> </li> <li> <label>日期时间选择</label> <div class="x-list-arrow"> <x-picker title="选择日期时间" placeholder="请选择日期时间" v-model="now_datetime" :timeStep="20" type="datetime"></x-picker> </div> </li> <li> <label>性别选择</label> <div class="x-list-arrow"> <x-picker v-model="gender.value" placeholder="请选择性别" :default="gender.default" title="选择性别" type="custom"></x-picker> </div> </li> </ul> </div> </template> <script> export default { data() { return { gender: { default: -1, value: [ { name: "保密", value: 0 }, { name: "男", value: 1 }, { name: "女", value: 2 } ] }, now_date: null, now_time: null, now_datetime: null // new Date().getTime()/1000 }; } }; </script>
4.7 select
组件props
props: { // 数据 selectData: Array, // 默认显示的标题 title: String, // 是否一直显示默认标题 alwaysShowTitle: Boolean, // 默认选中的值 defaultValue: [Number, String], // select组件的宽度,默认继承父元素100%的width width: { type: String, default: '100%' }, // select文字超过多出省略号的宽度 ellipsisWidth: { type: String, default: '120px' } }
组件用法
<template> <div class="select-page" v-title data-title="select"> <x-select @search="searchFn" :selectData="selectData" title="LIST ONE" :alwaysShowTitle="false" width="50%" defaultValue="0" ></x-select> <x-select @search="searchFn1" :selectData="selectData1" title="LIST TWO" width="50%" ellipsisWidth="65px" defaultValue="1" ></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" } ], 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>
4.8 dropdown
这个下拉菜单偏PC端的这里就不多做介绍了
<template> <div class="test"> <x-dropdown trigger="click" @command="commandHandle" :hide-on-click="true"> <span class="drop-down_link">下拉菜单</span> <x-dropdown-menu> <x-dropdown-list command="a">下拉列表1</x-dropdown-list> <x-dropdown-list command="b">下拉列表2</x-dropdown-list> <x-dropdown-list command="c"><h4>下拉列表3</h4></x-dropdown-list> </x-dropdown-menu> </x-dropdown> </div> </template> <script> export default { name: 'Dropdown', methods: { commandHandle (command, instance) { console.log(command, instance); } } } </script>
以上组件便是目前vui所有的组件了,后期会不断的进行维护并进行新组件的开发。
vui github传送门:https://github.com/xuqiang521/vui
vui npm传送门:https://www.npmjs.com/package/x-vui
如果小伙伴们喜欢我的vui,欢迎star。
如果有什么问题欢迎小伙伴们随时提issue
如果有好的组件欢迎小伙伴们随时提pr,我会不定期进行merge