diff --git a/CHANGELOG.md b/CHANGELOG.md index be30b421e..d22c37971 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,20 @@ ## 更新日志 -### 1.0.0-rc.6(待发布) +### 1.0.0-rc.7 *2016-XX-XX* +- Upload 新增 Data 属性支持额外数据的传输 +- DatePicker 修复 `$t` 报错 +- Popper 重构 vue-popper +- Pagination 修复输入后再点击切换,输入框的值不更新 +- Step: 修复自定义 icon 的样式 +- 修复 Tree 组件 checkbox 点击失效的问题 + +### 1.0.0-rc.6 + +*2016-10-11* + - 修复 Tabs 切换后 Tab-panel 被销毁的问题 - 修复 TimePicker 错误的隐藏面板 - 修复 Table Cell 的样式, #204 diff --git a/examples/docs/zh-cn/badge.md b/examples/docs/zh-cn/badge.md index c3371ca6b..0d1888d16 100644 --- a/examples/docs/zh-cn/badge.md +++ b/examples/docs/zh-cn/badge.md @@ -21,15 +21,20 @@ <el-button size="small">回复</el-button> </el-badge> -<el-dropdown text="点我查看" type="text" :icon-separate="false" trigger="click"> - <el-dropdown-item class="clearfix"> - 评论 - <el-badge class="mark" :value="12" /> - </el-dropdown-item> - <el-dropdown-item class="clearfix"> - 回复 - <el-badge class="mark" :value="3" /> - </el-dropdown-item> +<el-dropdown trigger="click"> + <span class="el-dropdown-link"> + 点我查看<i class="el-icon-caret-bottom el-icon-right"></i> + </span> + <el-dropdown-menu slot="dropdown"> + <el-dropdown-item class="clearfix"> + 评论 + <el-badge class="mark" :value="12" /> + </el-dropdown-item> + <el-dropdown-item class="clearfix"> + 回复 + <el-badge class="mark" :value="3" /> + </el-dropdown-item> + </el-dropdown-menu> </el-dropdown> ``` ::: diff --git a/examples/docs/zh-cn/date-picker.md b/examples/docs/zh-cn/date-picker.md index ad759d234..90d13e4f0 100644 --- a/examples/docs/zh-cn/date-picker.md +++ b/examples/docs/zh-cn/date-picker.md @@ -119,6 +119,7 @@ <span class="demonstration">带快捷选项</span> <el-date-picker v-model="value2" + align="right" type="date" placeholder="选择日期" :picker-options="pickerOptions1"> @@ -193,6 +194,7 @@ <span class="demonstration">年</span> <el-date-picker v-model="value5" + align="right" type="year" placeholder="选择年"> </el-date-picker> diff --git a/examples/docs/zh-cn/dropdown.md b/examples/docs/zh-cn/dropdown.md index 8a16b219d..1a193360f 100644 --- a/examples/docs/zh-cn/dropdown.md +++ b/examples/docs/zh-cn/dropdown.md @@ -152,7 +152,8 @@ ### Attributes | 参数 | 说明 | 类型 | 可选值 | 默认值 | |------------- |---------------- |---------------- |---------------------- |-------- | -| type | 菜单按钮类型,同 Button 组件 | string | — | — | +| type | 菜单按钮类型,同 Button 组件(只在`split-button`为 true 的情况下有效) | string | — | — | +| size | 菜单按钮尺寸,同 Button 组件(只在`split-button`为 true 的情况下有效) | string | hover, click | hover | | split-button | 下拉触发元素呈现为按钮组 | boolean | — | false | | menu-align | 菜单水平对齐方向 | string | start, end | end | | trigger | 触发下拉的行为 | string | hover, click | hover | diff --git a/examples/docs/zh-cn/form.md b/examples/docs/zh-cn/form.md index 3a0a043b7..592dd78d8 100644 --- a/examples/docs/zh-cn/form.md +++ b/examples/docs/zh-cn/form.md @@ -514,7 +514,7 @@ <el-option label="区域二" value="beijing"></el-option> </el-select> </el-form-item> - <el-form-item label="活动时间"> + <el-form-item label="活动时间" required> <el-col :span="11"> <el-form-item prop="date1"> <el-date-picker type="date" placeholder="选择日期" v-model="ruleForm.date1" style="width: 100%;"></el-date-picker> diff --git a/examples/docs/zh-cn/input.md b/examples/docs/zh-cn/input.md index 57d14e3a1..0f7ddcc31 100644 --- a/examples/docs/zh-cn/input.md +++ b/examples/docs/zh-cn/input.md @@ -627,7 +627,7 @@ | 参数 | 说明 | 类型 | 可选值 | 默认值 | |------------- |---------------- |---------------- |---------------------- |-------- | -| type | 同原生的 input 的 type 属性,另外提供 type="textarea" | string | — | — | +| type | 类型 | string | text/textarea | text | | value | 绑定值 | string, number | — | — | | maxlength | 最大输入长度 | number | — | — | | minlength | 最小输入长度 | number | — | — | diff --git a/examples/docs/zh-cn/slider.md b/examples/docs/zh-cn/slider.md index f083d8103..49d8b5d5d 100644 --- a/examples/docs/zh-cn/slider.md +++ b/examples/docs/zh-cn/slider.md @@ -16,22 +16,22 @@ .demo-box.demo-slider .source { padding: 0; } - + .demo-box.demo-slider .block { padding: 30px 24px; overflow: hidden; border-bottom: solid 1px #EFF2F6; &:last-child { - border-bottom: none; + border-bottom: none; } } - + .demo-box.demo-slider .demonstration { font-size: 14px; color: #8492a6; line-height: 44px; } - + .demo-box.demo-slider .demonstration + .el-slider { float: right; width: 70%; @@ -52,7 +52,7 @@ <template> <div class="block"> <span class="demonstration">默认</span> - <el-slider v-model="value1"></el-slider> + <el-slider v-model="value1"></el-slider> </div> <div class="block"> <span class="demonstration">自定义初始值</span> @@ -85,7 +85,7 @@ <el-slider v-model="value3" :step="10"> - </el-slider> + </el-slider> </div> <div class="block"> <span class="demonstration">显示间断点</span> @@ -121,7 +121,7 @@ <el-slider v-model="value5" show-input> - </el-slider> + </el-slider> </div> </template> diff --git a/package.json b/package.json index 9d5db9602..7f7e34b29 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "element-ui", - "version": "1.0.0-rc.5", + "version": "1.0.0-rc.6", "description": "A Component Library for Vue.js.", "main": "lib/element-ui.common.js", "files": [ @@ -89,10 +89,10 @@ "theaterjs": "^3.0.0", "uppercamelcase": "^1.1.0", "url-loader": "^0.5.7", - "vue": "^2.0.1", + "vue": "^2.0.2", "vue-loader": "^9.5.1", "vue-markdown-loader": "^0.5.1", - "vue-popup": "^0.2.6", + "vue-popup": "^0.2.8", "vue-router": "^2.0.0", "webpack": "^1.13.2", "webpack-dev-server": "^1.15.1", diff --git a/packages/autocomplete/src/autocomplete.vue b/packages/autocomplete/src/autocomplete.vue index 7c6eeafbf..eaa2ed877 100644 --- a/packages/autocomplete/src/autocomplete.vue +++ b/packages/autocomplete/src/autocomplete.vue @@ -5,8 +5,8 @@ :disabled="disabled" :placeholder="placeholder" :name='name' - @onchange="handleChange" - @onfocus="handleFocus" + @change="handleChange" + @focus="handleFocus" @keydown.up.native="highlight(highlightedIndex - 1)" @keydown.down.native="highlight(highlightedIndex + 1)" @keydown.enter.native="select(highlightedIndex)" diff --git a/packages/date-picker/src/css/date-picker.css b/packages/date-picker/src/css/date-picker.css index 49cf40449..29971e7c0 100644 --- a/packages/date-picker/src/css/date-picker.css +++ b/packages/date-picker/src/css/date-picker.css @@ -3,7 +3,19 @@ @component-namespace el { @b date-picker { - min-width: 300px; + min-width: 254px; + + &.has-sidebar.has-time { + min-width: 434px; + } + + &.has-sidebar { + min-width: 370px; + } + + &.has-time { + min-width: 324px; + } .el-picker-panel__content { min-width: 224px; diff --git a/packages/date-picker/src/css/date-range-picker.css b/packages/date-picker/src/css/date-range-picker.css index 3bfbe62d6..3df5d8781 100644 --- a/packages/date-picker/src/css/date-range-picker.css +++ b/packages/date-picker/src/css/date-range-picker.css @@ -2,6 +2,20 @@ @component-namespace el { @b date-range-picker { + min-width: 520px; + + &.has-sidebar.has-time { + min-width: 766px; + } + + &.has-sidebar { + min-width: 620px; + } + + &.has-time { + min-width: 660px; + } + table { table-layout: fixed; width: 100%; diff --git a/packages/date-picker/src/css/picker-panel.css b/packages/date-picker/src/css/picker-panel.css index 545a50793..99740e66b 100644 --- a/packages/date-picker/src/css/picker-panel.css +++ b/packages/date-picker/src/css/picker-panel.css @@ -63,6 +63,7 @@ cursor: pointer; background-color: transparent; outline: none; + font-size: 12px; &[disabled] { color: #cccccc; diff --git a/packages/date-picker/src/css/time-range-picker.css b/packages/date-picker/src/css/time-range-picker.css index 67eca4504..d22728581 100644 --- a/packages/date-picker/src/css/time-range-picker.css +++ b/packages/date-picker/src/css/time-range-picker.css @@ -2,7 +2,7 @@ @component-namespace el { @b time-range-picker { - width: 354px; + min-width: 354px; overflow: visible; @e content { diff --git a/packages/date-picker/src/panel/date-range.vue b/packages/date-picker/src/panel/date-range.vue index 3ec185b14..1f2862e35 100644 --- a/packages/date-picker/src/panel/date-range.vue +++ b/packages/date-picker/src/panel/date-range.vue @@ -1,8 +1,13 @@ <template> - <transition name="md-fade-bottom"> + <transition name="md-fade-bottom" @after-leave="$emit('dodestroy')"> <div v-show="visible" - class="el-picker-panel el-date-range-picker"> + :style="{ width: width + 'px' }" + class="el-picker-panel el-date-range-picker" + :class="{ + 'has-sidebar': $slots.sidebar || shortcuts, + 'has-time': showTime + }"> <div class="el-picker-panel__body-wrapper"> <slot name="sidebar" class="el-picker-panel__sidebar"></slot> <div class="el-picker-panel__sidebar" v-if="shortcuts"> @@ -31,6 +36,7 @@ @focus="leftTimePickerVisible = true" @change="handleTimeChange($event, 'min')"/> <time-picker + :picker-width="leftPickerWidth" ref="lefttimepicker" :date="minDate" @pick="handleLeftTimePick" @@ -41,6 +47,7 @@ <span class="el-icon-arrow-right"></span> <span class="el-date-range-picker__editors-wrap is-right"> <input + ref="leftInput" placeholder="结束日期" class="el-date-range-picker__editor" v-model="rightVisibleDate" @@ -51,6 +58,7 @@ class="el-date-range-picker__time-picker-wrap" v-clickoutside="closeRightTimePicker"> <input + ref="rightInput" placeholder="结束时间" class="el-date-range-picker__editor" v-model="rightVisibleTime" @@ -58,6 +66,7 @@ :readonly="!minDate" @change="handleTimeChange($event, 'max')" /> <time-picker + :picker-width="rightPickerWidth" ref="righttimepicker" :date="maxDate" @pick="handleRightTimePick" @@ -254,6 +263,8 @@ data() { return { + leftPickerWidth: 0, + rightPickerWidth: 0, date: new Date(), minDate: '', maxDate: '', @@ -269,11 +280,26 @@ visible: '', disabledDate: '', leftTimePickerVisible: false, - rightTimePickerVisible: false + rightTimePickerVisible: false, + width: 0 }; }, watch: { + showTime(val) { + if (!val) return; + this.$nextTick(_ => { + const leftInputElm = this.$refs.leftInput; + const rightInputElm = this.$refs.rightInput; + if (leftInputElm) { + this.leftPickerWidth = leftInputElm.getBoundingClientRect().width + 10; + } + if (rightInputElm) { + this.rightPickerWidth = rightInputElm.getBoundingClientRect().width + 10; + } + }); + }, + minDate() { this.$nextTick(() => { if (this.maxDate && this.maxDate < this.minDate) { @@ -302,7 +328,9 @@ }, methods: { - $t, + $t(...args) { + return $t.apply(this, args); + }, closeLeftTimePicker() { this.leftTimePickerVisible = false; diff --git a/packages/date-picker/src/panel/date.vue b/packages/date-picker/src/panel/date.vue index f68e0c576..5b676ec53 100644 --- a/packages/date-picker/src/panel/date.vue +++ b/packages/date-picker/src/panel/date.vue @@ -1,8 +1,15 @@ <template> - <transition name="md-fade-bottom"> + <transition name="md-fade-bottom" @after-leave="$emit('dodestroy')"> <div v-show="visible" - class="el-picker-panel el-date-picker"> + :style="{ + width: width + 'px' + }" + class="el-picker-panel el-date-picker" + :class="{ + 'has-sidebar': $slots.sidebar || shortcuts, + 'has-time': showTime + }"> <div class="el-picker-panel__body-wrapper"> <slot name="sidebar" class="el-picker-panel__sidebar"></slot> <div class="el-picker-panel__sidebar" v-if="shortcuts"> @@ -21,6 +28,7 @@ class="el-date-picker__editor"> <span style="position: relative" v-clickoutside="closeTimePicker"> <input + ref="input" @focus="timePickerVisible = true" v-model="visibleTime" :placehoder="$t('datepicker.selectTime')" @@ -29,6 +37,7 @@ <time-picker ref="timepicker" :date="date" + :picker-width="pickerWidth" @pick="handleTimePick" :visible="timePickerVisible"> </time-picker> @@ -115,6 +124,16 @@ export default { watch: { + showTime(val) { + if (!val) return; + this.$nextTick(_ => { + const inputElm = this.$refs.input; + if (inputElm) { + this.pickerWidth = inputElm.getBoundingClientRect().width + 10; + } + }); + }, + value(newVal) { if (this.selectionMode === 'day' && newVal instanceof Date) { this.date = newVal; @@ -328,6 +347,7 @@ data() { return { + pickerWidth: 0, date: new Date(), value: '', showTime: false, @@ -339,7 +359,8 @@ year: null, month: null, week: null, - timePickerVisible: false + timePickerVisible: false, + width: 0 }; }, diff --git a/packages/date-picker/src/panel/time-range.vue b/packages/date-picker/src/panel/time-range.vue index b63173f8f..c5cdd408d 100644 --- a/packages/date-picker/src/panel/time-range.vue +++ b/packages/date-picker/src/panel/time-range.vue @@ -1,7 +1,8 @@ <template> - <transition name="md-fade-bottom"> + <transition name="md-fade-bottom" @after-leave="$emit('dodestroy')"> <div v-show="visible" + :style="{ width: width + 'px' }" class="el-time-range-picker el-picker-panel"> <div class="el-time-range-picker__content"> <div class="el-time-range-picker__cell"> @@ -48,8 +49,9 @@ </transition> </template> -<script type="text/ecmascript-6"> +<script type="text/babel"> import { parseDate, limitRange } from '../util'; + import { $t } from '../util'; const MIN_TIME = parseDate('00:00:00', 'HH:mm:ss'); const MAX_TIME = parseDate('23:59:59', 'HH:mm:ss'); @@ -90,11 +92,16 @@ minMinutes: minTime.getMinutes(), minSeconds: minTime.getSeconds(), format: 'HH:mm:ss', - visible: false + visible: false, + width: 0 }; }, methods: { + $t(...args) { + return $t.apply(this, args); + }, + handleCancel() { this.$emit('pick'); }, diff --git a/packages/date-picker/src/panel/time-select.vue b/packages/date-picker/src/panel/time-select.vue index 1a5df8d30..402fd96dd 100644 --- a/packages/date-picker/src/panel/time-select.vue +++ b/packages/date-picker/src/panel/time-select.vue @@ -1,7 +1,8 @@ <template> - <transition name="md-fade-bottom"> + <transition name="md-fade-bottom" @after-leave="$emit('dodestroy')"> <div v-show="visible" + :style="{ width: width + 'px' }" class="el-picker-panel time-select"> <div class="el-picker-panel__content"> <div class="time-select-item" @@ -16,7 +17,7 @@ </transition> </template> -<script type="text/ecmascript-6"> +<script type="text/babel"> const parseTime = function(time) { const values = ('' || time).split(':'); if (values.length >= 2) { @@ -91,7 +92,8 @@ step: '00:30', value: '', visible: false, - minTime: '' + minTime: '', + width: 0 }; }, diff --git a/packages/date-picker/src/panel/time.vue b/packages/date-picker/src/panel/time.vue index fa15c319e..0561bf8ef 100644 --- a/packages/date-picker/src/panel/time.vue +++ b/packages/date-picker/src/panel/time.vue @@ -1,7 +1,8 @@ <template> - <transition name="md-fade-bottom"> + <transition name="md-fade-bottom" @after-leave="$emit('dodestroy')"> <div v-show="currentVisible" + :style="{width: width + 'px'}" class="el-time-panel"> <div class="el-time-panel__content"> <time-spinner @@ -31,6 +32,7 @@ <script type="text/babel"> import { limitRange } from '../util'; import Vue from 'vue'; + import { $t } from '../util'; export default { components: { @@ -38,12 +40,12 @@ }, props: { + pickerWidth: {}, date: { default() { return new Date(); } }, - visible: Boolean }, @@ -52,6 +54,10 @@ this.currentVisible = val; }, + pickerWidth(val) { + this.width = val; + }, + value(newVal) { let date; if (newVal instanceof Date) { @@ -80,7 +86,8 @@ seconds: 0, selectableRange: [], currentDate: this.$options.defaultValue || this.date, - currentVisible: this.visible + currentVisible: this.visible, + width: this.pickerWidth || 0 }; }, @@ -91,6 +98,10 @@ }, methods: { + $t(...args) { + return $t.apply(this, args); + }, + handleCancel() { this.$emit('pick', null); }, diff --git a/packages/date-picker/src/picker.vue b/packages/date-picker/src/picker.vue index 083dc9fee..3c9c8b698 100644 --- a/packages/date-picker/src/picker.vue +++ b/packages/date-picker/src/picker.vue @@ -11,7 +11,7 @@ <input class="el-date-editor__editor" :readonly="readonly" - :type="editorType" + type="text" :placeholder="placeholder" @focus="handleFocus" @blur="handleBlur" @@ -33,9 +33,20 @@ import Vue from 'vue'; import Clickoutside from 'main/utils/clickoutside'; import { merge, formatDate, parseDate, getWeekNumber } from './util'; -import Popper from 'main/utils/popper'; +import Popper from 'main/utils/vue-popper'; import emitter from 'main/mixins/emitter'; +const newPopper = { + props: { + appendToBody: Popper.props.appendToBody, + offset: Popper.props.offset, + boundariesPadding: Popper.props.boundariesPadding + }, + methods: Popper.methods, + data: Popper.data, + beforeDestroy: Popper.beforeDestroy +}; + const FUNCTION_KEYS = [13, 16, 17, 18, 19, 20, 27, 33, 34, 35, 36, 37, 38, 39, 40]; const RANGE_SEPARATOR = ' - '; const DEFAULT_FORMATS = { @@ -184,7 +195,7 @@ const PLACEMENT_MAP = { }; export default { - mixins: [emitter], + mixins: [emitter, newPopper], props: { format: String, @@ -274,13 +285,18 @@ export default { } this.$emit('input', value); } - }, - - editorType() { - return 'text'; } }, + created() { + // vue-popper + this.options = { + boundariesPadding: 0, + gpuAcceleration: false + }; + this.placement = PLACEMENT_MAP[this.align] || PLACEMENT_MAP.left; + }, + methods: { handleClose() { this.pickerVisible = false; @@ -386,16 +402,6 @@ export default { !this.pickerVisible ? this.showPicker() : this.hidePicker(); }, - destroyPopper() { - if (this.popper) { - this.resetTransformOrigin(this.popper); - setTimeout(() => { - this.popper && this.popper.destroy(); - this.popper = null; - }, 300); - } - }, - hidePicker() { if (this.picker) { this.picker.resetView && this.picker.resetView(); @@ -410,6 +416,8 @@ export default { this.picker = new Vue(merge({ el: document.createElement('div') }, this.panel)); + this.popperElm = this.picker.$el; + this.picker.width = this.$refs.reference.getBoundingClientRect().width; this.picker.showTime = this.type === 'datetime' || this.type === 'datetimerange'; this.picker.selectionMode = this.selectionMode; if (this.format) { @@ -445,6 +453,7 @@ export default { this.pickerVisible = this.picker.visible = true; this.picker.resetView && this.picker.resetView(); + this.picker.$on('dodestroy', this.doDestroy); this.picker.$on('pick', (date, visible = false) => { this.$emit('input', date); @@ -464,20 +473,7 @@ export default { this.pickerVisible = this.picker.visible = true; } - this.$nextTick(() => { - if (this.popper) return; - - this.popper = new Popper(this.$refs.reference, this.picker.$el, { - gpuAcceleration: false, - placement: PLACEMENT_MAP[this.align] || PLACEMENT_MAP.left, - boundariesPadding: 0, - forceAbsolute: true - }); - - this.popper.onCreate(popper => { - this.resetTransformOrigin(popper); - }); - }); + this.updatePopper(); if (this.value instanceof Date) { this.picker.date = new Date(this.value.getTime()); @@ -492,18 +488,7 @@ export default { } this.picker.ajustScrollTop && this.picker.ajustScrollTop(); }); - }, - - resetTransformOrigin(popper) { - let placementMap = { top: 'bottom', bottom: 'top' }; - let placement = popper._popper.getAttribute('x-placement').split('-')[0]; - let origin = placementMap[placement]; - popper._popper.style.transformOrigin = `center ${ origin }`; } - }, - - beforeDestroy() { - this.popper && this.popper.destroy(); } }; </script> diff --git a/packages/dropdown/src/dropdown-menu.vue b/packages/dropdown/src/dropdown-menu.vue index 329ac8b17..76d7dc524 100644 --- a/packages/dropdown/src/dropdown-menu.vue +++ b/packages/dropdown/src/dropdown-menu.vue @@ -1,39 +1,35 @@ <template> - <ul class="el-dropdown__menu"> + <transition name="md-fade-bottom" @after-leave="doDestroy"> + <ul class="el-dropdown__menu" v-show="showPopper"> <slot></slot> </ul> + </transition> </template> <script> - import Popper from 'main/utils/popper'; + import Popper from 'main/utils/vue-popper'; export default { name: 'ElDropdownMenu', - props: { - visible: Boolean - }, - data() { - return { - popper: null - }; - }, - computed: { - menuAlign() { - return this.$parent.menuAlign; - } - }, - mounted() { - document.body.appendChild(this.$el); + componentName: 'ElDropdownMenu', - this.$nextTick(() => { - this.popper = new Popper(this.$parent.$el, this.$el, { gpuAcceleration: false, placement: `bottom-${this.menuAlign}` }); + mixins: [Popper], + + created() { + this.$on('visible', val => { + this.showPopper = val; }); }, - destroyed() { - setTimeout(() => { - this.popper.destroy(); - }, 300); + mounted() { + this.$parent.popperElm = this.popperElm = this.$el; + this.referenceElm = this.$parent.$el; + }, + + computed: { + placement() { + return `bottom-${this.$parent.menuAlign}`; + } } }; </script> diff --git a/packages/dropdown/src/dropdown.vue b/packages/dropdown/src/dropdown.vue index 2124d3391..f0c9ed68e 100644 --- a/packages/dropdown/src/dropdown.vue +++ b/packages/dropdown/src/dropdown.vue @@ -1,9 +1,12 @@ <script> import Clickoutside from 'main/utils/clickoutside'; + import emitter from 'main/mixins/emitter'; export default { name: 'ElDropdown', + mixins: [emitter], + directives: { Clickoutside }, props: { @@ -15,9 +18,8 @@ type: String, default: 'end' }, - type: { - type: String - }, + type: String, + size: String, splitButton: Boolean }, @@ -32,6 +34,12 @@ this.initEvent(); }, + watch: { + visible(val) { + this.broadcast('ElDropdownMenu', 'visible', val); + } + }, + methods: { show() { clearTimeout(this.timeout); @@ -51,7 +59,7 @@ initEvent() { let { trigger, show, hide, handleClick, splitButton } = this; let triggerElm = splitButton - ? this.$refs.trigger + ? this.$refs.trigger.$el : this.$slots.default[0].elm; if (trigger === 'hover') { @@ -74,8 +82,7 @@ }, render(h) { - let { hide, splitButton, visible, type } = this; - let dropdownElm = visible ? this.$slots.dropdown : null; + let { hide, splitButton, type, size } = this; var handleClick = _ => { this.$emit('click'); @@ -84,10 +91,10 @@ let triggerElm = !splitButton ? this.$slots.default : (<el-button-group> - <el-button type={type} nativeOn-click={handleClick}> + <el-button type={type} size={size} nativeOn-click={handleClick}> {this.$slots.default} </el-button> - <el-button ref="trigger" type={type} class="el-dropdown__icon-button"> + <el-button ref="trigger" type={type} size={size} class="el-dropdown__icon-button"> <i class="el-dropdown__icon el-icon-caret-bottom"></i> </el-button> </el-button-group>); @@ -95,9 +102,7 @@ return ( <div class="el-dropdown" v-clickoutside={hide}> {triggerElm} - <transition name="md-fade-bottom"> - {dropdownElm} - </transition> + {this.$slots.dropdown} </div> ); } diff --git a/packages/form/src/form-item.vue b/packages/form/src/form-item.vue index 3c5f2f94e..e63d89ed2 100644 --- a/packages/form/src/form-item.vue +++ b/packages/form/src/form-item.vue @@ -127,9 +127,12 @@ } }, getRules() { - if (!this.prop) { return []; } - var rules = this.rules || (this.form.rules ? this.form.rules[this.prop] : []); - return Array.isArray(rules) ? rules : [rules]; + var formRules = this.form.rules; + var selfRuels = this.rules; + + formRules = formRules ? formRules[this.prop] : []; + + return [].concat(selfRuels || formRules || []); }, getFilteredRule(trigger) { var rules = this.getRules(); @@ -151,21 +154,22 @@ } }, mounted() { - var rules = this.getRules(); - - rules.every(rule => { - if (rule.required) { - this.isRequired = true; - return false; - } - }); - if (this.prop) { this.dispatch('form', 'el.form.addField', [this]); - } - this.$on('el.form.blur', this.onFieldBlur); - this.$on('el.form.change', this.onFieldChange); + let rules = this.getRules(); + + if (rules.length) { + rules.every(rule => { + if (rule.required) { + this.isRequired = true; + return false; + } + }); + this.$on('el.form.blur', this.onFieldBlur); + this.$on('el.form.change', this.onFieldChange); + } + } }, beforeDestroy() { this.dispatch('form', 'el.form.removeField', [this]); diff --git a/packages/input/src/input.vue b/packages/input/src/input.vue index 220fe7f07..28d8e705f 100644 --- a/packages/input/src/input.vue +++ b/packages/input/src/input.vue @@ -15,7 +15,7 @@ <input class="el-input__inner" v-model="currentValue" - :type="type" + type="text" :name="name" :placeholder="placeholder" :disabled="disabled" @@ -25,7 +25,7 @@ :minlength="minlength" :autocomplete="autoComplete" ref="input" - @focus="$emit('onfocus', currentValue)" + @focus="$emit('focus', currentValue)" @blur="handleBlur" > <!-- input 图标 --> @@ -49,7 +49,7 @@ :rows="rows" :maxlength="maxlength" :minlength="minlength" - @focus="$emit('onfocus', currentValue)" + @focus="$emit('focus', currentValue)" @blur="handleBlur"> </textarea> </div> @@ -162,6 +162,7 @@ 'currentValue'(val) { this.$emit('input', val); + this.$emit('change', val); this.dispatch('form-item', 'el.form.change', [val]); } } diff --git a/packages/loading/package.json b/packages/loading/package.json index b2db41026..533a1103e 100644 --- a/packages/loading/package.json +++ b/packages/loading/package.json @@ -11,5 +11,7 @@ "repository": "https://github.com/element-component/element/tree/master/packages/loading", "author": "elemefe", "license": "MIT", - "dependencies": {} + "dependencies": { + "wind-dom": "0.0.3" + } } diff --git a/packages/loading/src/spinner.js b/packages/loading/src/spinner.js index 97e29adf7..342a6e819 100644 --- a/packages/loading/src/spinner.js +++ b/packages/loading/src/spinner.js @@ -1,10 +1,12 @@ +import { addClass } from 'wind-dom/src/class'; + class Spinner { constructor() { let spinner = document.createElement('div'); - spinner.classList.add('el-loading-spinner'); + addClass(spinner, 'el-loading-spinner'); [1, 2, 3].forEach(index => { let bubble = document.createElement('div'); - bubble.classList.add('el-loading-bubble', `bubble${ index }`); + addClass(bubble, `el-loading-bubble bubble${ index }`); spinner.appendChild(bubble); }); this.el = spinner; diff --git a/packages/menu/src/menu.vue b/packages/menu/src/menu.vue index f96809e67..815e0885c 100644 --- a/packages/menu/src/menu.vue +++ b/packages/menu/src/menu.vue @@ -27,12 +27,7 @@ type: String, default: '' }, - defaultOpeneds: { - type: Array, - default() { - return []; - } - }, + defaultOpeneds: Array, theme: { type: String, default: 'light' @@ -43,7 +38,7 @@ data() { return { activeIndex: this.defaultActive, - openedMenus: this.defaultOpeneds.slice(0), + openedMenus: this.defaultOpeneds ? this.defaultOpeneds.slice(0) : [], menuItems: {}, submenus: {} }; @@ -63,6 +58,7 @@ openMenu(index, indexPath) { let openedMenus = this.openedMenus; if (openedMenus.indexOf(index) !== -1) return; + // 将不在该菜单路径下的其余菜单收起 if (this.uniqueOpened) { this.openedMenus = openedMenus.filter(index => { return indexPath.indexOf(index) !== -1; @@ -92,29 +88,28 @@ this.broadcast('submenu', 'item-select', [index, indexPath]); this.openedMenus = []; } else { + this.openActiveItemMenus(); + } + + if (this.router && route) { + this.$router.push(route); + } + }, + openActiveItemMenus() { + let index = this.activeIndex; + if (index && this.mode === 'vertical') { + let indexPath = this.menuItems[index].indexPath; + // 展开该菜单项的路径上所有子菜单 indexPath.forEach(index => { let submenu = this.submenus[index]; submenu && this.openMenu(index, submenu.indexPath); }); } - - if (this.router && route) { - this.$router.push(route); - } } }, mounted() { - let index = this.activeIndex; - if (index && this.mode === 'vertical') { - let indexPath = this.menuItems[index].indexPath; - - // 展开该菜单项的路径上所有子菜单 - indexPath.forEach(index => { - let submenu = this.submenus[index]; - submenu && this.openMenu(index, submenu.indexPath); - }); - } + this.openActiveItemMenus(); } }; </script> diff --git a/packages/message-box/package.json b/packages/message-box/package.json index 97718de96..b0b3315d6 100644 --- a/packages/message-box/package.json +++ b/packages/message-box/package.json @@ -12,5 +12,6 @@ "author": "elemefe", "license": "MIT", "dependencies": { + "wind-dom": "0.0.3" } } diff --git a/packages/message-box/src/main.vue b/packages/message-box/src/main.vue index e9d1548db..1502822a6 100644 --- a/packages/message-box/src/main.vue +++ b/packages/message-box/src/main.vue @@ -35,6 +35,7 @@ import Popup from 'vue-popup'; import ElInput from 'packages/input/index.js'; + import { addClass, removeClass } from 'wind-dom/src/class'; export default { mixins: [ Popup ], @@ -113,7 +114,7 @@ var inputPattern = this.inputPattern; if (inputPattern && !inputPattern.test(this.inputValue || '')) { this.editorErrorMessage = this.inputErrorMessage || '输入的数据不合法!'; - this.$refs.input.$el.querySelector('input').classList.add('invalid'); + addClass(this.$refs.input.$el.querySelector('input'), 'invalid'); return false; } var inputValidator = this.inputValidator; @@ -121,7 +122,7 @@ var validateResult = inputValidator(this.inputValue); if (validateResult === false) { this.editorErrorMessage = this.inputErrorMessage || '输入的数据不合法!'; - this.$refs.input.$el.querySelector('input').classList.add('invalid'); + addClass(this.$refs.input.$el.querySelector('input'), 'invalid'); return false; } if (typeof validateResult === 'string') { @@ -131,7 +132,7 @@ } } this.editorErrorMessage = ''; - this.$refs.input.$el.querySelector('input').classList.remove('invalid'); + removeClass(this.$refs.input.$el.querySelector('input'), 'invalid'); return true; } }, diff --git a/packages/pagination/src/pagination.js b/packages/pagination/src/pagination.js index 9399f248f..3a70dc4ce 100644 --- a/packages/pagination/src/pagination.js +++ b/packages/pagination/src/pagination.js @@ -168,14 +168,9 @@ export default { this.oldValue = event.target.value; }, - handleChange(event) { - const target = event.target; + handleChange({ target }) { this.$parent.internalCurrentPage = this.$parent.getValidCurrentPage(target.value); - - if (target.value !== this.oldValue && Number(target.value) === this.$parent.internalCurrentPage) { - this.$parent.$emit('currentchange', this.$parent.internalCurrentPage); - } - + this.$parent.$emit('currentchange', this.$parent.internalCurrentPage); this.oldValue = null; } }, @@ -189,12 +184,11 @@ export default { type="number" min={ 1 } max={ this.pageCount } - value={ this.$parent.internalCurrentPage } + domProps-value={ this.$parent.internalCurrentPage } on-change={ this.handleChange } on-focus={ this.handleFocus } style={{ width: '30px' }} - number - lazy/> + number/> 页 </span> ); diff --git a/packages/popover/src/main.vue b/packages/popover/src/main.vue index 2f840df83..3724144e3 100644 --- a/packages/popover/src/main.vue +++ b/packages/popover/src/main.vue @@ -46,65 +46,59 @@ export default { transition: { type: String, default: 'fade-in-linear' - }, - options: { - default() { - return { - gpuAcceleration: false - }; - } } }, mounted() { - setTimeout(() => { - let _timer; - const reference = this.reference || this.$refs.reference || this.$slots.reference[0].elm; + let _timer; + const reference = this.reference || this.$refs.reference || this.$slots.reference[0].elm; + const popper = this.popper || this.$refs.popper; - this.$nextTick(() => { - if (this.trigger === 'click') { - on(reference, 'click', () => { this.showPopper = !this.showPopper; }); - on(document, 'click', (e) => { - if (!this.$el || - !reference || - this.$el.contains(e.target) || - reference.contains(e.target)) return; + this.$nextTick(() => { + if (this.trigger === 'click') { + on(reference, 'click', () => { this.showPopper = !this.showPopper; }); + on(document, 'click', (e) => { + if (!this.$el || + !reference || + this.$el.contains(e.target) || + reference.contains(e.target) || + !popper || + popper.contains(e.target)) return; + this.showPopper = false; + }); + } else if (this.trigger === 'hover') { + on(reference, 'mouseenter', () => { + this.showPopper = true; + clearTimeout(_timer); + }); + on(reference, 'mouseleave', () => { + _timer = setTimeout(() => { this.showPopper = false; - }); - } else if (this.trigger === 'hover') { - on(reference, 'mouseenter', () => { - this.showPopper = true; - clearTimeout(_timer); - }); - on(reference, 'mouseleave', () => { - _timer = setTimeout(() => { - this.showPopper = false; - }, 200); - }); - } else { - if ([].slice.call(reference.children).length) { - const children = reference.childNodes; + }, 200); + }); + } else { + if ([].slice.call(reference.children).length) { + const children = reference.childNodes; - for (let i = 0; i < children.length; i++) { - if (children[i].nodeName === 'INPUT') { - on(children[i], 'focus', () => { this.showPopper = true; }); - on(children[i], 'blur', () => { this.showPopper = false; }); - break; - } + for (let i = 0; i < children.length; i++) { + if (children[i].nodeName === 'INPUT') { + on(children[i], 'focus', () => { this.showPopper = true; }); + on(children[i], 'blur', () => { this.showPopper = false; }); + break; } - } else if ( - reference.nodeName === 'INPUT' || - reference.nodeName === 'TEXTAREA' - ) { - on(reference, 'focus', () => { this.showPopper = true; }); - on(reference, 'blur', () => { this.showPopper = false; }); - } else { - on(reference, 'mousedown', () => { this.showPopper = true; }); - on(reference, 'mouseup', () => { this.showPopper = false; }); } + } else if ( + reference.nodeName === 'INPUT' || + reference.nodeName === 'TEXTAREA' + ) { + on(reference, 'focus', () => { this.showPopper = true; }); + on(reference, 'blur', () => { this.showPopper = false; }); + } else { + on(reference, 'mousedown', () => { this.showPopper = true; }); + on(reference, 'mouseup', () => { this.showPopper = false; }); } - }); - }, 100); + } + }); }, destroyed() { diff --git a/packages/rate/package.json b/packages/rate/package.json index 111d54f7d..d1233975a 100644 --- a/packages/rate/package.json +++ b/packages/rate/package.json @@ -11,5 +11,7 @@ "repository": "https://github.com/element-component/element/tree/master/packages/rate", "author": "elemefe", "license": "MIT", - "dependencies": {} + "dependencies": { + "wind-dom": "0.0.3" + } } diff --git a/packages/rate/src/main.vue b/packages/rate/src/main.vue index 124748116..13c8f4402 100644 --- a/packages/rate/src/main.vue +++ b/packages/rate/src/main.vue @@ -24,6 +24,8 @@ </template> <script type="text/babel"> + import { hasClass } from 'wind-dom/src/class'; + export default { name: 'el-rate', @@ -223,10 +225,10 @@ } if (this.allowHalf) { let target = event.target; - if (target.classList.contains('el-rate__item')) { + if (hasClass(target, 'el-rate__item')) { target = target.querySelector('.el-rate__icon'); } - if (target.classList.contains('el-rate__decimal')) { + if (hasClass(target, 'el-rate__decimal')) { target = target.parentNode; } this.pointerAtLeftHalf = event.offsetX * 2 <= target.clientWidth; diff --git a/packages/select-dropdown/src/select-dropdown.vue b/packages/select-dropdown/src/select-dropdown.vue index f440dba85..4323918ab 100644 --- a/packages/select-dropdown/src/select-dropdown.vue +++ b/packages/select-dropdown/src/select-dropdown.vue @@ -1,71 +1,58 @@ <template> - <div class="el-select-dropdown"> + <div + class="el-select-dropdown" + :class="{ 'is-multiple': $parent.multiple }" + :style="{ minWidth: minWidth }"> <slot></slot> </div> </template> <script type="text/babel"> - import Popper from 'main/utils/popper'; + import Popper from 'main/utils/vue-popper'; export default { name: 'el-select-dropdown', componentName: 'select-dropdown', + mixins: [Popper], + + props: { + placement: { + default: 'bottom-start' + }, + + boundariesPadding: { + default: 0 + }, + + options: { + default() { + return { + forceAbsolute: true, + gpuAcceleration: false + }; + } + } + }, + data() { return { - popper: null + minWidth: '' }; }, - created() { + watch: { + '$parent.inputWidth'() { + this.minWidth = this.$parent.$el.getBoundingClientRect().width + 'px'; + } + }, + + mounted() { + this.referenceElm = this.$parent.$refs.reference.$el; + this.$parent.popperElm = this.popperElm = this.$el; this.$on('updatePopper', this.updatePopper); this.$on('destroyPopper', this.destroyPopper); - }, - - methods: { - updatePopper() { - if (this.popper) { - this.$nextTick(() => { - this.popper.update(); - }); - } else { - this.$nextTick(() => { - this.popper = new Popper(this.$parent.$refs.reference.$el, this.$el, { - gpuAcceleration: false, - placement: 'bottom-start', - boundariesPadding: 0, - forceAbsolute: true - }); - this.popper.onCreate(popper => { - this.resetTransformOrigin(popper); - }); - }); - } - }, - - destroyPopper() { - if (this.popper) { - this.resetTransformOrigin(this.popper); - setTimeout(() => { - this.popper.destroy(); - this.popper = null; - }, 300); - } - }, - - resetTransformOrigin(popper) { - let placementMap = { top: 'bottom', bottom: 'top' }; - let placement = popper._popper.getAttribute('x-placement').split('-')[0]; - let origin = placementMap[placement]; - popper._popper.style.transformOrigin = `center ${ origin }`; - } - }, - - beforeDestroy() { - if (this.popper) { - this.popper.destroy(); - } } }; </script> diff --git a/packages/select/package.json b/packages/select/package.json index 95fd7126f..adfa6aedc 100644 --- a/packages/select/package.json +++ b/packages/select/package.json @@ -13,6 +13,7 @@ "repository": "https://github.com/element-component/element/tree/master/packages/select", "devDependencies": { "throttle-debounce": "^1.0.1", - "vue-clickoutside": "0.0.4" + "vue-clickoutside": "0.0.4", + "wind-dom": "0.0.3" } } diff --git a/packages/select/src/select.vue b/packages/select/src/select.vue index 0f700ecf6..81ee8bdf6 100644 --- a/packages/select/src/select.vue +++ b/packages/select/src/select.vue @@ -1,5 +1,8 @@ <template> - <div class="el-select" :class="{ 'is-multiple': multiple, 'is-small': size === 'small' }"> + <div + class="el-select" + v-clickoutside="handleClose" + :class="{ 'is-multiple': multiple, 'is-small': size === 'small' }"> <div class="el-select__tags" v-if="multiple" @click.stop="toggleMenu" ref="tags" :style="{ 'max-width': inputWidth - 32 + 'px' }"> <transition-group @after-leave="resetInputHeight"> <el-tag @@ -45,10 +48,9 @@ @keydown.native.tab="visible = false" @mouseenter.native="inputHovering = true" @mouseleave.native="inputHovering = false" - :icon="iconClass" - v-element-clickoutside="handleClose"> + :icon="iconClass"> </el-input> - <transition name="md-fade-bottom"> + <transition name="md-fade-bottom" @after-leave="doDestroy"> <el-select-menu ref="popper" v-show="visible && nodataText !== false"> @@ -68,6 +70,7 @@ import ElTag from 'packages/tag/index.js'; import debounce from 'throttle-debounce/debounce'; import Clickoutside from 'main/utils/clickoutside'; + import { addClass, removeClass } from 'wind-dom/src/class'; export default { mixins: [emitter], @@ -93,10 +96,10 @@ if (icon) { if (criteria) { icon.addEventListener('click', this.deleteSelected); - icon.classList.add('is-show-close'); + addClass(icon, 'is-show-close'); } else { icon.removeEventListener('click', this.deleteSelected); - icon.classList.remove('is-show-close'); + removeClass(icon, 'is-show-close'); } } return criteria; @@ -127,9 +130,7 @@ ElTag }, - directives: { - ElementClickoutside: Clickoutside - }, + directives: { Clickoutside }, props: { name: String, @@ -270,7 +271,7 @@ if (!val) { this.$refs.reference.$el.querySelector('input').blur(); if (this.$el.querySelector('.el-input__icon')) { - this.$el.querySelector('.el-input__icon').classList.remove('is-reverse'); + removeClass(this.$el.querySelector('.el-input__icon'), 'is-reverse'); } this.broadcast('select-dropdown', 'destroyPopper'); if (this.$refs.input) { @@ -287,7 +288,7 @@ } } else { if (this.$el.querySelector('.el-input__icon')) { - this.$el.querySelector('.el-input__icon').classList.add('is-reverse'); + addClass(this.$el.querySelector('.el-input__icon'), 'is-reverse'); } this.broadcast('select-dropdown', 'updatePopper'); if (this.filterable) { @@ -316,6 +317,10 @@ }, methods: { + doDestroy() { + this.$refs.popper.doDestroy(); + }, + handleClose() { this.visible = false; }, diff --git a/packages/slider/src/main.vue b/packages/slider/src/main.vue index 73bd7ff74..e66be5ab4 100644 --- a/packages/slider/src/main.vue +++ b/packages/slider/src/main.vue @@ -26,10 +26,11 @@ </div> </template> -<script type="text/ecmascript-6"> +<script type="text/babel"> import Popper from 'main/utils/popper'; import ElInputNumber from 'packages/input-number/index.js'; import { getStyle } from 'wind-dom/src/style'; + import { addClass, removeClass } from 'wind-dom/src/class'; export default { name: 'ElSlider', @@ -125,8 +126,8 @@ let placementMap = { top: 'bottom', bottom: 'top' }; let placement = this.popper._popper.getAttribute('x-placement').split('-')[0]; let origin = placementMap[placement]; - this.popper._popper.classList.add(placement); - this.popper._popper.classList.remove(placementMap[placement]); + addClass(this.popper._popper, placement); + removeClass(this.popper._popper, placementMap[placement]); this.popper._popper.style.transformOrigin = `center ${ origin }`; }, diff --git a/packages/steps/src/step.vue b/packages/steps/src/step.vue index abf1261ed..22fea2112 100644 --- a/packages/steps/src/step.vue +++ b/packages/steps/src/step.vue @@ -12,17 +12,18 @@ <i class="el-step__line-inner" :style="lineStyle"></i> </div> - <slot - v-if="currentStatus !== 'success' && currentStatus !== 'error'" - name="icon"> - <i v-if="icon" :class="['el-step__icon', 'el-icon-' + icon]"></i> - <div v-else>{{ index + 1 }}</div> - </slot> - <i - v-else - class="el-step__icon" - :class="['el-icon-' + (currentStatus === 'success' ? 'check' : 'close')]"> - </i> + <span class="el-step__icon"> + <slot + v-if="currentStatus !== 'success' && currentStatus !== 'error'" + name="icon"> + <i v-if="icon" :class="['el-icon-' + icon]"></i> + <div v-else>{{ index + 1 }}</div> + </slot> + <i + v-else + :class="['el-icon-' + (currentStatus === 'success' ? 'check' : 'close')]"> + </i> + </span> </div> <div class="el-step__main" @@ -59,8 +60,8 @@ export default { data() { return { index: -1, - style: { width: 0, height: 0 }, - lineStyle: { width: 0, height: 0 }, + style: { width: '', height: '' }, + lineStyle: { width: '', height: '' }, mainOffset: 0, currentStatus: this.status }; diff --git a/packages/table/src/table-body.js b/packages/table/src/table-body.js index 5092f47f2..a5ba6a930 100644 --- a/packages/table/src/table-body.js +++ b/packages/table/src/table-body.js @@ -155,11 +155,6 @@ export default { grid.$emit('rowclick', row, event); }, - handleCreate(vm) { - document.body.appendChild(vm.$refs.popper); - vm.updatePopper(); - }, - $getPropertyText(row, property, columnId) { let grid = this.$parent; const column = getColumnById(grid, columnId); diff --git a/packages/table/src/table-column.js b/packages/table/src/table-column.js index dd2e8373c..188d1acca 100644 --- a/packages/table/src/table-column.js +++ b/packages/table/src/table-column.js @@ -190,7 +190,6 @@ export default { return _self.showTooltipWhenOverflow ? <el-tooltip - on-created={ this.handleCreate } effect={ this.effect } placement="top" disabled={ this.tooltipDisabled }> diff --git a/packages/theme-default/src/dropdown-menu.css b/packages/theme-default/src/dropdown-menu.css new file mode 100644 index 000000000..e69de29bb diff --git a/packages/theme-default/src/icon.css b/packages/theme-default/src/icon.css index f24d22b47..4bfe12935 100644 --- a/packages/theme-default/src/icon.css +++ b/packages/theme-default/src/icon.css @@ -17,7 +17,7 @@ font-variant: normal; text-transform: none; line-height: 1; - vertical-align: bottom; + vertical-align: baseline; display: inline-block; /* Better Font Rendering =========== */ diff --git a/packages/theme-default/src/index.css b/packages/theme-default/src/index.css index 93edd39ae..a2c8792b2 100644 --- a/packages/theme-default/src/index.css +++ b/packages/theme-default/src/index.css @@ -9,6 +9,7 @@ @import "./radio.css"; @import "./switch.css"; @import "./dropdown.css"; +@import "./dropdown-menu.css"; @import "./loading.css"; @import "./dialog.css"; @import "./table.css"; diff --git a/packages/theme-default/src/select-dropdown.css b/packages/theme-default/src/select-dropdown.css index d887089df..dde8ab7e6 100644 --- a/packages/theme-default/src/select-dropdown.css +++ b/packages/theme-default/src/select-dropdown.css @@ -4,7 +4,6 @@ @component-namespace el { @b select-dropdown { - width: 100%; position: absolute; z-index: 1001; border: solid 1px #d3dce6; @@ -12,5 +11,44 @@ background-color: #fff; box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04); box-sizing: border-box; + margin: 5px 0; + + @when multiple { + & .el-select-dropdown__item.selected { + color: #20A0FF; + background-color: #fff; + + &.hover { + background-color: #E5E9F2; + } + + &::after { + position: absolute; + right: 10px; + font-family: 'element-icons'; + content: "\E608"; + font-size: 11px; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } + } + } + } + + @b select-dropdown__nodata { + padding: 10px 0; + margin: 0; + text-align: center; + color: #999; + } + + @b select-dropdown__list { + list-style: none; + padding: 6px 0; + margin: 0; + width: 100%; + max-height: 274px; + box-sizing: border-box; + overflow-y: auto; } } diff --git a/packages/theme-default/src/select.css b/packages/theme-default/src/select.css index 6b0c801fb..e50802b89 100644 --- a/packages/theme-default/src/select.css +++ b/packages/theme-default/src/select.css @@ -25,27 +25,6 @@ } } - & .el-select-dropdown { - margin: 5px 0; - - & p.el-select-dropdown__nodata { - padding: 10px 0; - margin: 0; - text-align: center; - color: #999; - } - } - - & .el-select-dropdown__list { - list-style: none; - padding: 6px 0; - margin: 0; - width: 100%; - max-height: 274px; - box-sizing: border-box; - overflow-y: auto; - } - & .el-input { & .el-input__icon { color: #c0ccda; @@ -95,27 +74,6 @@ } } - @when multiple { - & .el-select-dropdown__item.selected { - color: #20A0FF; - background-color: #fff; - - &.hover { - background-color: #E5E9F2; - } - - &::after { - position: absolute; - right: 10px; - font-family: 'element-icons'; - content: "\E608"; - font-size: 11px; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - } - } - } - @e input { border: none; outline: none; diff --git a/packages/theme-default/src/step.css b/packages/theme-default/src/step.css index 94bb5b7ba..834e1eecb 100644 --- a/packages/theme-default/src/step.css +++ b/packages/theme-default/src/step.css @@ -19,10 +19,6 @@ & .el-step__main { padding-left: 10px; } - - & .el-step__description { - width: 300px; - } } @e line { @@ -69,6 +65,10 @@ @e icon { line-height: 28px; + + > * { + line-height: inherit; + } } @e head { @@ -149,7 +149,7 @@ @e title { font-size: 14px; - margin-top: 5px; + line-height: 32px; display: inline-block; @when process { diff --git a/packages/theme-default/src/time-select.css b/packages/theme-default/src/time-select.css index 949dadb87..3a569df46 100644 --- a/packages/theme-default/src/time-select.css +++ b/packages/theme-default/src/time-select.css @@ -3,9 +3,8 @@ @import "../../date-picker/src/css/vars.css"; .time-select { - min-width: 200px; margin: 5px 0; - width: 100%; + min-width: 0; } .time-select .el-picker-panel__content { diff --git a/packages/tree/src/tree-node.vue b/packages/tree/src/tree-node.vue index 2f36a9d1a..bb1ff7238 100644 --- a/packages/tree/src/tree-node.vue +++ b/packages/tree/src/tree-node.vue @@ -10,9 +10,9 @@ <span v-if="node.loading" class="el-tree-node__icon el-icon-loading" - > + > </span> - <span class="el-tree-node__label">{{ node.label }}</span> + <span class="el-tree-node__label" v-html="node.label"></span> </div> <collapse-transition> <div class="el-tree-node__children" @@ -94,9 +94,9 @@ } }, - handleCheckChange(checked) { + handleCheckChange(ev) { if (!this.node.indeterminate) { - this.node.setChecked(checked, true); + this.node.setChecked(ev.target.checked, true); } } }, diff --git a/packages/upload/src/index.vue b/packages/upload/src/index.vue index e51ac9eac..7b27f1279 100644 --- a/packages/upload/src/index.vue +++ b/packages/upload/src/index.vue @@ -31,18 +31,13 @@ export default { }; } }, - multiple: { - type: Boolean, - default: false - }, + data: Object, + multiple: Boolean, name: { type: String, default: 'file' }, - withCredentials: { - type: Boolean, - default: false - }, + withCredentials: Boolean, thumbnailMode: Boolean, showUploadList: { type: Boolean, @@ -179,6 +174,7 @@ export default { 'with-credentials': this.withCredentials, headers: this.headers, name: this.name, + data: this.data, accept: this.thumbnailMode ? 'image/*' : this.accept, 'on-start': this.handleStart, 'on-progress': this.handleProgress, diff --git a/packages/upload/src/upload.vue b/packages/upload/src/upload.vue index b931addd8..20ede25b0 100644 --- a/packages/upload/src/upload.vue +++ b/packages/upload/src/upload.vue @@ -34,6 +34,7 @@ export default { type: String, default: 'file' }, + data: Object, headers: Object, withCredentials: Boolean, multiple: Boolean, @@ -133,6 +134,7 @@ export default { headers: this.headers, withCredentials: this.withCredentials, file: file, + data: this.data, filename: this.name, onProgress: e => { this.onProgress(e, file); diff --git a/src/index.js b/src/index.js index 40a472b04..a9a531943 100644 --- a/src/index.js +++ b/src/index.js @@ -127,7 +127,7 @@ if (typeof window !== 'undefined' && window.Vue) { }; module.exports = { - version: '1.0.0-rc.5', + version: '1.0.0-rc.6', install, SelectDropdown, Pagination, diff --git a/src/mixins/emitter.js b/src/mixins/emitter.js index 515705c13..117243e4d 100644 --- a/src/mixins/emitter.js +++ b/src/mixins/emitter.js @@ -12,7 +12,7 @@ function broadcast(componentName, eventName, params) { export default { methods: { dispatch(componentName, eventName, params) { - var parent = this.$parent; + var parent = this.$parent || this.$root; var name = parent.$options.componentName; while (parent && (!name || name !== componentName)) { diff --git a/src/utils/clickoutside.js b/src/utils/clickoutside.js index ccbbc6687..32550cb58 100644 --- a/src/utils/clickoutside.js +++ b/src/utils/clickoutside.js @@ -1,3 +1,5 @@ +import { on, off } from 'wind-dom/src/event'; + /** * v-clickoutside * @desc 点击元素外面才会触发的事件 @@ -11,7 +13,10 @@ const clickoutsideContext = '@@clickoutsideContext'; export default { bind(el, binding, vnode) { const documentHandler = function(e) { - if (!vnode.context || el.contains(e.target)) return; + if (!vnode.context || + el.contains(e.target) || + !vnode.context.popperElm || + vnode.context.popperElm.contains(e.target)) return; if (binding.expression) { vnode.context[el[clickoutsideContext].methodName](); } else { @@ -23,7 +28,7 @@ export default { methodName: binding.expression, bindingFn: binding.value }; - document.addEventListener('click', documentHandler); + on(document, 'click', documentHandler); }, update(el, binding) { @@ -32,7 +37,7 @@ export default { }, unbind(el) { - document.removeEventListener('click', el[clickoutsideContext].documentHandler); + off(document, 'click', el[clickoutsideContext].documentHandler); }, install(Vue) { diff --git a/src/utils/vue-popper.js b/src/utils/vue-popper.js index f6a6a55a9..88789d077 100644 --- a/src/utils/vue-popper.js +++ b/src/utils/vue-popper.js @@ -1,4 +1,5 @@ import PopperJS from './popper'; +import { PopupManager } from 'vue-popup'; /** * @param {HTMLElement} [reference=$refs.reference] - The reference element used to position the popper. @@ -26,10 +27,16 @@ export default { value: Boolean, visibleArrow: Boolean, transition: String, + appendToBody: { + type: Boolean, + default: true + }, options: { type: Object, default() { - return {}; + return { + gpuAcceleration: false + }; } } }, @@ -62,59 +69,48 @@ export default { } const options = this.options; - const popper = this.popper || this.$refs.popper; - const reference = this.reference || this.$refs.reference || this.$slots.reference[0].elm; + const popper = this.popperElm = this.popperElm || this.popper || this.$refs.popper; + const reference = this.referenceElm = this.referenceElm || this.reference || this.$refs.reference || this.$slots.reference[0].elm; if (!popper || !reference) return; - if (this.visibleArrow) { - this.appendArrow(popper); - } + if (this.visibleArrow) this.appendArrow(popper); + if (this.appendToBody) document.body.appendChild(this.popperElm); if (this.popperJS && this.popperJS.hasOwnProperty('destroy')) { this.popperJS.destroy(); } options.placement = this.placement; options.offset = this.offset; - - this.$nextTick(() => { - this.popperJS = new PopperJS( - reference, - popper, - options - ); - this.popperJS.onCreate(popper => { - this.resetTransformOrigin(popper); - this.$emit('created', this); - }); + this.popperJS = new PopperJS(reference, popper, options); + this.popperJS.onCreate(_ => { + this.$emit('created', this); + this.resetTransformOrigin(); }); + this.popperJS._popper.style.zIndex = PopupManager.nextZIndex(); }, updatePopper() { - if (this.popperJS) { - this.popperJS.update(); - } else { - this.createPopper(); - } + this.popperJS ? this.popperJS.update() : this.createPopper(); }, doDestroy() { - if (this.showPopper) return; + if (this.showPopper || !this.popperJS) return; this.popperJS.destroy(); this.popperJS = null; }, destroyPopper() { if (this.popperJS) { - this.resetTransformOrigin(this.popperJS); + this.resetTransformOrigin(); } }, - resetTransformOrigin(popper) { + resetTransformOrigin() { let placementMap = { top: 'bottom', bottom: 'top', left: 'right', right: 'left' }; - let placement = popper._popper.getAttribute('x-placement').split('-')[0]; + let placement = this.popperJS._popper.getAttribute('x-placement').split('-')[0]; let origin = placementMap[placement]; - popper._popper.style.transformOrigin = ['top', 'bottom'].indexOf(placement) > -1 ? `center ${ origin }` : `${ origin } center`; + this.popperJS._popper.style.transformOrigin = ['top', 'bottom'].indexOf(placement) > -1 ? `center ${ origin }` : `${ origin } center`; }, appendArrow(element) { @@ -144,8 +140,9 @@ export default { }, beforeDestroy() { - if (this.popperJS) { - this.popperJS.destroy(); - } + this.doDestroy(); + this.popperElm && + document.body.contains(this.popperElm) && + document.body.removeChild(this.popperElm); } };