123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- <template>
- <view class="tm-segTabs d-inline-block relative ">
- <view class="tm-segTabs-wkbody fulled flex-start relative" :class="['pa-'+gutter]"
- :style="{width:width>0?width+'rpx':'auto'}">
- <view @click="clickItem(index, item)" :class="[
- `px-${margin[0]} py-${margin[1]}`,
- `text-size-${fontSize}`,
- `round-${round}`,
- active_index == index
- ? 'text-weight-b ' + (black_tmeme ? `text-grey-lighten-3 ` : `text-${color_tmeme}`)
- : black_tmeme
- ? `text-grey bk`
- : `text-${color}`
- ]" :id="'tm-segTabs-item-' + index" v-for="(item, index) in listData" :key="index"
- class="tm-segTabs-item flex-shrink flex-center" :style="{
- width:width_item+'px'
- }">
- <slot name="default"
- :item="{color:color_tmeme, data: item, index: index, isActive: active_index == index }">
- {{ returnKeyValue(item) }}
- </slot>
- </view>
- </view>
- <view :class="[black_tmeme ? 'grey-darken-5' : bgColor, `round-${round}`]"
- class="tm-segTabs-bg absolute l-0 t-0 fulled " :style="{ height: body_height + 'px' }">
- <view
- :class="[`shadow-${activeColor}-${shadow}`,black_tmeme ? 'grey-darken-3' : activeColor, `round-${round}`,aniOn?'aniOn':'',`mt-${gutter} ml-${gutter/2}`]"
- class="tm-segTabs-bg-bar relative"
- :style="{ width: `${active_barWidth}px`, height: `${active_barHeight}px`,transform: `translateX(${left}px)` }">
- </view>
- </view>
- </view>
- </template>
- <script>
- /**
- * 分段器选项卡
- * @property {Number} value = [] 默认0,当前激活的选项.
- * @property {Array} list = [] 默认数据,对象数组或者字符串数组
- * @property {String} rang-key = [] 默认text,list对象数组时取文本的字段名称
- * @property {String} color = [] 默认black,默认的文字颜色
- * @property {String} bg-color = [] 默认grey-lighten-4,默认的背景色
- * @property {String} active-font-color = [] 默认black,激活的文本色
- * @property {String} active-color = [] 默认black,激活项的背景色
- * @property {String} font-size = [] 默认 n,字号,xxs,xs,s,n,g,lg,xl
- * @property {Array} margin = [] 默认 [24,10],左右和上下的间距,调整它可以控制宽度和高度。
- * @property {Number} round = [] 默认4, 圆角
- * @property {Number} shadow = [] 默认4, 投影
- * @property {Number} gutter = [] 默认4, 四边的间隙
- * @property {Number} width = [] 默认0, 整体的宽度,默认不自动宽度,提供了后,项目内的宽度为均分此宽度。
- * @property {Boolean} black = [] 默认false, 是否暗黑模式
- * @property {Boolean} fllow-theme = [] 默认true, 是否跟随主题切换主色。
- */
- export default {
- name: 'tm-segTabs',
- props: {
- value: {
- type: Number,
- defalut: 0
- },
- list: {
- type: Array,
- default: () => []
- },
- //整体的宽度,不设置使用默认计算的宽度。
- width: {
- type: Number,
- default: 0
- },
- // 四周的间隙
- gutter: {
- type: Number,
- default: 4
- },
- shadow: {
- type: Number,
- default: 4
- },
- margin: {
- type: Array,
- default: () => [24, 10]
- },
- rangKey: {
- type: String,
- default: 'text'
- },
- color: {
- type: String,
- default: 'black'
- },
- bgColor: {
- type: String,
- default: 'grey-lighten-4'
- },
- activeFontColor: {
- type: String,
- default: 'black'
- },
- activeColor: {
- type: String,
- default: 'white'
- },
- fontSize: {
- type: String,
- default: 'n'
- },
- round: {
- type: String | Number,
- default: 4
- },
- // 跟随主题色的改变而改变。
- fllowTheme: {
- type: Boolean | String,
- default: true
- },
- black: {
- type: Boolean | String,
- default: null
- }
- },
- data() {
- return {
- body_height: 0,
- active_barHeight: 0,
- active_barWidth: 0,
- aniOn: false,
- left: 0,
- preventLeft: 0,
- width_item_w: 0,
- };
- },
- watch: {
- value(newValue, oldValue) {
- this.active_index = newValue;
- },
- list: {
- deep: true,
- async handler() {
- this.width_item = this.width;
- await this.setInits();
- }
- }
- },
- computed: {
- width_item: {
- get: function() {
- return this.width_item_w;
- },
- set: function(val) {
- if (val == 0) {
- this.width_item_w = 'auto'
- } else {
- this.width_item_w = (uni.upx2px(val) / this.list.length)
- }
- }
- },
- black_tmeme: function() {
- if (this.black !== null) return this.black;
- return this.$tm.vx.state().tmVuetify.black;
- },
- color_tmeme: function() {
- if (this.$tm.vx.state().tmVuetify.color !== null && this.$tm.vx.state().tmVuetify.color && this
- .fllowTheme) {
- return this.$tm.vx.state().tmVuetify.color;
- }
- return this.activeFontColor;
- },
- listData: function() {
- return this.list;
- },
- active_index: {
- get: function() {
- return this.value;
- },
- set: function(val) {
- this.active = val;
- this.$emit('input', val);
- this.$emit('update:value', val);
- // this.$emit('change', val);
- this.$nextTick(function() {
- this.setDefaultPos();
- });
- }
- }
- },
- created() {
- this.active_index = this.value;
- this.width_item = this.width;
- },
- mounted() {
- let t = this;
- uni.$tm.sleep(30).then(()=>{
- t.setInits();
-
- })
- },
- methods: {
- setInits() {
- let t = this;
- this.width_item = this.width;
- this.$nextTick(function() {
- uni.createSelectorQuery().in(t).select('.tm-segTabs-wkbody')
- .boundingClientRect().select('#tm-segTabs-item-' + this.active).boundingClientRect()
- .exec(function(tx) {
-
- let p = tx[0]
- if (!p) return;
- t.body_height = p.height;
- t.preventLeft = p.left;
- let p1 = tx[1]
- if (!p1) return;
- t.active_barHeight = p1.height;
- let left = 0;
- if (t.width == 0) {
- t.active_barWidth = p1.width;
- left = p1.left;
- } else {
- t.active_barWidth = t.width_item
- left = t.preventLeft + t.width_item * t.active;
- }
- let lsl = Math.floor((t.gutter / 2))
- t.left = left - t.preventLeft - uni.upx2px(lsl);
- t.aniOn = true;
- })
- });
- },
- returnKeyValue(item) {
- if (typeof item == 'string') {
- return item;
- }
- if (typeof item == 'object') {
- return item[this.rangKey];
- }
- },
- setDefaultPos() {
- let t = this;
- uni.createSelectorQuery().in(t).select('#tm-segTabs-item-' + this.active)
- .boundingClientRect().exec(
- function(p1) {
- if (!p1[0]) return;
- t.active_barHeight = p1[0].height;
- t.active_barWidth = p1[0].width;
- let lsl = Math.floor((t.gutter / 2))
- t.left = p1[0].left - t.preventLeft - uni.upx2px(lsl);
- })
- },
- clickItem(index, item) {
- this.active_index = index;
- this.$emit('change', index);
- this.$nextTick(function() {
- this.setDefaultPos();
- });
- }
- }
- };
- </script>
- <style lang="scss">
- .tm-segTabs {
- .tm-segTabs-wkbody {
- z-index: 2;
- .tm-segTabs-item {
- transition: all 0.2s linear;
- }
- }
- .tm-segTabs-bg {
- .tm-segTabs-bg-bar {
- &.aniOn {
- transition: all 0.2s ease-in-out;
- }
- }
- box-shadow: 0 0 3px 2px rgba(0, 0, 0, 0.02) inset;
- }
- }
- </style>
|