This commit is contained in:
陈嘉涵 2018-09-27 14:27:00 +08:00
parent b57b524787
commit 1bd233534c
41 changed files with 1262 additions and 1459 deletions

20
dist/area/index.js vendored
View File

@ -2,14 +2,8 @@ import { VantComponent } from '../common/component';
VantComponent({
props: {
title: String,
value: String,
loading: Boolean,
value: {
type: String,
observer(value) {
this.code = value;
this.setValues();
}
},
itemHeight: {
type: Number,
value: 44
@ -24,10 +18,7 @@ VantComponent({
},
areaList: {
type: Object,
value: {},
observer() {
this.setValues();
}
value: {}
}
},
data: {
@ -40,6 +31,13 @@ VantComponent({
return columns.slice(0, +columnsNum);
}
},
watch: {
value(value) {
this.code = value;
this.setValues();
},
areaList: 'setValues'
},
methods: {
onCancel() {
this.$emit('cancel', {

View File

@ -1,28 +1,29 @@
import { VantComponent } from '../common/component';
VantComponent({
relations: {
'../badge/index': {
type: 'descendant',
linked(target) {
this.data.badges.push(target);
this.setActive();
},
unlinked(target) {
this.data.badges = this.data.badges.filter(item => item !== target);
this.setActive();
}
relation: {
name: 'badge',
type: 'descendant',
linked(target) {
this.data.badges.push(target);
this.setActive();
},
unlinked(target) {
this.data.badges = this.data.badges.filter(item => item !== target);
this.setActive();
}
},
props: {
active: {
type: Number,
value: 0,
observer: 'setActive'
value: 0
}
},
data: {
badges: []
},
watch: {
active: 'setActive'
},
beforeCreate() {
this.currentActive = -1;
},

7
dist/badge/index.js vendored
View File

@ -1,9 +1,8 @@
import { VantComponent } from '../common/component';
VantComponent({
relations: {
'../badge-group/index': {
type: 'ancestor'
}
relation: {
type: 'ancestor',
name: 'badge-group'
},
props: {
info: Number,

View File

@ -1,7 +1,8 @@
import { VantComponent } from '../common/component';
import { button } from '../mixins/button';
import { openType } from '../mixins/open-type';
VantComponent({
mixins: [button],
mixins: [button, openType],
props: {
plain: Boolean,
block: Boolean,

View File

@ -1,5 +1,6 @@
<button
class="custom-class van-button {{ classes }}"
id="{{ id }}"
disabled="{{ disabled }}"
hover-class="button-hover"
open-type="{{ openType }}"
@ -14,11 +15,11 @@
send-message-img="{{ sendMessageImg }}"
show-message-card="{{ showMessageCard }}"
bind:tap="onClick"
bindcontact="bindcontact"
bindgetuserinfo="bindgetuserinfo"
bindgetphonenumber="bindgetphonenumber"
binderror="binderror"
bindopensetting="bindopensetting"
bindcontact="bindContact"
bindgetuserinfo="bindGetUserInfo"
bindgetphonenumber="bindGetPhoneNumber"
binderror="bindError"
bindopensetting="bindOpenSetting"
>
<van-loading
wx:if="{{ loading }}"

7
dist/col/index.js vendored
View File

@ -1,9 +1,8 @@
import { VantComponent } from '../common/component';
VantComponent({
relations: {
'../row/index': {
type: 'ancestor'
}
relation: {
name: 'row',
type: 'ancestor'
},
props: {
span: Number,

View File

@ -2,12 +2,14 @@ import { basic } from '../mixins/basic';
import { observe } from '../mixins/observer/index';
function mapKeys(source, target, map) {
Object.keys(map).forEach(key => {
target[map[key]] = source[key];
if (source[key]) {
target[map[key]] = source[key];
}
});
}
function VantComponent(sfc) {
function VantComponent(vantOptions) {
const options = {};
mapKeys(sfc, options, {
mapKeys(vantOptions, options, {
data: 'data',
props: 'properties',
mixins: 'behaviors',
@ -15,10 +17,16 @@ function VantComponent(sfc) {
beforeCreate: 'created',
created: 'attached',
mounted: 'ready',
destroyed: 'detached',
relations: 'relations',
destroyed: 'detached',
classes: 'externalClasses'
});
const { relation } = vantOptions;
if (relation) {
options.relations = Object.assign(options.relations || {}, {
[`../${relation.name}/index`]: relation
});
}
// add default externalClasses
options.externalClasses = options.externalClasses || [];
options.externalClasses.push('custom-class');
@ -26,7 +34,7 @@ function VantComponent(sfc) {
options.behaviors = options.behaviors || [];
options.behaviors.push(basic);
// map field to form-field behavior
if (sfc.field) {
if (vantOptions.field) {
options.behaviors.push('wx://form-field');
}
// add default options
@ -34,7 +42,7 @@ function VantComponent(sfc) {
multipleSlots: true,
addGlobalClass: true
};
observe(sfc, options);
observe(vantOptions, options);
Component(options);
}
export { VantComponent };

32
dist/dialog/index.js vendored
View File

@ -1,25 +1,15 @@
import { VantComponent } from '../common/component';
import { openType } from '../mixins/open-type';
VantComponent({
mixins: [openType],
props: {
show: Boolean,
title: String,
message: String,
useSlot: Boolean,
asyncClose: Boolean,
showCancelButton: Boolean,
confirmButtonOpenType: String,
show: {
type: Boolean,
observer(show) {
if (!show) {
this.setData({
loading: {
confirm: false,
cancel: false
}
});
}
}
},
zIndex: {
type: Number,
value: 100
@ -51,6 +41,18 @@ VantComponent({
cancel: false
}
},
watch: {
show(show) {
if (!show) {
this.setData({
loading: {
confirm: false,
cancel: false
}
});
}
}
},
methods: {
onConfirm() {
this.handleAction('confirm');
@ -70,7 +72,9 @@ VantComponent({
this.onClose(action);
},
close() {
this.setData({ show: false });
this.setData({
show: false
});
},
onClose(action) {
if (!this.data.asyncClose) {

View File

@ -37,6 +37,11 @@
custom-class="van-dialog__confirm"
open-type="{{ confirmButtonOpenType }}"
bind:click="onConfirm"
bindcontact="bindContact"
bindgetuserinfo="bindGetUserInfo"
bindgetphonenumber="bindGetPhoneNumber"
binderror="bindError"
bindopensetting="bindOpenSetting"
>
{{ confirmButtonText }}
</van-button>

71
dist/mixins/button.js vendored
View File

@ -1,50 +1,27 @@
export const button = Behavior({
properties: {
loading: Boolean,
openType: String,
appParameter: String,
sendMessageTitle: String,
sendMessagePath: String,
sendMessageImg: String,
showMessageCard: String,
hoverStopPropagation: Boolean,
hoverStartTime: {
type: Number,
value: 20
},
hoverStayTime: {
type: Number,
value: 70
},
lang: {
type: String,
value: 'en'
},
sessionFrom: {
type: String,
value: ''
properties: {
id: String,
appParameter: String,
sendMessageTitle: String,
sendMessagePath: String,
sendMessageImg: String,
showMessageCard: String,
hoverStopPropagation: Boolean,
hoverStartTime: {
type: Number,
value: 20
},
hoverStayTime: {
type: Number,
value: 70
},
lang: {
type: String,
value: 'en'
},
sessionFrom: {
type: String,
value: ''
}
}
},
methods: {
bindgetuserinfo(event = {}) {
this.$emit('getuserinfo', event.detail);
},
bindcontact(event = {}) {
this.$emit('contact', event.detail);
},
bindgetphonenumber(event = {}) {
this.$emit('getphonenumber', event.detail);
},
bindopensetting(event = {}) {
this.$emit('opensetting', event.detail);
},
binderror(event = {}) {
this.$emit('error', event.detail);
}
}
});

View File

@ -1,10 +1,25 @@
import { behavior } from './behavior';
import { observeProps } from './props';
export function observe(sfc, options) {
if (sfc.computed) {
export function observe(vantOptions, options) {
const { watch, computed } = vantOptions;
if (watch) {
const props = options.properties || {};
Object.keys(watch).forEach(key => {
if (key in props) {
let prop = props[key];
if (prop === null || !prop.type) {
prop = { type: prop };
}
prop.observer = watch[key];
props[key] = prop;
}
});
options.properties = props;
}
if (computed) {
options.behaviors.push(behavior);
options.methods = options.methods || {};
options.methods.$options = () => sfc;
options.methods.$options = () => vantOptions;
if (options.properties) {
observeProps(options.properties);
}

22
dist/mixins/open-type.js vendored Normal file
View File

@ -0,0 +1,22 @@
export const openType = Behavior({
properties: {
openType: String
},
methods: {
bindGetUserInfo(event) {
this.$emit('getuserinfo', event.detail);
},
bindContact(event) {
this.$emit('contact', event.detail);
},
bindGetPhoneNumber(event) {
this.$emit('getphonenumber', event.detail);
},
bindOpenSetting(event) {
this.$emit('opensetting', event.detail);
},
bindError(event) {
this.$emit('error', event.detail);
}
}
});

37
dist/mixins/touch.js vendored
View File

@ -1,22 +1,21 @@
export const touch = Behavior({
methods: {
touchStart(event) {
this.direction = '';
this.deltaX = 0;
this.deltaY = 0;
this.offsetX = 0;
this.offsetY = 0;
this.startX = event.touches[0].clientX;
this.startY = event.touches[0].clientY;
},
touchMove(event) {
const touch = event.touches[0];
this.deltaX = touch.clientX - this.startX;
this.deltaY = touch.clientY - this.startY;
this.offsetX = Math.abs(this.deltaX);
this.offsetY = Math.abs(this.deltaY);
this.direction = this.offsetX > this.offsetY ? 'horizontal' : this.offsetX < this.offsetY ? 'vertical' : '';
methods: {
touchStart(event) {
this.direction = '';
this.deltaX = 0;
this.deltaY = 0;
this.offsetX = 0;
this.offsetY = 0;
this.startX = event.touches[0].clientX;
this.startY = event.touches[0].clientY;
},
touchMove(event) {
const touch = event.touches[0];
this.deltaX = touch.clientX - this.startX;
this.deltaY = touch.clientY - this.startY;
this.offsetX = Math.abs(this.deltaX);
this.offsetY = Math.abs(this.deltaY);
this.direction = this.offsetX > this.offsetY ? 'horizontal' : this.offsetX < this.offsetY ? 'vertical' : '';
}
}
}
});

View File

@ -1,54 +1,52 @@
export const transition = function(showDefaultValue) {
return Behavior({
properties: {
customStyle: String,
show: {
value: showDefaultValue,
type: Boolean,
observer(value) {
if (value) {
this.show();
} else {
this.setData({
type: 'leave'
});
}
}
},
duration: {
type: Number,
value: 300
}
},
data: {
type: '',
inited: false,
display: false
},
attached() {
if (this.data.show) {
this.show();
}
},
methods: {
show() {
this.setData({
inited: true,
display: true,
type: 'enter'
});
},
onAnimationEnd() {
if (!this.data.show) {
this.setData({
export const transition = function (showDefaultValue) {
return Behavior({
properties: {
customStyle: String,
show: {
type: Boolean,
value: showDefaultValue,
observer: 'observeShow'
},
duration: {
type: Number,
value: 300
}
},
data: {
type: '',
inited: false,
display: false
});
},
attached() {
if (this.data.show) {
this.show();
}
},
methods: {
observeShow(value) {
if (value) {
this.show();
}
else {
this.setData({
type: 'leave'
});
}
},
show() {
this.setData({
inited: true,
display: true,
type: 'enter'
});
},
onAnimationEnd() {
if (!this.data.show) {
this.setData({
display: false
});
}
}
}
}
}
});
});
};

40
dist/nav-bar/index.js vendored
View File

@ -1,27 +1,23 @@
import { VantComponent } from '../common/component';
VantComponent({
classes: ['title-class'],
props: {
title: String,
leftText: String,
rightText: String,
leftArrow: Boolean,
fixed: Boolean,
zIndex: {
type: Number,
value: 1
}
},
methods: {
onClickLeft() {
this.$emit('click-left');
classes: ['title-class'],
props: {
title: String,
leftText: String,
rightText: String,
leftArrow: Boolean,
fixed: Boolean,
zIndex: {
type: Number,
value: 1
}
},
onClickRight() {
this.$emit('click-right');
methods: {
onClickLeft() {
this.$emit('click-left');
},
onClickRight() {
this.$emit('click-right');
}
}
}
});

View File

@ -1,159 +1,142 @@
import { VantComponent } from '../common/component';
const FONT_COLOR = '#f60';
const BG_COLOR = '#fff7cc';
VantComponent({
props: {
text: {
type: String,
value: '',
observer() {
this.setData({}, this.init);
}
},
mode: {
type: String,
value: ''
},
url: {
type: String,
value: ''
},
openType: {
type: String,
value: 'navigate'
},
delay: {
type: Number,
value: 0
},
speed: {
type: Number,
value: 50
},
scrollable: {
type: Boolean,
value: true
},
leftIcon: {
type: String,
value: ''
},
color: {
type: String,
value: FONT_COLOR
},
backgroundColor: {
type: String,
value: BG_COLOR
}
},
data: {
show: true,
hasRightIcon: false,
width: undefined,
wrapWidth: undefined,
elapse: undefined,
animation: null,
resetAnimation: null,
timer: null
},
created() {
if (this.data.mode) {
this.setData({
hasRightIcon: true
});
}
},
destroyed() {
const { timer } = this.data;
timer && clearTimeout(timer);
},
methods: {
init() {
this.getRect('.van-notice-bar__content').then(rect => {
if (!rect || !rect.width) {
return;
props: {
text: {
type: String,
value: ''
},
mode: {
type: String,
value: ''
},
url: {
type: String,
value: ''
},
openType: {
type: String,
value: 'navigate'
},
delay: {
type: Number,
value: 0
},
speed: {
type: Number,
value: 50
},
scrollable: {
type: Boolean,
value: true
},
leftIcon: {
type: String,
value: ''
},
color: {
type: String,
value: FONT_COLOR
},
backgroundColor: {
type: String,
value: BG_COLOR
}
this.setData({
width: rect.width
});
this.getRect('.van-notice-bar__content-wrap').then(rect => {
if (!rect || !rect.width) {
return;
}
const wrapWidth = rect.width;
const {
width, speed, scrollable, delay
} = this.data;
if (scrollable && wrapWidth < width) {
const elapse = width / speed * 1000;
const animation = wx.createAnimation({
duration: elapse,
timeingFunction: 'linear',
delay
});
const resetAnimation = wx.createAnimation({
duration: 0,
timeingFunction: 'linear'
});
this.setData({
elapse,
wrapWidth,
animation,
resetAnimation
}, () => {
this.scroll();
});
}
});
});
},
scroll() {
const {
animation, resetAnimation, wrapWidth, elapse, speed
} = this.data;
resetAnimation.translateX(wrapWidth).step();
const animationData = animation.translateX(-(elapse * speed) / 1000).step();
this.setData({
animationData: resetAnimation.export()
});
setTimeout(() => {
this.setData({
animationData: animationData.export()
});
}, 100);
const timer = setTimeout(() => {
this.scroll();
}, elapse);
this.setData({
timer
});
},
onClickIcon() {
const { timer } = this.data;
timer && clearTimeout(timer);
this.setData({
show: false,
data: {
show: true,
hasRightIcon: false,
width: undefined,
wrapWidth: undefined,
elapse: undefined,
animation: null,
resetAnimation: null,
timer: null
});
},
onClick(event) {
this.$emit('click', event);
watch: {
text() {
this.setData({}, this.init);
}
},
created() {
if (this.data.mode) {
this.setData({
hasRightIcon: true
});
}
},
destroyed() {
const { timer } = this.data;
timer && clearTimeout(timer);
},
methods: {
init() {
this.getRect('.van-notice-bar__content').then(rect => {
if (!rect || !rect.width) {
return;
}
this.setData({
width: rect.width
});
this.getRect('.van-notice-bar__content-wrap').then(rect => {
if (!rect || !rect.width) {
return;
}
const wrapWidth = rect.width;
const { width, speed, scrollable, delay } = this.data;
if (scrollable && wrapWidth < width) {
const elapse = width / speed * 1000;
const animation = wx.createAnimation({
duration: elapse,
timeingFunction: 'linear',
delay
});
const resetAnimation = wx.createAnimation({
duration: 0,
timeingFunction: 'linear'
});
this.setData({
elapse,
wrapWidth,
animation,
resetAnimation
}, () => {
this.scroll();
});
}
});
});
},
scroll() {
const { animation, resetAnimation, wrapWidth, elapse, speed } = this.data;
resetAnimation.translateX(wrapWidth).step();
const animationData = animation.translateX(-(elapse * speed) / 1000).step();
this.setData({
animationData: resetAnimation.export()
});
setTimeout(() => {
this.setData({
animationData: animationData.export()
});
}, 100);
const timer = setTimeout(() => {
this.scroll();
}, elapse);
this.setData({
timer
});
},
onClickIcon() {
const { timer } = this.data;
timer && clearTimeout(timer);
this.setData({
show: false,
timer: null
});
},
onClick(event) {
this.$emit('click', event);
}
}
}
});

71
dist/notify/index.js vendored
View File

@ -1,43 +1,38 @@
import { VantComponent } from '../common/component';
VantComponent({
props: {
text: String,
color: {
type: String,
value: '#fff'
props: {
text: String,
color: {
type: String,
value: '#fff'
},
backgroundColor: {
type: String,
value: '#e64340'
},
duration: {
type: Number,
value: 3000
}
},
backgroundColor: {
type: String,
value: '#e64340'
},
duration: {
type: Number,
value: 3000
methods: {
show() {
const { duration } = this.data;
clearTimeout(this.timer);
this.setData({
show: true
});
if (duration > 0 && duration !== Infinity) {
this.timer = setTimeout(() => {
this.hide();
}, duration);
}
},
hide() {
clearTimeout(this.timer);
this.setData({
show: false
});
}
}
},
methods: {
show() {
const { duration } = this.data;
clearTimeout(this.timer);
this.setData({
show: true
});
if (duration > 0 && duration !== Infinity) {
this.timer = setTimeout(() => {
this.hide();
}, duration);
}
},
hide() {
clearTimeout(this.timer);
this.setData({
show: false
});
}
}
});

30
dist/notify/notify.js vendored
View File

@ -1,25 +1,19 @@
import { isObj } from '../common/utils';
const defaultOptions = {
selector: '#van-notify',
duration: 3000
selector: '#van-notify',
duration: 3000
};
function parseOptions(text) {
return isObj(text) ? text : { text };
return isObj(text) ? text : { text };
}
export default function Notify(options = {}) {
const pages = getCurrentPages();
const ctx = pages[pages.length - 1];
options = Object.assign({}, defaultOptions, parseOptions(options));
const el = ctx.selectComponent(options.selector);
delete options.selector;
if (el) {
el.setData(options);
el.show();
}
const pages = getCurrentPages();
const ctx = pages[pages.length - 1];
options = Object.assign({}, defaultOptions, parseOptions(options));
const el = ctx.selectComponent(options.selector);
delete options.selector;
if (el) {
el.setData(options);
el.show();
}
}

33
dist/overlay/index.js vendored
View File

@ -1,22 +1,19 @@
import { VantComponent } from '../common/component';
VantComponent({
props: {
show: Boolean,
mask: Boolean,
customStyle: String,
zIndex: {
type: Number,
value: 1
}
},
methods: {
onClick() {
this.$emit('click');
props: {
show: Boolean,
mask: Boolean,
customStyle: String,
zIndex: {
type: Number,
value: 1
}
},
// for prevent touchmove
noop() {}
}
methods: {
onClick() {
this.$emit('click');
},
// for prevent touchmove
noop() { }
}
});

18
dist/panel/index.js vendored
View File

@ -1,13 +1,11 @@
import { VantComponent } from '../common/component';
VantComponent({
classes: ['footer-class'],
props: {
desc: String,
title: String,
status: String,
headerClass: String,
useFooterSlot: Boolean
}
classes: ['footer-class'],
props: {
desc: String,
title: String,
status: String,
headerClass: String,
useFooterSlot: Boolean
}
});

60
dist/popup/index.js vendored
View File

@ -1,38 +1,34 @@
import { VantComponent } from '../common/component';
import { transition } from '../mixins/transition';
VantComponent({
mixins: [transition(false)],
props: {
transition: String,
customStyle: String,
overlayStyle: String,
zIndex: {
type: Number,
value: 100
mixins: [transition(false)],
props: {
transition: String,
customStyle: String,
overlayStyle: String,
zIndex: {
type: Number,
value: 100
},
overlay: {
type: Boolean,
value: true
},
closeOnClickOverlay: {
type: Boolean,
value: true
},
position: {
type: String,
value: 'center'
}
},
overlay: {
type: Boolean,
value: true
},
closeOnClickOverlay: {
type: Boolean,
value: true
},
position: {
type: String,
value: 'center'
methods: {
onClickOverlay() {
this.$emit('click-overlay');
if (this.data.closeOnClickOverlay) {
this.$emit('close');
}
}
}
},
methods: {
onClickOverlay() {
this.$emit('click-overlay');
if (this.data.closeOnClickOverlay) {
this.$emit('close');
}
}
}
});

148
dist/progress/index.js vendored
View File

@ -1,104 +1,64 @@
import { VantComponent } from '../common/component';
VantComponent({
props: {
inactive: {
type: Boolean,
observer() {
this.setPivotStyle();
this.setPortionStyle();
}
props: {
inactive: Boolean,
percentage: Number,
pivotText: String,
pivotColor: String,
showPivot: {
type: Boolean,
value: true
},
color: {
type: String,
value: '#38f'
},
textColor: {
type: String,
value: '#fff'
}
},
pivotColor: {
type: String,
observer: 'setPivotStyle'
data: {
pivotWidth: 0,
progressWidth: 0
},
percentage: {
type: Number,
observer() {
this.setText();
this.setPortionStyle();
}
watch: {
pivotText: 'getWidth',
showPivot: 'getWidth'
},
showPivot: {
type: Boolean,
value: true,
observer: 'getWidth'
computed: {
portionStyle() {
const width = (this.data.progressWidth - this.data.pivotWidth) * this.data.percentage / 100 + 'px';
const background = this.getCurrentColor();
return `width: ${width}; background: ${background}; `;
},
pivotStyle() {
const color = this.data.textColor;
const background = this.data.pivotColor || this.getCurrentColor();
return `color: ${color}; background: ${background}`;
},
text() {
return this.data.pivotText || this.data.percentage + '%';
}
},
pivotText: {
type: String,
observer() {
this.setText();
mounted() {
this.getWidth();
}
},
color: {
type: String,
value: '#38f',
observer() {
this.setPivotStyle();
this.setPortionStyle();
}
},
textColor: {
type: String,
value: '#fff',
observer: 'setPivotStyle'
methods: {
getCurrentColor() {
return this.data.inactive ? '#cacaca' : this.data.color;
},
getWidth() {
this.getRect('.van-progress').then(rect => {
this.setData({
progressWidth: rect.width
});
});
this.getRect('.van-progress__pivot').then(rect => {
this.setData({
pivotWidth: rect.width || 0
});
});
}
}
},
data: {
pivotWidth: 0,
progressWidth: 0
},
mounted() {
this.setText();
this.setPivotStyle();
this.getWidth();
},
methods: {
getCurrentColor() {
return this.data.inactive ? '#cacaca' : this.data.color;
},
setText() {
this.setData({
text: this.data.pivotText || this.data.percentage + '%'
});
},
setPortionStyle() {
const width = (this.data.progressWidth - this.data.pivotWidth) * this.data.percentage / 100 + 'px';
const background = this.getCurrentColor();
this.setData({
portionStyle: `width: ${width}; background: ${background}; `
});
},
setPivotStyle() {
const color = this.data.textColor;
const background = this.data.pivotColor || this.getCurrentColor();
this.setData({
pivotStyle: `color: ${color}; background: ${background}`
});
},
getWidth() {
this.getRect('.van-progress').then(rect => {
this.setData({
progressWidth: rect.width
});
this.setPortionStyle();
});
this.getRect('.van-progress__pivot').then(rect => {
this.setData({
pivotWidth: rect.width || 0
});
this.setPortionStyle();
});
}
}
});

View File

@ -1,37 +1,32 @@
import { VantComponent } from '../common/component';
VantComponent({
relations: {
'../radio/index': {
type: 'descendant',
linked(target) {
const { value, disabled } = this.data;
target.setData({
value: value,
disabled: disabled || target.data.disabled
});
}
}
},
props: {
value: {
type: null,
observer(value) {
const children = this.getRelationNodes('../radio/index');
children.forEach(child => {
child.setData({ value });
});
}
relation: {
name: 'radio',
type: 'descendant',
linked(target) {
const { value, disabled } = this.data;
target.setData({
value: value,
disabled: disabled || target.data.disabled
});
}
},
disabled: {
type: Boolean,
observer(disabled) {
const children = this.getRelationNodes('../radio/index');
children.forEach(child => {
child.setData({ disabled: disabled || children.data.disabled });
});
}
props: {
value: null,
disabled: Boolean
},
watch: {
value(value) {
const children = this.getRelationNodes('../radio/index');
children.forEach(child => {
child.setData({ value });
});
},
disabled(disabled) {
const children = this.getRelationNodes('../radio/index');
children.forEach(child => {
child.setData({ disabled: disabled || child.data.disabled });
});
}
}
}
});

77
dist/radio/index.js vendored
View File

@ -1,49 +1,40 @@
import { VantComponent } from '../common/component';
VantComponent({
relations: {
'../radio-group/index': {
type: 'ancestor'
}
},
classes: ['icon-class', 'label-class'],
props: {
name: null,
value: null,
disabled: Boolean,
labelDisabled: Boolean,
labelPosition: String
},
computed: {
iconClass() {
const { disabled, name, value } = this.data;
return this.classNames('van-radio__icon', {
'van-radio__icon--disabled': disabled,
'van-radio__icon--checked': !disabled && name === value,
'van-radio__icon--check': !disabled && name !== value
});
}
},
methods: {
emitChange(value) {
const parent = this.getRelationNodes('../radio-group/index')[0];
(parent || this).$emit('input', value);
(parent || this).$emit('change', value);
relation: {
name: 'radio-group',
type: 'ancestor'
},
onChange(event) {
const { value } = event.detail;
this.emitChange(value);
classes: ['icon-class', 'label-class'],
props: {
name: null,
value: null,
disabled: Boolean,
labelDisabled: Boolean,
labelPosition: String
},
onClickLabel() {
if (!this.data.disabled && !this.data.labelDisabled) {
this.emitChange(this.data.name);
}
computed: {
iconClass() {
const { disabled, name, value } = this.data;
return this.classNames('van-radio__icon', {
'van-radio__icon--disabled': disabled,
'van-radio__icon--checked': !disabled && name === value,
'van-radio__icon--check': !disabled && name !== value
});
}
},
methods: {
emitChange(value) {
const instance = this.getRelationNodes('../radio-group/index')[0] || this;
instance.$emit('input', value);
instance.$emit('change', value);
},
onChange(event) {
this.emitChange(event.detail.value);
},
onClickLabel() {
if (!this.data.disabled && !this.data.labelDisabled) {
this.emitChange(this.data.name);
}
}
}
}
});

67
dist/row/index.js vendored
View File

@ -1,41 +1,36 @@
import { VantComponent } from '../common/component';
VantComponent({
relations: {
'../col/index': {
type: 'descendant',
linked(target) {
if (this.data.gutter) {
target.setGutter(this.data.gutter);
relation: {
name: 'col',
type: 'descendant',
linked(target) {
if (this.data.gutter) {
target.setGutter(this.data.gutter);
}
}
},
props: {
gutter: Number
},
watch: {
gutter: 'setGutter'
},
mounted() {
if (this.data.gutter) {
this.setGutter();
}
},
methods: {
setGutter() {
const { gutter } = this.data;
const margin = `-${Number(gutter) / 2}px`;
const style = gutter
? `margin-right: ${margin}; margin-left: ${margin};`
: '';
this.setData({ style });
this.getRelationNodes('../col/index').forEach(col => {
col.setGutter(this.data.gutter);
});
}
}
}
},
props: {
gutter: {
type: Number,
observer: 'setGutter'
}
},
mounted() {
if (this.data.gutter) {
this.setGutter();
}
},
methods: {
setGutter() {
const { gutter } = this.data;
const margin = `-${Number(gutter) / 2}px`;
const style = gutter ? `margin-right: ${margin}; margin-left: ${margin};` : '';
this.setData({ style });
this.getRelationNodes('../col/index').forEach((col) => {
col.setGutter(this.data.gutter);
});
}
}
});

83
dist/search/index.js vendored
View File

@ -1,49 +1,44 @@
import { VantComponent } from '../common/component';
VantComponent({
field: true,
classes: ['cancel-class'],
props: {
focus: Boolean,
disabled: Boolean,
readonly: Boolean,
showAction: Boolean,
useActionSlot: Boolean,
placeholder: String,
background: {
type: String,
value: '#f2f2f2'
field: true,
classes: ['cancel-class'],
props: {
focus: Boolean,
disabled: Boolean,
readonly: Boolean,
showAction: Boolean,
useActionSlot: Boolean,
placeholder: String,
background: {
type: String,
value: '#f2f2f2'
},
maxlength: {
type: Number,
value: -1
}
},
maxlength: {
type: Number,
value: -1
data: {
value: ''
},
methods: {
onChange(event) {
this.setData({ value: event.detail });
this.$emit('change', event.detail);
},
onCancel() {
this.setData({ value: '' });
this.$emit('cancel');
this.$emit('change', '');
},
onSearch() {
this.$emit('search', this.data.value);
},
onFocus() {
this.$emit('focus');
},
onBlur() {
this.$emit('blur');
}
}
},
methods: {
onChange(event) {
this.setData({ value: event.detail });
this.$emit('change', event.detail);
},
onCancel() {
this.setData({ value: '' });
this.$emit('cancel');
this.$emit('change', '');
},
onSearch() {
this.$emit('search', this.data.value);
},
onFocus() {
this.$emit('focus');
},
onBlur() {
this.$emit('blur');
}
}
});

146
dist/slider/index.js vendored
View File

@ -1,85 +1,75 @@
import { VantComponent } from '../common/component';
import { touch } from '../mixins/touch';
VantComponent({
mixins: [touch],
props: {
disabled: Boolean,
max: {
type: Number,
value: 100
mixins: [touch],
props: {
disabled: Boolean,
max: {
type: Number,
value: 100
},
min: {
type: Number,
value: 0
},
step: {
type: Number,
value: 1
},
value: {
type: Number,
value: 0
},
barHeight: {
type: String,
value: '2px'
}
},
min: {
type: Number,
value: 0
created() {
this.updateValue(this.data.value);
},
step: {
type: Number,
value: 1
},
value: {
type: Number,
value: 0
},
barHeight: {
type: String,
value: '2px'
methods: {
onTouchStart(event) {
if (this.data.disabled)
return;
this.touchStart(event);
this.startValue = this.format(this.data.value);
},
onTouchMove(event) {
if (this.data.disabled)
return;
this.touchMove(event);
this.getRect('.van-slider').then(rect => {
const diff = this.deltaX / rect.width * 100;
this.updateValue(this.startValue + diff);
});
},
onTouchEnd() {
if (this.data.disabled)
return;
this.updateValue(this.data.value, true);
},
onClick(event) {
if (this.data.disabled)
return;
this.getRect(rect => {
const value = (event.detail.x - rect.left) / rect.width * 100;
this.updateValue(value, true);
});
},
updateValue(value, end) {
value = this.format(value);
this.setData({
value,
barStyle: `width: ${value}%; height: ${this.data.barHeight};`
});
if (end) {
this.$emit('change', value);
}
},
format(value) {
const { max, min, step } = this.data;
return Math.round(Math.max(min, Math.min(value, max)) / step) * step;
}
}
},
created() {
this.updateValue(this.data.value);
},
methods: {
onTouchStart(event) {
if (this.data.disabled) return;
this.touchStart(event);
this.startValue = this.format(this.data.value);
},
onTouchMove(event) {
if (this.data.disabled) return;
this.touchMove(event);
this.getRect('.van-slider').then(rect => {
const diff = this.deltaX / rect.width * 100;
this.updateValue(this.startValue + diff);
});
},
onTouchEnd() {
if (this.data.disabled) return;
this.updateValue(this.data.value, true);
},
onClick(event) {
if (this.data.disabled) return;
this.getRect(rect => {
const value = (event.detail.x - rect.left) / rect.width * 100;
this.updateValue(value, true);
});
},
updateValue(value, end) {
value = this.format(value);
this.setData({
value,
barStyle: `width: ${value}%; height: ${this.data.barHeight};`
});
if (end) {
this.$emit('change', value);
}
},
format(value) {
const { max, min, step } = this.data;
return Math.round(Math.max(min, Math.min(value, max)) / step) * step;
}
}
});

136
dist/stepper/index.js vendored
View File

@ -1,82 +1,72 @@
import { VantComponent } from '../common/component';
// Note that the bitwise operators and shift operators operate on 32-bit ints
// so in that case, the max safe integer is 2^31-1, or 2147483647
const MAX = 2147483647;
VantComponent({
field: true,
classes: [
'input-class',
'plus-class',
'minus-class'
],
props: {
integer: Boolean,
disabled: Boolean,
disableInput: Boolean,
min: {
type: null,
value: 1
field: true,
classes: [
'input-class',
'plus-class',
'minus-class'
],
props: {
integer: Boolean,
disabled: Boolean,
disableInput: Boolean,
min: {
type: null,
value: 1
},
max: {
type: null,
value: MAX
},
step: {
type: null,
value: 1
}
},
max: {
type: null,
value: MAX
data: {
value: 0
},
step: {
type: null,
value: 1
created() {
this.setData({
value: this.range(this.data.value)
});
},
methods: {
// limit value range
range(value) {
return Math.max(Math.min(this.data.max, value), this.data.min);
},
onInput(event) {
const { value = '' } = event.detail || {};
this.triggerInput(value);
},
onChange(type) {
if (this[`${type}Disabled`]) {
this.$emit('overlimit', type);
return;
}
const diff = type === 'minus' ? -this.data.step : +this.data.step;
const value = Math.round((this.data.value + diff) * 100) / 100;
this.triggerInput(this.range(value));
this.$emit(type);
},
onBlur(event) {
const value = this.range(this.data.value);
this.triggerInput(value);
this.$emit('blur', event);
},
onMinus() {
this.onChange('minus');
},
onPlus() {
this.onChange('plus');
},
triggerInput(value) {
this.setData({ value });
this.$emit('change', value);
}
}
},
created() {
this.setData({
value: this.range(this.data.value)
});
},
methods: {
// limit value range
range(value) {
return Math.max(Math.min(this.data.max, value), this.data.min);
},
onInput(event) {
const { value = '' } = event.detail || {};
this.triggerInput(value);
},
onChange(type) {
if (this[`${type}Disabled`]) {
this.$emit('overlimit', type);
return;
}
const diff = type === 'minus' ? -this.data.step : +this.data.step;
const value = Math.round((this.data.value + diff) * 100) / 100;
this.triggerInput(this.range(value));
this.$emit(type);
},
onBlur(event) {
const value = this.range(this.data.value);
this.triggerInput(value);
this.$emit('blur', event);
},
onMinus() {
this.onChange('minus');
},
onPlus() {
this.onChange('plus');
},
triggerInput(value) {
this.setData({ value });
this.$emit('change', value);
}
}
});

77
dist/steps/index.js vendored
View File

@ -1,49 +1,42 @@
import { VantComponent } from '../common/component';
VantComponent({
props: {
icon: String,
steps: {
type: Array,
observer: 'formatSteps'
props: {
icon: String,
steps: Array,
active: Number,
direction: {
type: String,
value: 'horizontal'
},
activeColor: {
type: String,
value: '#06bf04'
}
},
active: {
type: Number,
observer: 'formatSteps'
watch: {
steps: 'formatSteps',
active: 'formatSteps'
},
direction: {
type: String,
value: 'horizontal'
created() {
this.formatSteps();
},
activeColor: {
type: String,
value: '#06bf04'
methods: {
formatSteps() {
const { steps } = this.data;
steps.forEach((step, index) => {
step.status = this.getStatus(index);
});
this.setData({ steps });
},
getStatus(index) {
const { active } = this.data;
if (index < active) {
return 'finish';
}
else if (index === active) {
return 'process';
}
return '';
}
}
},
created() {
this.formatSteps();
},
methods: {
formatSteps() {
const { steps } = this.data;
steps.forEach((step, index) => {
step.status = this.getStatus(index);
});
this.setData({ steps });
},
getStatus(index) {
const { active } = this.data;
if (index < active) {
return 'finish';
} else if (index === active) {
return 'process';
}
return '';
}
}
});

View File

@ -1,48 +1,42 @@
import { VantComponent } from '../common/component';
VantComponent({
classes: [
'bar-class',
'price-class',
'button-class'
],
props: {
tip: [String, Boolean],
type: Number,
price: null,
label: String,
loading: Boolean,
disabled: Boolean,
buttonText: String,
currency: {
type: String,
value: '¥'
classes: [
'bar-class',
'price-class',
'button-class'
],
props: {
tip: [String, Boolean],
type: Number,
price: null,
label: String,
loading: Boolean,
disabled: Boolean,
buttonText: String,
currency: {
type: String,
value: '¥'
},
buttonType: {
type: String,
value: 'danger'
}
},
buttonType: {
type: String,
value: 'danger'
}
},
computed: {
hasPrice() {
return typeof this.data.price === 'number';
computed: {
hasPrice() {
return typeof this.data.price === 'number';
},
priceStr() {
return (this.data.price / 100).toFixed(2);
},
tipStr() {
const { tip } = this.data;
return typeof tip === 'string' ? tip : '';
}
},
priceStr() {
return (this.data.price / 100).toFixed(2);
},
tipStr() {
const { tip } = this.data;
return typeof tip === 'string' ? tip : '';
methods: {
onSubmit(event) {
this.$emit('submit', event.detail);
}
}
},
methods: {
onSubmit(event) {
this.$emit('submit', event.detail);
}
}
});

View File

@ -1,32 +1,28 @@
import { VantComponent } from '../common/component';
VantComponent({
field: true,
props: {
title: String,
border: Boolean,
loading: Boolean,
disabled: Boolean,
checked: {
type: Boolean,
observer(value) {
this.setData({ value });
}
field: true,
props: {
title: String,
border: Boolean,
checked: Boolean,
loading: Boolean,
disabled: Boolean,
size: {
type: String,
value: '26px'
}
},
size: {
type: String,
value: '26px'
watch: {
checked(value) {
this.setData({ value });
}
},
created() {
this.setData({ value: this.data.checked });
},
methods: {
onChange(event) {
this.$emit('change', event.detail);
}
}
},
created() {
this.setData({ value: this.data.checked });
},
methods: {
onChange(event) {
this.$emit('change', event.detail);
}
}
});

57
dist/switch/index.js vendored
View File

@ -1,36 +1,31 @@
import { VantComponent } from '../common/component';
VantComponent({
field: true,
classes: ['node-class'],
props: {
loading: Boolean,
disabled: Boolean,
checked: {
type: Boolean,
observer(value) {
this.setData({ value });
}
field: true,
classes: ['node-class'],
props: {
checked: Boolean,
loading: Boolean,
disabled: Boolean,
size: {
type: String,
value: '30px'
}
},
size: {
type: String,
value: '30px'
watch: {
checked(value) {
this.setData({ value });
}
},
created() {
this.setData({ value: this.data.checked });
},
methods: {
onClick() {
if (!this.data.disabled && !this.data.loading) {
const checked = !this.data.checked;
this.$emit('input', checked);
this.$emit('change', checked);
}
}
}
},
created() {
this.setData({ value: this.data.checked });
},
methods: {
onClick() {
if (!this.data.disabled && !this.data.loading) {
const checked = !this.data.checked;
this.$emit('input', checked);
this.$emit('change', checked);
}
}
}
});

54
dist/tab/index.js vendored
View File

@ -1,36 +1,30 @@
import { VantComponent } from '../common/component';
VantComponent({
props: {
disabled: {
type: Boolean,
observer() {
const parent = this.getRelationNodes('../tabs/index')[0];
if (parent) {
parent.updateTabs();
}
}
relation: {
name: 'tabs',
type: 'ancestor'
},
title: {
type: String,
observer() {
const parent = this.getRelationNodes('../tabs/index')[0];
if (parent) {
parent.setLine();
parent.updateTabs();
props: {
title: String,
disabled: Boolean
},
data: {
inited: false,
active: false
},
watch: {
disabled() {
const parent = this.getRelationNodes('../tabs/index')[0];
if (parent) {
parent.updateTabs();
}
},
title() {
const parent = this.getRelationNodes('../tabs/index')[0];
if (parent) {
parent.setLine();
parent.updateTabs();
}
}
}
}
},
relations: {
'../tabs/index': {
type: 'ancestor'
}
},
data: {
inited: false,
active: false
}
});

View File

@ -1,37 +1,31 @@
import { VantComponent } from '../common/component';
VantComponent({
props: {
info: null,
icon: String,
dot: Boolean
},
relations: {
'../tabbar/index': {
type: 'ancestor'
}
},
data: {
active: false,
count: 0
},
methods: {
onClick() {
const parent = this.getRelationNodes('../tabbar/index')[0];
if (parent) {
parent.onChange(this);
}
this.$emit('click');
props: {
info: null,
icon: String,
dot: Boolean
},
setActive(data) {
const { active, count } = this.data;
if (active !== data.active || count !== data.count) {
this.setData(data);
}
relation: {
name: 'tabbar',
type: 'ancestor'
},
data: {
active: false,
count: 0
},
methods: {
onClick() {
const parent = this.getRelationNodes('../tabbar/index')[0];
if (parent) {
parent.onChange(this);
}
this.$emit('click');
},
setActive(data) {
const { active, count } = this.data;
if (active !== data.active || count !== data.count) {
this.setData(data);
}
}
}
}
});

117
dist/tabbar/index.js vendored
View File

@ -1,70 +1,61 @@
import { VantComponent } from '../common/component';
VantComponent({
props: {
active: {
type: Number,
observer(active) {
this.setData({ currentActive: active });
this.setActiveItem();
}
relation: {
name: 'tabbar-item',
type: 'descendant',
linked(target) {
this.data.items.push(target);
setTimeout(() => {
this.setActiveItem();
});
},
unlinked(target) {
this.data.items = this.data.items.filter(item => item !== target);
setTimeout(() => {
this.setActiveItem();
});
}
},
fixed: {
type: Boolean,
value: true
props: {
active: Number,
fixed: {
type: Boolean,
value: true
},
zIndex: {
type: Number,
value: 1
}
},
zIndex: {
type: Number,
value: 1
}
},
data: {
items: [],
currentActive: -1
},
created() {
this.setData({ currentActive: this.data.active });
},
relations: {
'../tabbar-item/index': {
type: 'descendant',
linked(target) {
this.data.items.push(target);
setTimeout(() => {
this.setActiveItem();
});
},
unlinked(target) {
this.data.items = this.data.items.filter(item => item !== target);
setTimeout(() => {
this.setActiveItem();
});
}
}
},
methods: {
setActiveItem() {
this.data.items.forEach((item, index) => {
item.setActive({
active: index === this.data.currentActive,
count: this.data.items.length
});
});
data: {
items: [],
currentActive: -1
},
onChange(child) {
const active = this.data.items.indexOf(child);
if (active !== this.data.currentActive && active !== -1) {
this.$emit('change', active);
this.setData({ currentActive: active });
this.setActiveItem();
}
watch: {
active(active) {
this.setData({ currentActive: active });
this.setActiveItem();
}
},
created() {
this.setData({ currentActive: this.data.active });
},
methods: {
setActiveItem() {
this.data.items.forEach((item, index) => {
item.setActive({
active: index === this.data.currentActive,
count: this.data.items.length
});
});
},
onChange(child) {
const active = this.data.items.indexOf(child);
if (active !== this.data.currentActive && active !== -1) {
this.$emit('change', active);
this.setData({ currentActive: active });
this.setActiveItem();
}
}
}
}
});

299
dist/tabs/index.js vendored
View File

@ -1,175 +1,154 @@
import { VantComponent } from '../common/component';
VantComponent({
relations: {
'../tab/index': {
type: 'descendant',
linked(child) {
this.data.tabs.push({
instance: child,
data: child.data
});
this.updateTabs();
},
unlinked(child) {
const tabs = this.data.tabs.filter(item => item.instance !== child);
this.setData({
tabs,
scrollable: tabs.length > this.data.swipeThreshold
});
this.setActiveTab();
}
}
},
props: {
color: {
type: String,
observer: 'setLine'
relation: {
name: 'tab',
type: 'descendant',
linked(child) {
this.data.tabs.push({
instance: child,
data: child.data
});
this.updateTabs();
},
unlinked(child) {
const tabs = this.data.tabs.filter(item => item.instance !== child);
this.setData({
tabs,
scrollable: tabs.length > this.data.swipeThreshold
});
this.setActiveTab();
}
},
lineWidth: {
type: Number,
observer: 'setLine'
props: {
color: String,
lineWidth: Number,
active: {
type: null,
value: 0
},
type: {
type: String,
value: 'line'
},
border: {
type: Boolean,
value: true
},
duration: {
type: Number,
value: 0.2
},
swipeThreshold: {
type: Number,
value: 4
}
},
active: {
type: null,
value: 0,
observer: 'setActiveTab'
data: {
tabs: [],
lineStyle: '',
scrollLeft: 0,
scrollable: false
},
type: {
type: String,
value: 'line'
watch: {
swipeThreshold() {
this.setData({
scrollable: this.data.tabs.length > this.data.swipeThreshold
});
},
color: 'setLine',
lineWidth: 'setLine',
active: 'setActiveTab'
},
border: {
type: Boolean,
value: true
mounted() {
this.setLine();
this.scrollIntoView();
},
duration: {
type: Number,
value: 0.2
},
swipeThreshold: {
type: Number,
value: 4,
observer() {
this.setData({
scrollable: this.data.tabs.length > this.data.swipeThreshold
});
}
}
},
data: {
tabs: [],
lineStyle: '',
scrollLeft: 0
},
mounted() {
this.setLine();
this.scrollIntoView();
},
methods: {
updateTabs() {
const { tabs } = this.data;
this.setData({
tabs,
scrollable: tabs.length > this.data.swipeThreshold
});
this.setActiveTab();
},
trigger(eventName, index) {
this.$emit(eventName, {
index,
title: this.data.tabs[index].data.title
});
},
onTap(event) {
const { index } = event.currentTarget.dataset;
if (this.data.tabs[index].data.disabled) {
this.trigger('disabled', index);
} else {
this.trigger('click', index);
this.setActive(index);
}
},
setActive(active) {
if (active !== this.data.active) {
this.trigger('change', active);
this.setData({ active });
this.setActiveTab();
}
},
setLine() {
if (this.data.type !== 'line') {
return;
}
this.getRect('.van-tab', true).then(rects => {
const rect = rects[this.data.active];
const width = this.data.lineWidth || rect.width;
let left = rects
.slice(0, this.data.active)
.reduce((prev, curr) => prev + curr.width, 0);
left += (rect.width - width) / 2;
this.setData({
lineStyle: `
methods: {
updateTabs() {
const { tabs } = this.data;
this.setData({
tabs,
scrollable: tabs.length > this.data.swipeThreshold
});
this.setActiveTab();
},
trigger(eventName, index) {
this.$emit(eventName, {
index,
title: this.data.tabs[index].data.title
});
},
onTap(event) {
const { index } = event.currentTarget.dataset;
if (this.data.tabs[index].data.disabled) {
this.trigger('disabled', index);
}
else {
this.trigger('click', index);
this.setActive(index);
}
},
setActive(active) {
if (active !== this.data.active) {
this.trigger('change', active);
this.setData({ active });
this.setActiveTab();
}
},
setLine() {
if (this.data.type !== 'line') {
return;
}
this.getRect('.van-tab', true).then(rects => {
const rect = rects[this.data.active];
const width = this.data.lineWidth || rect.width;
let left = rects
.slice(0, this.data.active)
.reduce((prev, curr) => prev + curr.width, 0);
left += (rect.width - width) / 2;
this.setData({
lineStyle: `
width: ${width}px;
background-color: ${this.data.color};
transform: translateX(${left}px);
transition-duration: ${this.data.duration}s;
`
});
});
},
setActiveTab() {
this.data.tabs.forEach((item, index) => {
const data = {
active: index === this.data.active
};
if (data.active) {
data.inited = true;
});
});
},
setActiveTab() {
this.data.tabs.forEach((item, index) => {
const data = {
active: index === this.data.active
};
if (data.active) {
data.inited = true;
}
if (data.active !== item.instance.data.active) {
item.instance.setData(data);
}
});
this.setLine();
this.scrollIntoView();
},
// scroll active tab into view
scrollIntoView(immediate) {
if (!this.data.scrollable) {
return;
}
this.getRect('.van-tab', true).then(tabRects => {
const tabRect = tabRects[this.data.active];
const offsetLeft = tabRects
.slice(0, this.data.active)
.reduce((prev, curr) => prev + curr.width, 0);
const tabWidth = tabRect.width;
this.getRect('.van-tabs__nav').then(navRect => {
const navWidth = navRect.width;
this.setData({
scrollLeft: offsetLeft - (navWidth - tabWidth) / 2
});
});
});
}
if (data.active !== item.instance.data.active) {
item.instance.setData(data);
}
});
this.setLine();
this.scrollIntoView();
},
// scroll active tab into view
scrollIntoView(immediate) {
if (!this.data.scrollable) {
return;
}
this.getRect('.van-tab', true).then(tabRects => {
const tabRect = tabRects[this.data.active];
const offsetLeft = tabRects
.slice(0, this.data.active)
.reduce((prev, curr) => prev + curr.width, 0);
const tabWidth = tabRect.width;
this.getRect('.van-tabs__nav').then(navRect => {
const navWidth = navRect.width;
this.setData({
scrollLeft: offsetLeft - (navWidth - tabWidth) / 2
});
});
});
}
}
});

11
dist/tag/index.js vendored
View File

@ -1,9 +1,8 @@
import { VantComponent } from '../common/component';
VantComponent({
props: {
type: String,
mark: Boolean,
plain: Boolean
}
props: {
type: String,
mark: Boolean,
plain: Boolean
}
});

61
dist/toast/index.js vendored
View File

@ -1,37 +1,34 @@
import { VantComponent } from '../common/component';
VantComponent({
props: {
show: Boolean,
mask: Boolean,
message: String,
forbidClick: Boolean,
zIndex: {
type: Number,
value: 1000
props: {
show: Boolean,
mask: Boolean,
message: String,
forbidClick: Boolean,
zIndex: {
type: Number,
value: 1000
},
type: {
type: String,
value: 'text'
},
loadingType: {
type: String,
value: 'circular'
},
position: {
type: String,
value: 'middle'
}
},
type: {
type: String,
value: 'text'
},
loadingType: {
type: String,
value: 'circular'
},
position: {
type: String,
value: 'middle'
methods: {
clear() {
this.setData({
show: false
});
},
// for prevent touchmove
noop() { }
}
},
methods: {
clear() {
this.setData({
show: false
});
},
// for prevent touchmove
noop() {}
}
});

94
dist/toast/toast.js vendored
View File

@ -1,72 +1,52 @@
import { isObj } from '../common/utils';
const defaultOptions = {
type: 'text',
mask: false,
message: '',
show: true,
zIndex: 1000,
duration: 3000,
position: 'middle',
forbidClick: false,
loadingType: 'circular',
selector: '#van-toast'
type: 'text',
mask: false,
message: '',
show: true,
zIndex: 1000,
duration: 3000,
position: 'middle',
forbidClick: false,
loadingType: 'circular',
selector: '#van-toast'
};
let queue = [];
let currentOptions = { ...defaultOptions };
let currentOptions = Object.assign({}, defaultOptions);
function parseOptions(message) {
return isObj(message) ? message : { message };
return isObj(message) ? message : { message };
}
function Toast(options = {}) {
options = {
...currentOptions,
...parseOptions(options)
};
const pages = getCurrentPages();
const ctx = pages[pages.length - 1];
const toast = ctx.selectComponent(options.selector);
delete options.selector;
queue.push(toast);
toast.setData(options);
clearTimeout(toast.timer);
if (options.duration > 0) {
toast.timer = setTimeout(() => {
toast.clear();
queue = queue.filter(item => item !== toast);
}, options.duration);
}
return toast;
const Toast = (options = {}) => {
options = Object.assign({}, currentOptions, parseOptions(options));
const pages = getCurrentPages();
const ctx = pages[pages.length - 1];
const toast = ctx.selectComponent(options.selector);
delete options.selector;
queue.push(toast);
toast.setData(options);
clearTimeout(toast.timer);
if (options.duration > 0) {
toast.timer = setTimeout(() => {
toast.clear();
queue = queue.filter(item => item !== toast);
}, options.duration);
}
return toast;
};
const createMethod = type => options => Toast({
type, ...parseOptions(options)
});
const createMethod = type => options => Toast(Object.assign({ type }, parseOptions(options)));
['loading', 'success', 'fail'].forEach(method => {
Toast[method] = createMethod(method);
Toast[method] = createMethod(method);
});
Toast.clear = all => {
queue.forEach(toast => {
toast.clear();
});
queue = [];
Toast.clear = () => {
queue.forEach(toast => {
toast.clear();
});
queue = [];
};
Toast.setDefaultOptions = options => {
Object.assign(currentOptions, options);
Object.assign(currentOptions, options);
};
Toast.resetDefaultOptions = () => {
currentOptions = { ...defaultOptions };
currentOptions = Object.assign({}, defaultOptions);
};
export default Toast;

View File

@ -1,13 +1,11 @@
import { VantComponent } from '../common/component';
import { transition } from '../mixins/transition';
VantComponent({
mixins: [transition(true)],
props: {
name: {
type: String,
value: 'fade'
mixins: [transition(true)],
props: {
name: {
type: String,
value: 'fade'
}
}
}
});

View File

@ -1,72 +1,63 @@
import { VantComponent } from '../common/component';
const ITEM_HEIGHT = 44;
VantComponent({
props: {
items: {
type: Array,
observer() {
this.updateSubItems();
this.updateMainHeight();
}
props: {
items: Array,
mainActiveIndex: {
type: Number,
value: 0
},
activeId: {
type: Number,
value: 0
},
maxHeight: {
type: Number,
value: 300
}
},
mainActiveIndex: {
type: Number,
value: 0,
observer: 'updateSubItems'
data: {
subItems: [],
mainHeight: 0,
itemHeight: 0
},
activeId: {
type: Number,
value: 0
watch: {
items() {
this.updateSubItems();
this.updateMainHeight();
},
maxHeight() {
this.updateItemHeight();
this.updateMainHeight();
},
mainActiveIndex: 'updateSubItems'
},
maxHeight: {
type: Number,
value: 300,
observer() {
this.updateItemHeight();
this.updateMainHeight();
}
methods: {
// 当一个子项被选择时
onSelectItem(event) {
this.$emit('click-item', event.currentTarget.dataset.item);
},
// 当一个导航被点击时
onClickNav(event) {
const { index } = event.currentTarget.dataset;
this.$emit('click-nav', { index });
},
// 更新子项列表
updateSubItems() {
const selectedItem = this.data.items[this.data.mainActiveIndex] || {};
this.setData({ subItems: selectedItem.children || [] });
this.updateItemHeight();
},
// 更新组件整体高度,根据最大高度和当前组件需要展示的高度来决定
updateMainHeight() {
const maxHeight = Math.max(this.data.items.length * ITEM_HEIGHT, this.data.subItems.length * ITEM_HEIGHT);
this.setData({ mainHeight: Math.min(maxHeight, this.data.maxHeight) });
},
// 更新子项列表高度,根据可展示的最大高度和当前子项列表的高度决定
updateItemHeight() {
this.setData({
itemHeight: Math.min(this.data.subItems.length * ITEM_HEIGHT, this.data.maxHeight)
});
}
}
},
data: {
subItems: [],
mainHeight: 0,
itemHeight: 0
},
methods: {
// 当一个子项被选择时
onSelectItem(event) {
this.$emit('click-item', event.currentTarget.dataset.item);
},
// 当一个导航被点击时
onClickNav(event) {
const { index } = event.currentTarget.dataset;
this.$emit('click-nav', { index });
},
// 更新子项列表
updateSubItems() {
const selectedItem = this.data.items[this.data.mainActiveIndex] || {};
this.setData({ subItems: selectedItem.children || [] });
this.updateItemHeight();
},
// 更新组件整体高度,根据最大高度和当前组件需要展示的高度来决定
updateMainHeight() {
const maxHeight = Math.max(this.data.items.length * ITEM_HEIGHT, this.data.subItems.length * ITEM_HEIGHT);
this.setData({ mainHeight: Math.min(maxHeight, this.data.maxHeight) });
},
// 更新子项列表高度,根据可展示的最大高度和当前子项列表的高度决定
updateItemHeight() {
this.setData({ itemHeight: Math.min(this.data.subItems.length * ITEM_HEIGHT, this.data.maxHeight) });
}
}
});