輪子嘛~總得造上一造~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
組件庫基本組件完成的差很少,我會作一個該項目搭建以及組件開發的分享,敬請期待~~~
我的準備從新撿回本身的公衆號了,以後每週保證一篇高質量好文,感興趣的小夥伴能夠關注一波。