dvant
Version:
A Vue.js 2.0 Mobile UI at dawnwin modified from Youzan
221 lines (181 loc) • 6.15 kB
JavaScript
'use strict';
exports.__esModule = true;
var _utils = require('../utils');
var _raf = require('../utils/raf');
var _event = require('../utils/event');
var _node = require('../utils/node');
var _node2 = _interopRequireDefault(_node);
var _scroll = require('../utils/scroll');
var _scroll2 = _interopRequireDefault(_scroll);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
exports.default = (0, _utils.create)({
render: function render() {
var _vm = this;var _h = _vm.$createElement;var _c = _vm._self._c || _h;return _c('div', { staticClass: "van-tabs", class: "van-tabs--" + _vm.type }, [_c('div', { ref: "wrap", staticClass: "van-tabs__wrap", class: ["van-tabs__wrap--" + _vm.position, {
'van-tabs--scrollable': _vm.scrollable,
'van-hairline--top-bottom': _vm.type === 'line'
}] }, [_c('div', { ref: "nav", staticClass: "van-tabs__nav", class: "van-tabs__nav--" + _vm.type }, [_vm.type === 'line' ? _c('div', { staticClass: "van-tabs__nav-bar", style: _vm.navBarStyle }) : _vm._e(), _vm._l(_vm.tabs, function (tab, index) {
return _c('div', { key: index, ref: "tabs", refInFor: true, staticClass: "van-tab", class: {
'van-tab--active': index === _vm.curActive,
'van-tab--disabled': tab.disabled
}, on: { "click": function click($event) {
_vm.onClick(index);
} } }, [tab.$slots.title ? _c('van-node', { attrs: { "node": tab.$slots.title } }) : _c('span', { staticClass: "van-ellipsis" }, [_vm._v(_vm._s(tab.title))])], 1);
})], 2)]), _c('div', { staticClass: "van-tabs__content" }, [_vm._t("default")], 2)]);
},
name: 'van-tabs',
components: {
VanNode: _node2.default
},
props: {
sticky: Boolean,
active: {
type: [Number, String],
default: 0
},
type: {
type: String,
default: 'line'
},
duration: {
type: Number,
default: 0.2
},
swipeThreshold: {
type: Number,
default: 4
}
},
data: function data() {
return {
tabs: [],
position: 'content-top',
curActive: 0,
navBarStyle: {}
};
},
computed: {
// whether the nav is scrollable
scrollable: function scrollable() {
return this.tabs.length > this.swipeThreshold;
}
},
watch: {
active: function active(val) {
this.correctActive(val);
},
tabs: function tabs(_tabs) {
this.correctActive(this.curActive || this.active);
this.setNavBar();
},
curActive: function curActive() {
this.scrollIntoView();
this.setNavBar();
// scroll to correct position
if (this.position === 'page-top' || this.position === 'content-bottom') {
_scroll2.default.setScrollTop(this.scrollEl, _scroll2.default.getElementTop(this.$el));
}
},
sticky: function sticky(isSticky) {
this.scrollHandler(isSticky);
}
},
mounted: function mounted() {
var _this = this;
this.correctActive(this.active);
this.setNavBar();
this.$nextTick(function () {
if (_this.sticky) {
_this.scrollHandler(true);
}
_this.scrollIntoView();
});
},
beforeDestroy: function beforeDestroy() {
/* istanbul ignore next */
if (this.sticky) {
this.scrollHandler(false);
}
},
methods: {
// whether to bind sticky listener
scrollHandler: function scrollHandler(init) {
this.scrollEl = this.scrollEl || _scroll2.default.getScrollEventTarget(this.$el);
(init ? _event.on : _event.off)(this.scrollEl, 'scroll', this.onScroll, true);
if (init) {
this.onScroll();
}
},
// adjust tab position
onScroll: function onScroll() {
var scrollTop = _scroll2.default.getScrollTop(this.scrollEl);
var elTopToPageTop = _scroll2.default.getElementTop(this.$el);
var elBottomToPageTop = elTopToPageTop + this.$el.offsetHeight - this.$refs.wrap.offsetHeight;
if (scrollTop > elBottomToPageTop) {
this.position = 'content-bottom';
} else if (scrollTop > elTopToPageTop) {
this.position = 'page-top';
} else {
this.position = 'content-top';
}
},
// update nav bar style
setNavBar: function setNavBar() {
var _this2 = this;
this.$nextTick(function () {
if (!_this2.$refs.tabs) {
return;
}
var tab = _this2.$refs.tabs[_this2.curActive];
_this2.navBarStyle = {
width: (tab.offsetWidth || 0) + 'px',
transform: 'translate(' + (tab.offsetLeft || 0) + 'px, 0)',
transitionDuration: _this2.duration + 's'
};
});
},
// correct the value of active
correctActive: function correctActive(active) {
active = +active;
var exist = this.tabs.some(function (tab) {
return tab.index === active;
});
var defaultActive = (this.tabs[0] || {}).index || 0;
this.curActive = exist ? active : defaultActive;
},
// emit event when clicked
onClick: function onClick(index) {
if (this.tabs[index].disabled) {
this.$emit('disabled', index);
} else {
this.$emit('click', index);
this.curActive = index;
}
},
// scroll active tab into view
scrollIntoView: function scrollIntoView() {
if (!this.scrollable || !this.$refs.tabs) {
return;
}
var tab = this.$refs.tabs[this.curActive];
var nav = this.$refs.nav;
var scrollLeft = nav.scrollLeft,
navWidth = nav.offsetWidth;
var offsetLeft = tab.offsetLeft,
tabWidth = tab.offsetWidth;
this.scrollTo(nav, scrollLeft, offsetLeft - (navWidth - tabWidth) / 2);
},
// animate the scrollLeft of nav
scrollTo: function scrollTo(el, from, to) {
var count = 0;
var frames = Math.round(this.duration * 1000 / 16);
var animate = function animate() {
el.scrollLeft += (to - from) / frames;
/* istanbul ignore next */
if (++count < frames) {
(0, _raf.raf)(animate);
}
};
animate();
}
}
});