Merge pull request #4352 from icarusion/Drawer-Component

Drawer component
This commit is contained in:
Aresn 2018-08-24 15:02:31 +08:00 committed by GitHub
commit 8249a85701
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 552 additions and 3 deletions

File diff suppressed because one or more lines are too long

View file

@ -67,6 +67,7 @@ nav {
<li><router-link to="/divider">Divider</router-link></li> <li><router-link to="/divider">Divider</router-link></li>
<li><router-link to="/time">Time</router-link></li> <li><router-link to="/time">Time</router-link></li>
<li><router-link to="/cell">Cell</router-link></li> <li><router-link to="/cell">Cell</router-link></li>
<li><router-link to="/drawer">Drawer</router-link></li>
</ul> </ul>
</nav> </nav>
<router-view></router-view> <router-view></router-view>

View file

@ -225,6 +225,10 @@ const router = new VueRouter({
{ {
path: '/cell', path: '/cell',
component: (resolve) => require(['./routers/cell.vue'], resolve) component: (resolve) => require(['./routers/cell.vue'], resolve)
},
{
path: '/drawer',
component: (resolve) => require(['./routers/drawer.vue'], resolve)
} }
] ]
}); });

219
examples/routers/drawer.vue Normal file
View file

@ -0,0 +1,219 @@
<template>
<div>
<Button @click="visible = true">show1</Button>
<Button @click="visible2 = true">show2</Button>
<Button @click="visible3 = true">show3</Button>
<div style="width: 500px;height:500px;background: green;position: relative;">
</div>
<Drawer v-model="visible" width="70" title="抽屉标题" :styles="styles" @on-close="handleClose">
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<Button @click="visible2 = true">show2</Button>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
</Drawer>
<Drawer v-model="visible2" title="抽屉标题" placement="right">
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容22</p>
</Drawer>
<Drawer v-model="visible3" placement="left">
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容</p>
<p>一些内容22</p>
</Drawer>
</div>
</template>
<script>
export default {
data () {
return {
visible: false,
visible2: false,
visible3: false,
styles: {
height: 'calc(100% - 55px)',
paddingBottom: '53px',
},
ms: {
backgroundColor: 'rgba(255,0,255,0.5)'
}
};
},
methods: {
handleClose () {
this.$Message.info('关闭了');
}
}
};
</script>
<style>
body{
height: 2000px;
}
</style>

2
package-lock.json generated
View file

@ -1,6 +1,6 @@
{ {
"name": "iview", "name": "iview",
"version": "2.14.1", "version": "3.0.1",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {

View file

@ -0,0 +1,223 @@
<template>
<div v-transfer-dom :data-transfer="transfer">
<transition name="fade">
<div :class="maskClasses" :style="maskStyle" v-show="visible" v-if="mask" @click="handleMask"></div>
</transition>
<div :class="wrapClasses" @click="handleWrapClick">
<transition :name="'move-' + placement">
<div :class="classes" :style="mainStyles" v-show="visible">
<div :class="contentClasses" ref="content">
<a class="ivu-drawer-close" v-if="closable" @click="close">
<slot name="close">
<Icon type="ios-close"></Icon>
</slot>
</a>
<div :class="[prefixCls + '-header']" v-if="showHead"><slot name="header"><div :class="[prefixCls + '-header-inner']">{{ title }}</div></slot></div>
<div :class="[prefixCls + '-body']" :style="styles"><slot></slot></div>
</div>
</div>
</transition>
</div>
</div>
</template>
<script>
import Icon from '../icon';
import { oneOf } from '../../utils/assist';
import TransferDom from '../../directives/transfer-dom';
import Emitter from '../../mixins/emitter';
import ScrollbarMixins from '../modal/mixins-scrollbar';
const prefixCls = 'ivu-drawer';
export default {
name: 'Drawer',
mixins: [ Emitter, ScrollbarMixins ],
components: { Icon },
directives: { TransferDom },
props: {
value: {
type: Boolean,
default: false
},
title: {
type: String
},
width: {
type: [Number, String],
default: 256
},
closable: {
type: Boolean,
default: true
},
maskClosable: {
type: Boolean,
default: true
},
mask: {
type: Boolean,
default: true
},
maskStyle: {
type: Object
},
styles: {
type: Object
},
scrollable: {
type: Boolean,
default: false
},
placement: {
validator (value) {
return oneOf(value, ['left', 'right']);
},
default: 'right'
},
zIndex: {
type: Number,
default: 1000
},
transfer: {
type: Boolean,
default () {
return !this.$IVIEW || this.$IVIEW.transfer === '' ? true : this.$IVIEW.transfer;
}
},
className: {
type: String
},
inner: {
type: Boolean,
default: false
}
},
data () {
return {
prefixCls: prefixCls,
visible: this.value,
wrapShow: false,
showHead: true,
};
},
computed: {
wrapClasses () {
return [
`${prefixCls}-wrap`,
{
[`${prefixCls}-hidden`]: !this.wrapShow,
[`${this.className}`]: !!this.className,
[`${prefixCls}-no-mask`]: !this.mask,
[`${prefixCls}-wrap-inner`]: this.inner
}
];
},
mainStyles () {
let style = {};
const width = parseInt(this.width);
const styleWidth = {
width: width <= 100 ? `${width}%` : `${width}px`
};
Object.assign(style, styleWidth);
return style;
},
contentClasses () {
return [
`${prefixCls}-content`,
{
[`${prefixCls}-content-no-mask`]: !this.mask
}
];
},
classes () {
return [
`${prefixCls}`,
`${prefixCls}-${this.placement}`,
{
[`${prefixCls}-no-header`]: !this.showHead,
[`${prefixCls}-inner`]: this.inner
}
];
},
maskClasses () {
return [
`${prefixCls}-mask`,
{
[`${prefixCls}-mask-inner`]: this.inner
}
];
}
},
methods: {
close () {
this.visible = false;
this.$emit('input', false);
this.$emit('on-close');
},
handleMask () {
if (this.maskClosable && this.mask) {
this.close();
}
},
handleWrapClick (event) {
// use indexOf,do not use === ,because ivu-modal-wrap can have other custom className
const className = event.target.getAttribute('class');
if (className && className.indexOf(`${prefixCls}-wrap`) > -1) this.handleMask();
},
},
mounted () {
if (this.visible) {
this.wrapShow = true;
}
let showHead = true;
if (this.$slots.header === undefined && !this.title) {
showHead = false;
}
this.showHead = showHead;
},
beforeDestroy () {
this.removeScrollEffect();
},
watch: {
value (val) {
this.visible = val;
},
visible (val) {
if (val === false) {
this.timer = setTimeout(() => {
this.wrapShow = false;
this.removeScrollEffect();
}, 300);
} else {
if (this.timer) clearTimeout(this.timer);
this.wrapShow = true;
if (!this.scrollable) {
this.addScrollEffect();
}
}
this.broadcast('Table', 'on-visible-change', val);
this.broadcast('Slider', 'on-visible-change', val); // #2852
this.$emit('on-visible-change', val);
},
scrollable (val) {
if (!val) {
this.addScrollEffect();
} else {
this.removeScrollEffect();
}
},
title (val) {
if (this.$slots.header === undefined) {
this.showHead = !!val;
}
}
}
};
</script>

View file

@ -0,0 +1,3 @@
import Drawer from './drawer.vue';
export default Drawer;

View file

@ -1,4 +1,4 @@
// used for Modal & $Spin // used for Modal & $Spin & Drawer
import { getScrollBarSize } from '../../utils/assist'; import { getScrollBarSize } from '../../utils/assist';
export default { export default {
methods: { methods: {

View file

@ -19,6 +19,7 @@ import ColorPicker from './components/color-picker';
import Content from './components/content'; import Content from './components/content';
import DatePicker from './components/date-picker'; import DatePicker from './components/date-picker';
import Divider from './components/divider'; import Divider from './components/divider';
import Drawer from './components/drawer';
import Dropdown from './components/dropdown'; import Dropdown from './components/dropdown';
import Footer from './components/footer'; import Footer from './components/footer';
import Form from './components/form'; import Form from './components/form';
@ -85,6 +86,7 @@ const components = {
Content: Content, Content: Content,
DatePicker, DatePicker,
Divider, Divider,
Drawer,
Dropdown, Dropdown,
DropdownItem: Dropdown.Item, DropdownItem: Dropdown.Item,
DropdownMenu: Dropdown.Menu, DropdownMenu: Dropdown.Menu,

View file

@ -0,0 +1,95 @@
@drawer-prefix-cls: ~"@{css-prefix}drawer";
.@{drawer-prefix-cls} {
width: auto;
height: 100%;
position: fixed;
top: 0;
&-inner{
position: absolute;
}
&-left{
left: 0;
}
&-right{
right: 0;
}
&-hidden {
display: none !important;
}
&-wrap {
position: fixed;
overflow: auto;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: @zindex-drawer;
-webkit-overflow-scrolling: touch;
outline: 0;
&-inner{
position: absolute;
}
}
&-wrap * {
box-sizing: border-box;
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
&-mask {
.mask;
&-inner{
position: absolute;
}
}
&-content {
width: 100%;
height: 100%;
position: absolute;
top: 0;
bottom: 0;
background-color: #fff;
border: 0;
background-clip: padding-box;
box-shadow: 0 4px 12px rgba(0,0,0,.15);
&-no-mask{
pointer-events: auto;
}
}
&-header {
.content-header;
}
&-close {
z-index: 1;
.content-close(1px, 31px);
}
&-body {
width: 100%;
height: calc(~'100% - 51px');
padding: 16px;
font-size: 12px;
line-height: 1.5;
word-wrap: break-word;
position: absolute;
overflow: auto;
}
&-no-header &-body{
height: 100%;
}
&-no-mask{
pointer-events: none;
}
}

View file

@ -49,3 +49,4 @@
@import "anchor"; @import "anchor";
@import "time"; @import "time";
@import "cell"; @import "cell";
@import "drawer";

View file

@ -166,6 +166,7 @@
@zindex-back-top : 10; @zindex-back-top : 10;
@zindex-select : 900; @zindex-select : 900;
@zindex-modal : 1000; @zindex-modal : 1000;
@zindex-drawer : 1000;
@zindex-message : 1010; @zindex-message : 1010;
@zindex-notification : 1010; @zindex-notification : 1010;
@zindex-tooltip : 1060; @zindex-tooltip : 1060;