[聚合文章] 合格前端系列第八弹-造一个属于自己的ui库

JavaScript 2017-12-10 33 阅读
cd my-vui-projectnpm install && npm install x-vui# 项目启动 默认端口localhost:8080npm 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);        }
                

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。