update input-number and slider

pull/2/head
Leopoldthecoder 2016-08-11 15:51:13 +08:00
parent 4fcfa04a9b
commit c641355e4f
6 changed files with 111 additions and 73 deletions

View File

@ -21,45 +21,45 @@
<p>当我们需要标准的数字值时可以用到这个组件,它为你提供了数值输入提供了范围控制和递增递减的步数控制。</p> <p>当我们需要标准的数字值时可以用到这个组件,它为你提供了数值输入提供了范围控制和递增递减的步数控制。</p>
<div class="demo-box demo-input-number"> <div class="demo-box demo-input-number">
<el-input-number :value.sync="num1"></el-input-number> <el-input-number v-model="num1"></el-input-number>
</div> </div>
```html ```html
<el-input-number :value.sync="num1"></el-input-number> <el-input-number v-model="num1"></el-input-number>
``` ```
## 禁用状态 ## 禁用状态
<div class="demo-box demo-input-number"> <div class="demo-box demo-input-number">
<el-input-number :value.sync="num1" :disabled="true"></el-input-number> <el-input-number v-model="num1" :disabled="true"></el-input-number>
</div> </div>
```html ```html
<el-input-number :value.sync="num1" :disabled="true"></el-input-number> <el-input-number v-model="num1" :disabled="true"></el-input-number>
``` ```
## 步数 ## 步数
<div class="demo-box demo-input-number"> <div class="demo-box demo-input-number">
<el-input-number :value.sync="num2" :step="2"></el-input-number> <el-input-number v-model="num2" :step="2"></el-input-number>
</div> </div>
```html ```html
<el-input-number :value.sync="num2" :step="2"></el-input-number> <el-input-number v-model="num2" :step="2"></el-input-number>
``` ```
## 尺寸 ## 尺寸
<div class="demo-box demo-input-number"> <div class="demo-box demo-input-number">
<el-input-number :value.sync="num1" size="large"></el-input-number> <el-input-number v-model="num1" size="large"></el-input-number>
<el-input-number :value.sync="num1"></el-input-number> <el-input-number v-model="num1"></el-input-number>
<el-input-number :value.sync="num1" size="small"></el-input-number> <el-input-number v-model="num1" size="small"></el-input-number>
</div> </div>
```html ```html
<el-input-number :value.sync="num1" size="large"></el-input-number> <el-input-number v-model="num1" size="large"></el-input-number>
<el-input-number :value.sync="num1"></el-input-number> <el-input-number v-model="num1"></el-input-number>
<el-input-number :value.sync="num1" size="small"></el-input-number> <el-input-number v-model="num1" size="small"></el-input-number>
``` ```
## API ## API

View File

@ -1,5 +1,16 @@
<script> <script>
export default { export default {
data() {
return {
value1: 0,
value2: 50,
value3: null,
value4: null,
value5: null,
value6: null,
value7: null
};
},
methods: { methods: {
onChange(value) { onChange(value) {
console.log(value); console.log(value);
@ -10,55 +21,55 @@
## 基本用法 ## 基本用法
<el-slider></el-slider> <el-slider v-model="value1"></el-slider>
```html ```html
<el-slider></el-slider> <el-slider v-model="value1"></el-slider>
``` ```
## 定义初始值 ## 定义初始值
<el-slider :value="50"></el-slider> <el-slider v-model="value2"></el-slider>
```html ```html
<el-slider :value="50"></el-slider> <el-slider v-model="value2"></el-slider>
``` ```
## 定义区间 ## 定义区间
<el-slider :min="20" :max="80"></el-slider> <el-slider :min="20" :max="80" v-model="value3"></el-slider>
```html ```html
<el-slider :min="20" :max="80"></el-slider> <el-slider :min="20" :max="80" v-model="value3"></el-slider>
``` ```
## 定义步长 ## 定义步长
<el-slider :step="10"></el-slider> <el-slider :step="10" v-model="value4"></el-slider>
```html ```html
<el-slider :step="10"></el-slider> <el-slider :step="10" v-model="value4"></el-slider>
``` ```
## 显示间断点 ## 显示间断点
<el-slider :step="10" show-stops></el-slider> <el-slider :step="10" show-stops v-model="value5"></el-slider>
```html ```html
<el-slider :step="10" show-stops></el-slider> <el-slider :step="10" show-stops v-model="value5"></el-slider>
``` ```
## 带有输入框 ## 带有输入框
<el-slider show-input></el-slider> <el-slider show-input v-model="value6"></el-slider>
```html ```html
<el-slider show-input></el-slider> <el-slider show-input v-model="value6"></el-slider>
``` ```
## 回调函数 ## 回调函数
<el-slider @change="onChange"></el-slider> <el-slider @change="onChange" v-model="value7"></el-slider>
```html ```html
<template> <template>

View File

@ -6,8 +6,8 @@
]" ]"
> >
<el-input <el-input
:value="value" v-model="currentValue"
@onchange="handleChnage" @onchange="handleChange"
:disabled="disabled" :disabled="disabled"
:size="size" :size="size"
:number="true" :number="true"
@ -18,17 +18,17 @@
<span <span
class="el-input-number__decrease el-icon-minus" class="el-input-number__decrease el-icon-minus"
:class="{'is-disabled': minDisabled}" :class="{'is-disabled': minDisabled}"
v-repeat-click="decrease()" v-repeat-click="decrease"
@mouseenter="activeInput(minDisabled)" @mouseenter="activeInput(minDisabled)"
@mouseleave="unactiveInput(minDisabled)" @mouseleave="inactiveInput(minDisabled)"
> >
</span> </span>
<span <span
class="el-input-number__increase el-icon-plus" class="el-input-number__increase el-icon-plus"
:class="{'is-disabled': maxDisabled}" :class="{'is-disabled': maxDisabled}"
v-repeat-click="increase()" v-repeat-click="increase"
@mouseenter="activeInput(maxDisabled)" @mouseenter="activeInput(maxDisabled)"
@mouseleave="unactiveInput(maxDisabled)" @mouseleave="inactiveInput(maxDisabled)"
> >
</span> </span>
</div> </div>
@ -41,8 +41,7 @@
name: 'ElInputNumber', name: 'ElInputNumber',
props: { props: {
value: { value: {
type: Number, type: Number
required: true
}, },
step: { step: {
type: Number, type: Number,
@ -61,13 +60,12 @@
}, },
directives: { directives: {
repeatClick: { repeatClick: {
bind() { bind(el, binding, vnode) {
const el = this.el;
let interval = null; let interval = null;
let startTime; let startTime;
const handler = () => { const handler = () => {
this.vm.$get(this.expression); vnode.context[binding.expression]();
}; };
const clear = function() { const clear = function() {
@ -93,9 +91,23 @@
}, },
data() { data() {
return { return {
currentValue: null,
inputActive: false inputActive: false
}; };
}, },
watch: {
value: {
immediate: true,
handler(val) {
this.currentValue = val;
}
},
currentValue(val) {
if (!isNaN(parseInt(val, 10))) {
this.$emit('input', parseInt(val, 10));
}
}
},
computed: { computed: {
minDisabled() { minDisabled() {
return this.value - this.step < this.min; return this.value - this.step < this.min;
@ -107,14 +119,14 @@
methods: { methods: {
increase() { increase() {
if (this.value + this.step > this.max || this.disabled) return; if (this.value + this.step > this.max || this.disabled) return;
this.value += this.step; this.currentValue += this.step;
if (this.maxDisabled) { if (this.maxDisabled) {
this.inputActive = false; this.inputActive = false;
} }
}, },
decrease() { decrease() {
if (this.value - this.step < this.min || this.disabled) return; if (this.value - this.step < this.min || this.disabled) return;
this.value -= this.step; this.currentValue -= this.step;
if (this.minDisabled) { if (this.minDisabled) {
this.inputActive = false; this.inputActive = false;
} }
@ -124,12 +136,12 @@
this.inputActive = true; this.inputActive = true;
} }
}, },
unactiveInput(disabled) { inactiveInput(disabled) {
if (!this.disabled && !disabled) { if (!this.disabled && !disabled) {
this.inputActive = false; this.inputActive = false;
} }
}, },
handleChnage(value) { handleChange(value) {
this.$emit('onchange', value); this.$emit('onchange', value);
} }
} }

View File

@ -106,8 +106,11 @@
}, },
watch: { watch: {
'value'(val) { 'value': {
immediate: true,
handler(val) {
this.currentValue = val; this.currentValue = val;
}
}, },
'currentValue'(val) { 'currentValue'(val) {

View File

@ -1,11 +1,11 @@
<template> <template>
<div class="el-slider"> <div class="el-slider">
<el-input-number <el-input-number
:value.sync="value" v-model="inputValue"
v-if="showInput" v-if="showInput"
class="el-slider__input" class="el-slider__input"
@keyup="onInputChange()" @keyup.native="onInputChange()"
v-el:input ref="input"
:step="step" :step="step"
:min="min" :min="min"
:max="max" :max="max"
@ -13,12 +13,14 @@
</el-input-number> </el-input-number>
<div class="el-slider__runway" <div class="el-slider__runway"
:class="{ 'show-input': showInput }" :class="{ 'show-input': showInput }"
@click="onSliderClick($event)" v-el:slider> @click="onSliderClick" ref="slider">
<div class="el-slider__bar" :style="{ width: currentPosition }"></div> <div class="el-slider__bar" :style="{ width: currentPosition }"></div>
<div class="el-slider__button-wrapper" @mouseenter="hovering = true" @mouseleave="hovering = false" :style="{left: currentPosition}" v-el:button> <div class="el-slider__button-wrapper" @mouseenter="hovering = true" @mouseleave="hovering = false" :style="{left: currentPosition}" ref="button">
<div class="el-slider__button" :class="{ 'hover': hovering, 'dragging': dragging }"></div> <div class="el-slider__button" :class="{ 'hover': hovering, 'dragging': dragging }"></div>
</div> </div>
<div class="el-slider__pop" v-show="showTip" transition="popper-fade" v-el:pop>{{ value }}</div> <transition name="popper-fade">
<div class="el-slider__pop" v-show="showTip" transition="popper-fade" ref="pop">{{ value }}</div>
</transition>
<div class="el-slider__stop" v-for="item in stops" :style="{ 'left': item + '%' }" v-if="showStops"></div> <div class="el-slider__stop" v-for="item in stops" :style="{ 'left': item + '%' }" v-if="showStops"></div>
</div> </div>
</div> </div>
@ -69,6 +71,8 @@
data() { data() {
return { return {
inputValue: null,
timeout: null,
showTip: false, showTip: false,
hovering: false, hovering: false,
dragging: false, dragging: false,
@ -80,18 +84,22 @@
}, },
watch: { watch: {
inputValue(val) {
this.$emit('input', val);
},
showTip(val) { showTip(val) {
if (val) { if (val) {
this.$nextTick(() => { this.$nextTick(() => {
this.updatePopper(); this.updatePopper();
}); });
} else { } else {
setTimeout(() => { this.timeout = setTimeout(() => {
if (this.popper) { if (this.popper) {
this.popper.destroy(); this.popper.destroy();
this.popper = null; this.popper = null;
} }
}, 150); }, 300);
} }
}, },
@ -100,30 +108,37 @@
this.updatePopper(); this.updatePopper();
}); });
if (val < this.min) { if (val < this.min) {
this.value = this.min; this.$emit('input', this.min);
return; return;
} }
if (val > this.max) { if (val > this.max) {
this.value = this.max; this.$emit('input', this.max);
return; return;
} }
this.inputValue = val;
this.setPosition((val - this.min) * 100 / (this.max - this.min)); this.setPosition((val - this.min) * 100 / (this.max - this.min));
} }
}, },
methods: { methods: {
updatePopper() { handlePopperStyle() {
if (this.popper) {
this.popper.update();
} else {
this.popper = new Popper(this.$els.button, this.$els.pop, { gpuAcceleration: false, placement: 'top' });
this.popper.onCreate(() => {
let placementMap = { top: 'bottom', bottom: 'top' }; let placementMap = { top: 'bottom', bottom: 'top' };
let placement = this.popper._popper.getAttribute('x-placement').split('-')[0]; let placement = this.popper._popper.getAttribute('x-placement').split('-')[0];
let origin = placementMap[placement]; let origin = placementMap[placement];
this.popper._popper.classList.add(placement); this.popper._popper.classList.add(placement);
this.popper._popper.classList.remove(placementMap[placement]); this.popper._popper.classList.remove(placementMap[placement]);
this.popper._popper.style.transformOrigin = `center ${ origin }`; this.popper._popper.style.transformOrigin = `center ${ origin }`;
},
updatePopper() {
if (this.popper) {
clearTimeout(this.timeout);
this.popper.update();
this.handlePopperStyle();
} else {
this.popper = new Popper(this.$refs.button, this.$refs.pop, { gpuAcceleration: false, placement: 'top' });
this.popper.onCreate(() => {
this.handlePopperStyle();
}); });
this.updatePopper(); this.updatePopper();
} }
@ -133,7 +148,7 @@
if (newPos >= 0 && (newPos <= 100)) { if (newPos >= 0 && (newPos <= 100)) {
var lengthPerStep = 100 / ((this.max - this.min) / this.step); var lengthPerStep = 100 / ((this.max - this.min) / this.step);
var steps = Math.round(newPos / lengthPerStep); var steps = Math.round(newPos / lengthPerStep);
this.value = Math.round(steps * lengthPerStep * (this.max - this.min) * 0.01 + this.min); this.$emit('input', Math.round(steps * lengthPerStep * (this.max - this.min) * 0.01 + this.min));
this.currentPosition = (this.value - this.min) / (this.max - this.min) * 100 + '%'; this.currentPosition = (this.value - this.min) / (this.max - this.min) * 100 + '%';
if (!this.dragging) { if (!this.dragging) {
if (this.value !== this.oldValue) { if (this.value !== this.oldValue) {
@ -146,8 +161,7 @@
onSliderClick(event) { onSliderClick(event) {
var currentX = event.clientX; var currentX = event.clientX;
var sliderOffsetLeft; var sliderOffsetLeft = getStyle(this.$el.parentNode, 'position') === 'static' ? this.$refs.slider.offsetLeft : this.$el.parentNode.offsetLeft + this.$refs.slider.offsetLeft;
getStyle(this.$el.parentNode, 'position') === 'static' ? sliderOffsetLeft = this.$els.slider.offsetLeft : sliderOffsetLeft = this.$el.parentNode.offsetLeft + this.$els.slider.offsetLeft;
var newPos = (currentX - sliderOffsetLeft) / this.$sliderWidth * 100; var newPos = (currentX - sliderOffsetLeft) / this.$sliderWidth * 100;
this.setPosition(newPos); this.setPosition(newPos);
}, },
@ -164,7 +178,7 @@
computed: { computed: {
$sliderWidth() { $sliderWidth() {
return parseInt(getStyle(this.$els.slider, 'width'), 10); return parseInt(getStyle(this.$refs.slider, 'width'), 10);
}, },
showTip() { showTip() {
@ -183,7 +197,7 @@
} }
}, },
compiled() { mounted() {
var startX = 0; var startX = 0;
var currentX = 0; var currentX = 0;
var startPos = 0; var startPos = 0;
@ -212,7 +226,7 @@
} }
}; };
this.$els.button.addEventListener('mousedown', function(event) { this.$refs.button.addEventListener('mousedown', function(event) {
onDragStart(event); onDragStart(event);
window.addEventListener('mousemove', onDragging); window.addEventListener('mousemove', onDragging);
window.addEventListener('mouseup', onDragEnd); window.addEventListener('mouseup', onDragEnd);
@ -220,9 +234,10 @@
}, },
created() { created() {
if (this.value < this.min || this.value > this.max) { if (typeof this.value !== 'number' || this.value < this.min || this.value > this.max) {
this.value = this.min; this.$emit('input', this.min);
} }
this.inputValue = this.inputValue || this.value;
}, },
beforeDestroy() { beforeDestroy() {

View File

@ -74,6 +74,8 @@
color: #fff; color: #fff;
cursor: default; cursor: default;
z-index: var(--index-top); z-index: var(--index-top);
transition: transform .3s, opacity .3s;
transform-origin: center bottom;
&::before { &::before {
triangle: 9px top #20A0FF; triangle: 9px top #20A0FF;
@ -106,13 +108,8 @@
transform: translateX(-50%); transform: translateX(-50%);
} }
.popper-fade-transition {
transition: transform .3s, opacity .3s;
transform-origin: center bottom;
}
.popper-fade-enter, .popper-fade-enter,
.popper-fade-leave { .popper-fade-leave-active {
transform: scale(0.1); transform: scale(0.1);
opacity: 0; opacity: 0;
} }