start
最近遇到一个需求,给一个移动端项目加一点小功能。移动端 UI 组件库使用的是 cube-ui。但是基础的 cube-ui 不太满足我的需求…重点是记录一下我的思路,其次才是实现的代码。1. 需求
需要点击按钮弹出一个弹出框,然后再弹出框中可以输入内容,点击确定的时候,调用接口保存。
原生的 cube-ui 仅支持一个输入框,而且这个输入框类型不可控。
我接到的需求呢,是支持多个输入框,且输入框类型还不一样。
基础cube-ui的prompt弹出框效果如下图:
2. 寻找解决方案
cube-ui是支持插槽的,具体的代码中createElement这个函数结构有点类似于h函数。
通过这个插槽插入文字图片什么的还是可以的。
我如果通过这个函数,向对话框中,插入几个input框。第一有点麻烦。第二可操作性有点低。
基础cube-ui的弹出框-插槽 代码以及效果如下图:
3. 最终的解决方案
正当我思索的时候,我突发奇想,先看看它的对话框源码是怎么写的。
cube-ui的dialog源码
看了一眼他的源码之后,我有解决方案了。他的源码无非就是一个vue组件。我直接cv一套出来,自己加一些自己的额外定制化配置,这样不就可以符合我的需求了?
4.结果
自定义的 基于 cube-ui的一个对话框
<template><transition name="cube-dialog-fade"><cube-popupref="selfPopup"type="self-dialog":z-index="zIndex":mask="true":center="true"@mask-click="maskClick"@click.stop="say()"><div class="self-dialog-main cube-dialog-main" @click.stop="say()"><!-- <span v-show="showClose" class="cube-dialog-close"><i class="cubeic-close"></i></span> --><div :class="containerClass"><h2 v-if="title || $slots.title" class="cube-dialog-title"><slot name="title"><p class="cube-dialog-title-def">{{ title }}</p></slot></h2><div class="cube-dialog-content"><slot name="content"><div v-if="promptList && promptList.length > 0" class="cube-dialog-content-def"><div v-for="(item, index) in promptList" :key="index"><div>{{ item.label }}</div><div v-if="item.type === 'text' || item.type === 'number'"><cube-inputv-model="item.value":type="item.type":placeholder="item.placeholder"/></div><div v-if="item.type === 'select'"><cube-inputv-model="item.value":type="item.type":placeholder="item.placeholder":readonly="true"@focus="showPicker(item, index)"/></div></div></div></slot></div><div class="cube-dialog-btns" :class="{ 'border-right-1px': isConfirm || isPrompt }"><slot name="btns"><av-if="isConfirm || isPrompt":href="cancelBtn.href"class="cube-dialog-btn border-top-1px":class="{'cube-dialog-btn_highlight': cancelBtn.active,'cube-dialog-btn_disabled': cancelBtn.disabled}"@click="cancel">{{ cancelBtn.text }}</a><a:href="confirmBtn.href"class="cube-dialog-btn border-top-1px":class="{'cube-dialog-btn_highlight': confirmBtn.active,'cube-dialog-btn_disabled': confirmBtn.disabled}"@click="confirm">{{ confirmBtn.text }}</a></slot></div></div></div></cube-popup></transition></template><script>export default {props: {zIndex: {type: Number,default: 100},type: {require: true,type: String,default: 'prompt'},title: {type: String,default: ''},promptList: {type: Array,default() {return []}},cancelBtn: {type: Object,default() {return {href: 'javascript:;',active: false,disabled: false,text: '关闭'}}},confirmBtn: {type: Object,default() {return {href: 'javascript:;',active: true,disabled: false,text: '确认'}}}},data() {return {}},computed: {containerClass() {return `cube-dialog-${this.type}`},isPrompt() {return this.type === 'prompt'},isConfirm() {return this.type === 'confirm'}},methods: {show() {this.$refs.selfPopup.show()},hide() {this.$refs.selfPopup.hide()},maskClick(e) {this.maskClosable && this.cancel(e)},confirm(e) {if (this.confirmBtn.disabled) {return}this.$emit('EVENT_CONFIRM', e, this.promptValue)},cancel(e) {if (this.cancelBtn.disabled) {return}this.$refs.selfPopup.hide()this.$emit('EVENT_CANCEL', e)},close(e) {this.$refs.selfPopup.hide()this.$emit('EVENT_CLOSE', e)},showPicker(item, index) {this.picker = this.$createPicker({title: item.label,data: [item.column],onSelect: (value, i, text) => {this.promptList[index].value = text[0]this.promptList[index].key = value[0]}// onCancel: this.cancelHandle})this.picker.show()},say() {}}}</script><style>.self-dialog-main .cube-input {border: 0.071429rem solid #ebebeb !important;}.self-dialog-main .cube-input-field {padding: 0.714286rem !important;}</style>
主要差异
主要差异就是对cube-dialog-content
的内容进行了扩展,支持传入配置文件进行扩展。其次就是做了一下样式兼容以及点击事件的处理。
演示一下传入的 额外配置文件
[{type: 'number',value: '',require: true,label: '数量',placeholder: '数量',rules: {positiveInteger: true // 正整数}},{type: 'select',value: '',key: '',label: '原因',require: true,placeholder: '请选择原因',column: [{text: '破损', value: 'A' },{text: '丢失', value: 'B' },{text: '其他', value: 'C' }]},{type: 'text',value: '',label: '其他',placeholder: '请输入'}]