vant components

This commit is contained in:
cookfront
2017-04-19 17:33:44 +08:00
commit 63c549d651
346 changed files with 25710 additions and 0 deletions
+8
View File
@@ -0,0 +1,8 @@
## 0.0.2 (2017-01-20)
* 改了bug A
* 加了功能B
## 0.0.1 (2017-01-10)
* 第一版
+26
View File
@@ -0,0 +1,26 @@
# @youzan/<%= name %>
!!! 请在此处填写你的文档最简单描述 !!!
[![version][version-image]][download-url]
[![download][download-image]][download-url]
[version-image]: http://npm.qima-inc.com/badge/v/@youzan/<%= name %>.svg?style=flat-square
[download-image]: http://npm.qima-inc.com/badge/d/@youzan/<%= name %>.svg?style=flat-square
[download-url]: http://npm.qima-inc.com/package/@youzan/<%= name %>
## Demo
## Usage
## API
| 参数 | 说明 | 类型 | 默认值 | 可选值 |
|-----------|-----------|-----------|-------------|-------------|
| className | 自定义额外类名 | string | '' | '' |
## License
[MIT](https://opensource.org/licenses/MIT)
+3
View File
@@ -0,0 +1,3 @@
import Picker from './src/picker';
export default Picker;
+10
View File
@@ -0,0 +1,10 @@
{
"name": "@youzan/van-picker",
"version": "0.0.1",
"description": "picker component",
"main": "./index.js",
"author": "zhangmin <zhangmin@youzan.com>",
"license": "MIT",
"devDependencies": {},
"dependencies": {}
}
+51
View File
@@ -0,0 +1,51 @@
import Vue from 'vue';
let isDragging = false;
const supportTouch = !Vue.prototype.$isServer && 'ontouchstart' in window;
export default function(element, options) {
const moveFn = function(event) {
if (options.drag) {
options.drag(supportTouch ? event.changedTouches[0] || event.touches[0] : event);
}
};
const endFn = function(event) {
if (!supportTouch) {
document.removeEventListener('mousemove', moveFn);
document.removeEventListener('mouseup', endFn);
}
document.onselectstart = null;
document.ondragstart = null;
isDragging = false;
if (options.end) {
options.end(supportTouch ? event.changedTouches[0] || event.touches[0] : event);
}
};
element.addEventListener(supportTouch ? 'touchstart' : 'mousedown', function(event) {
if (isDragging) return;
document.onselectstart = function() { return false; };
document.ondragstart = function() { return false; };
if (!supportTouch) {
document.addEventListener('mousemove', moveFn);
document.addEventListener('mouseup', endFn);
}
isDragging = true;
if (options.start) {
event.preventDefault();
options.start(supportTouch ? event.changedTouches[0] || event.touches[0] : event);
}
});
if (supportTouch) {
element.addEventListener('touchmove', moveFn);
element.addEventListener('touchend', endFn);
element.addEventListener('touchcancel', endFn);
}
};
+239
View File
@@ -0,0 +1,239 @@
<template>
<div class="van-picker-column" :class="classNames">
<div class="van-picker-column-wrapper" :class="{ dragging: isDragging }" ref="wrapper" :style="{ height: visibleContentHeight + 'px' }">
<div
v-for="item in currentValues"
class="van-picker-column__item"
:class="{ 'van-picker-column__item--selected': item === currentValue }"
:style="{ height: itemHeight + 'px', lineHeight: itemHeight + 'px' }">
{{ typeof item === 'object' && item[valueKey] ? item[valueKey] : item }}
</div>
</div>
</div>
</template>
<script>
import translateUtil from 'src/utils/transition';
import draggable from './draggable';
const DEFAULT_ITEM_HEIGHT = 44;
export default {
name: 'van-picker-column',
props: {
/**
* 每一列可见备选元素的个数
*/
visibileColumnCount: {
type: Number,
default: 5
},
/**
* 该列所有的可选值
*/
values: {
type: Array,
default() {
return [];
}
},
/**
* 每列添加额外的`className`
*/
className: {
type: String,
default: ''
},
/**
* 行高
*/
itemHeight: {
type: Number,
default: DEFAULT_ITEM_HEIGHT
},
value: {},
valueKey: String
},
data() {
return {
currentValue: this.value,
currentValues: this.values,
isDragging: false
};
},
watch: {
values(val) {
this.currentValues = val;
},
currentValues(val) {
if (this.valueIndex === -1) {
this.currentValue = (val || [])[0];
}
},
currentValue(val) {
this.doOnValueChange();
this.$emit('input', val);
this.$emit('columnChange', this);
}
},
computed: {
/**
* picker可见备选元素总高度
*/
visibleContentHeight() {
return this.itemHeight * this.visibileColumnCount;
},
/**
* 当前选中值在`values`中的索引
*/
valueIndex() {
return this.currentValues.indexOf(this.currentValue);
},
/**
* 计算picker的拖动范围
*/
dragRange() {
var values = this.currentValues;
var visibileColumnCount = this.visibileColumnCount;
var itemHeight = this.itemHeight;
return [-itemHeight * (values.length - Math.ceil(visibileColumnCount / 2)), itemHeight * Math.floor(visibileColumnCount / 2)];
},
/**
* 计算`classNames`
*/
classNames() {
return this.className.split(' ');
}
},
mounted() {
this.initEvents();
this.doOnValueChange();
},
methods: {
/**
* 将当前`value`值转换成需要垂直方向需要`translate`的值
*/
value2Translate(value) {
const values = this.currentValues;
const valueIndex = values.indexOf(value);
const offset = Math.floor(this.visibileColumnCount / 2);
const itemHeight = this.itemHeight;
if (valueIndex !== -1) {
return (valueIndex - offset) * (-itemHeight);
}
},
/**
* 根据当前`translate`的值转换成当前选中的`value`
*/
translate2Value(translate) {
const itemHeight = this.itemHeight;
translate = Math.round(translate / itemHeight) * itemHeight;
const index = -(translate - Math.floor(this.visibileColumnCount / 2) * itemHeight) / itemHeight;
return this.currentValues[index];
},
/**
* 初始化拖动事件
*/
initEvents() {
var el = this.$refs.wrapper;
var dragState = {};
var velocityTranslate;
var prevTranslate;
var pickerItems; // eslint-disable-line
draggable(el, {
start: (event) => {
// 存储当前状态
dragState = {
range: this.dragRange,
start: new Date(),
startLeft: event.pageX,
startTop: event.pageY,
startTranslateTop: translateUtil.getElementTranslate(el).top
};
pickerItems = el.querySelectorAll('.van-picker-item'); // eslint-disable-line
},
drag: (event) => {
this.isDragging = true;
dragState.left = event.pageX;
dragState.top = event.pageY;
const deltaY = dragState.top - dragState.startTop;
const translate = dragState.startTranslateTop + deltaY;
translateUtil.translateElement(el, null, translate);
velocityTranslate = translate - prevTranslate || translate;
prevTranslate = translate;
},
end: () => {
if (this.isDragging) {
this.isDragging = false;
var momentumRatio = 7;
var currentTranslate = translateUtil.getElementTranslate(el).top;
var duration = new Date() - dragState.start;
var momentumTranslate;
if (duration < 300) {
momentumTranslate = currentTranslate + velocityTranslate * momentumRatio;
}
var dragRange = dragState.range;
this.$nextTick(() => {
var translate;
var itemHeight = this.itemHeight;
if (momentumTranslate) {
translate = Math.round(momentumTranslate / itemHeight) * itemHeight;
} else {
translate = Math.round(currentTranslate / itemHeight) * itemHeight;
}
translate = Math.max(Math.min(translate, dragRange[1]), dragRange[0]);
translateUtil.translateElement(el, null, translate);
this.currentValue = this.translate2Value(translate);
});
}
dragState = {};
}
});
},
/**
* `value`改变时调用
*/
doOnValueChange() {
const value = this.currentValue;
const wrapper = this.$refs.wrapper;
translateUtil.translateElement(wrapper, null, this.value2Translate(value));
}
}
};
</script>
+159
View File
@@ -0,0 +1,159 @@
<template>
<div class="van-picker">
<div class="van-picker__toolbar" v-show="showToolbar">
<slot>
<a href="javascript:void(0)" class="van-picker__cancel" @click="handlePickerCancel">取消</a>
<a href="javascript:void(0)" class="van-picker__confirm" @click="handlePickerConfirm">完成</a>
</slot>
</div>
<div class="van-picker__columns" :class="['van-picker__columns--' + columns.length]">
<picker-column
v-for="(item, index) in columns"
v-model="values[index]"
:values="item.values"
:class-name="item.className"
:itemHeight="itemHeight"
:visible-item-count="visibleItemCount"
:value-key="valueKey"
@columnChange="columnValueChange(index)">
</picker-column>
<div class="van-picker-center-highlight" :style="{ height: itemHeight + 'px', marginTop: -itemHeight / 2 + 'px' }"></div>
</div>
</div>
</template>
<script>
import PickerColumn from './picker-column';
const DEFAULT_ITEM_HEIGHT = 44;
export default {
name: 'van-picker',
components: {
PickerColumn
},
props: {
/**
* 每一列可见备选元素的个数
*/
visibileColumnCount: {
type: Number,
default: 5
},
/**
* 选中元素区高度
*/
itemHeight: {
type: Number,
default: DEFAULT_ITEM_HEIGHT
},
/**
* 对象数组,配置每一列显示的数据
*/
columns: {
type: Array,
default() {
return [];
}
},
/**
* 否在组件顶部显示一个toolbar
*/
showToolbar: {
type: Boolean,
default: false
},
valueKey: String
},
computed: {
values() {
const columns = this.columns || [];
const values = [];
columns.forEach(column => {
values.push(column.value || column.values[column.defaultIndex || 0]);
});
return values;
}
},
methods: {
handlePickerCancel() {
this.$emit('cancel', this.values);
},
handlePickerConfirm() {
this.$emit('confirm', this.values);
},
/**
* 处理列`change`事件
*/
columnValueChange(index) {
this.$emit('change', this, this.values, index);
},
/**
* 获取对应索引的列的实例
*/
getColumn(index) {
const children = this.$children.filter(child => child.$options.name === 'van-picker-column');
return children[index];
},
/**
* 获取对应列中选中的值
*/
getColumnValue(index) {
const column = this.getColumn(index);
return column && column.values[column.valueIndex];
},
/**
* 设置对应列中选中的值
*/
setColumnValue(index, value) {
const column = this.getColumn(index);
if (column) {
column.currentValue = value;
}
},
/**
* 获取对应列中所有的备选值
*/
getColumnValues(index) {
const column = this.getColumn(index);
return column && column.currentValues;
},
/**
* 设置对应列中所有的备选值
*/
setColumnValues(index, values) {
const column = this.getColumn(index);
if (column) {
column.currentValues = values;
}
},
/**
* 获取所有列中被选中的值,返回一个数组
*/
getValues() {
return this.values;
},
/**
* `values`为一个数组,设置所有列中被选中的值
*/
setValues(values) {
values.forEach((value, index) => {
this.setColumnValue(index, value);
});
}
}
};
</script>