鍍金池/ 問答/HTML/ vue做一個tabbar,進(jìn)行切換問題

vue做一個tabbar,進(jìn)行切換問題

現(xiàn)在需要一個和底部tabbar的東西一模一樣的,要求就是點(diǎn)擊某個,它的圖片和背景色改為選中的樣式,其它的便會默認(rèn)樣式。
圖片描述
現(xiàn)在我已經(jīng)做了出來,可以實(shí)現(xiàn)這樣的功能,但是實(shí)現(xiàn)的過程實(shí)在是不堪入目。下面上代碼

HTML

<div class="optioncardbox">
      <div class="optioncard optioncardtext" @click="changetype(0)">
        <p :class="[is0?a:b]">ALL</p>
        <p class="optioncardtip">全部</p>
      </div>
      <div class="optioncard optioncardlist">
        <img :src="[is1?e:f]" alt="" srcset="" :class="[is1?d:c]" @click="changetype(1)">
        <p class="optioncardtip">營養(yǎng)</p>
      </div>
      <div class="optioncard optioncardlist">
        <img :src="[is2?g:h]" alt="" srcset="" :class="[is2?d:c]" @click="changetype(2)">
        <p class="optioncardtip">運(yùn)動</p>
      </div>
      <div class="optioncard optioncardlist">
        <img :src="[is3?i:j]" alt="" srcset="" :class="[is3?d:c]" @click="changetype(3)">
        <p class="optioncardtip">睡眠</p>
      </div>
      <div class="optioncard optioncardlist">
        <img :src="[is4?k:l]" alt="" srcset="" :class="[is4?d:c]" @click="changetype(4)">
        <p class="optioncardtip">情緒</p>
      </div>
      <div class="optioncard optioncardlist">
        <img :src="[is5?m:n]" alt="" srcset="" :class="[is5?d:c]" @click="changetype(5)">
        <p class="optioncardtip">內(nèi)分泌</p>
      </div>
    </div>

JavaScript

export default {
    data() {
      return {
        is0: true,
        is1: false,
        is2: false,
        is3: false,
        is4: false,
        is5: false,
        istip0: true,
        istip1: false,
        istip2: false,
        goodsinfo: [],
        targetid: 0,
        a: 'optioncardfirst',
        b: 'notoptioncardfirst',
        c: 'optioncardimg',
        d: 'notoptioncardimg',
        e: '../../../static/image/icon16-y.png',
        f: '../../../static/image/icon16.png',
        g: '../../../static/image/icon17-y.png',
        h: '../../../static/image/icon17.png',
        i: '../../../static/image/icon18-y.png',
        j: '../../../static/image/icon18.png',
        k: '../../../static/image/icon19-y.png',
        l: '../../../static/image/icon19.png',
        m: '../../../static/image/icon20-y.png',
        n: '../../../static/image/icon20.png',
        o: 'islessonlistoptioncard',
        p: 'lessonlistoptioncard',
      }
    },
    
    methods: {
      changetype(x) {
        if (x == 0) {
          this.is0 = true
          this.is1 = false
          this.is2 = false
          this.is3 = false
          this.is4 = false
          this.is5 = false
          this.targetid = 0
          this.getLessonlist(0)
          this.istip0 = true
          this.istip1 = false
          this.istip2 = false
        } else if (x == 1) {
          this.is1 = true
          this.is0 = false
          this.is2 = false
          this.is3 = false
          this.is4 = false
          this.is5 = false
          this.targetid = 16
          this.getLessonlist(0)
          this.istip0 = true
          this.istip1 = false
          this.istip2 = false
        } else if (x == 2) {
          this.istip0 = true
          this.istip1 = false
          this.istip2 = false
          this.is2 = true
          this.is0 = false
          this.is1 = false
          this.is3 = false
          this.is4 = false
          this.is5 = false
          this.targetid = 17
          this.getLessonlist(0)
        } else if (x == 3) {
          this.istip0 = true
          this.istip1 = false
          this.istip2 = false
          this.is3 = true
          this.is0 = false
          this.is2 = false
          this.is1 = false
          this.is4 = false
          this.is5 = false
          this.targetid = 18
          this.getLessonlist(0)
        } else if (x == 4) {
          this.istip0 = true
          this.istip1 = false
          this.istip2 = false
          this.is4 = true
          this.is0 = false
          this.is2 = false
          this.is3 = false
          this.is1 = false
          this.is5 = false
          this.targetid = 19
          this.getLessonlist(0)
        } else if (x == 5) {
          this.istip0 = true
          this.istip1 = false
          this.istip2 = false
          this.is5 = true
          this.is0 = false
          this.is2 = false
          this.is3 = false
          this.is4 = false
          this.is1 = false
          this.targetid = 20
          this.getLessonlist(0)
        }
      },

這個是部分代碼,其中有些無關(guān)緊要?,F(xiàn)在的基本思路就是加載2套不同樣式和src,然后每次點(diǎn)擊之后判定進(jìn)行切換,選中的進(jìn)行加載,其它的返回默認(rèn)值。但是這樣的代碼實(shí)在繁瑣,感覺程序員不應(yīng)該寫出這樣的代碼,說起來真挺丟人的,誰有很好的思路可以提供一下。非常感謝。

回答
編輯回答
真難過

https://codepen.io/kingdil/pe...

1.tabbar圖片和文字一一對應(yīng),首先考慮到的肯定是循環(huán)數(shù)據(jù)格式應(yīng)該如下

   tabs:[
                    {
                        title:'全部',
                        ico:'http://thyrsi.com/t6/367/1536299620x-1404781180.png',
                        icon:'http://thyrsi.com/t6/367/1536299648x-1404781180.png',
                    },
                    {
                        title:'營養(yǎng)',
                        ico:'http://thyrsi.com/t6/367/1536299680x-1404781180.png',
                        icon:'http://thyrsi.com/t6/367/1536299701x-1404781180.png',

                    },
                    {
                        title:'運(yùn)動',
                        ico:'http://thyrsi.com/t6/367/1536299735x-1404781180.png',
                        icon:'http://thyrsi.com/t6/367/1536299715x-1404781180.png',
                    }
                ] 

2.選中后圖片變化,文字變色,設(shè)選中的索引值為curIdx,當(dāng)選中索引值等于tabbar索引值時便是該tabbar被選中。添加選中后的class,改變選中后的圖標(biāo)

 <ul class="tabs">
            <li :class="{'cur':curIdx==index}" v-for="(item,index) in tabs"  @click="selectTabs(index)">
               <div class="tab_ico">
                   <img :src="curIdx==index?item.icon:item.ico" alt="">
               </div>
                <div class="tab_title">
                    <span v-text="item.title"></span>
                </div>
            </li>
        </ul>

3.綁定點(diǎn)擊事件,傳索引值,點(diǎn)擊哪個tabbar的時候curIdx就等于改索引值

  selectTabs:function(index){
                    this.curIdx=index;

                },
2018年4月1日 20:43
編輯回答
墨沫

代碼大概是這樣的

<script src="https://libs.cdnjs.net/vue/2.3.0/vue.min.js"></script>
<script src="https://libs.cdnjs.net/jquery/1.12.4/jquery.min.js"></script>
<style>
.b{background-color:black;}
.a{background-color:red;}
.optioncardbox{width:50px;}
.hide{display:none;}
</style>
<p style="line-height: 18px; font-size: 18px;  font-family: times;">
    <div id='tbar'  class="optioncardbox">
      <div v-for='(btn,key) in btns' class="optioncard optioncardtext"  @click="changetype(key)">      
        <p :class="{'hide':!(!btn.src1&&btn.selected)}" class="a">{{btn.text}}</p>
        <p :class="{'hide':!(!btn.src1&&!btn.selected)}" class="b">{{btn.text}}</p>
        <img :class="{'hide':!(btn.src1&&btn.selected)}" :src="btn.src1" alt="1"/>
        <img :class="{'hide':!(btn.src1&&!btn.selected)}" :src="btn.src2" alt="2"/>
        <p class="optioncardtip">{{btn.tip}}</p>
      </div>
</div> 
</p>
<script>
$(function(){
var app=new Vue({
    el:'#tbar',
    data: {
      btns:[
      {selected:true,text:'All',tip:'全部'},
       {selected:false,src1:'./pic1.png',src2:'./pic2.png',tip:'營養(yǎng)'},
       {selected:false,src1:'./pic1.png',src2:'./pic2.png',tip:'運(yùn)動'},
       {selected:false,src1:'./pic1.png',src2:'./pic2.png',tip:'睡眠'},
       {selected:false,src1:'./pic1.png',src2:'./pic2.png',tip:'情緒'},
       {selected:false,src1:'./pic1.png',src2:'./pic2.png',tip:'內(nèi)分泌'}
      ]
      },
   methods: {
        changetype:function(key) { 
        this.btns.forEach(function(e){e.selected=false});
         this.btns[key].selected=true;
       }
       }
  });
});

</script>

一點(diǎn)心得:
1,資源類的東內(nèi)容最好放在網(wǎng)頁模板里面而不是放在代碼中,這樣看起來比較方便;
2,重復(fù)性的東西一定要放在循環(huán)里面;
2.5,能完全一致就不要特殊化(都用一樣的標(biāo)簽,而不是p和img混用);
3,如果沒有外部的資源預(yù)加載(主要是圖片),盡量用css控制顯示隱藏而不用v-if進(jìn)行渲染控制;

2017年2月18日 13:40
編輯回答
何蘇葉

先給你個demo,之后給你說到說到想法。

<div id="app">
  <ul>
    <li v-for="(item,index) in tabbar.list" :class="{selected: index == tabbar.index}" @click="tabbar.index = index">{{index === tabbar.index?item.img_h:item.img}}</li>
  </ul>
</div>
new Vue({
  el: '#app',
  data: {
    tabbar: {
      list: [
        {name: 'ALL',img: '1.jpg',img_h: '1_h.jpg'},
        {name: 'ALL',img: '1.jpg',img_h: '1_h.jpg'},
        {name: 'ALL',img: '1.jpg',img_h: '1_h.jpg'},
        {name: 'ALL',img: '1.jpg',img_h: '1_h.jpg'}
      ],
      index: 0
    }
  }
})

你這個看上去是一樣的,為什么不考慮用循環(huán)呢?
既然都用了0123來表示為什么不用一個統(tǒng)一變量呢?
如果高亮和不高亮的命名有規(guī)律,那么可以判斷選中直接拼接呀? tabbar.index == index ? '_h':''

2017年12月16日 13:57
編輯回答
任她鬧

其他幾個人的答案基本的已經(jīng)很完備了,我這邊補(bǔ)充一個小東西,對于這種navtab,一般點(diǎn)擊的tab更改狀態(tài),其他沒點(diǎn)擊的恢復(fù)原態(tài),其實(shí)不用每次更改的時候都一個個去改變,你只用記錄上一次點(diǎn)擊的是哪個tab,在本次點(diǎn)擊的時候判斷是跟上次點(diǎn)擊的是同一個還是不同個,同一個的話 就不用做任何更改,非同一個的話,更改狀態(tài)即可,這樣的話,性能上面更好。

2018年4月10日 05:20
編輯回答
心夠野

我實(shí)現(xiàn)的辦法是利用索引。
寫一個記錄索引的字段,點(diǎn)擊的時候改變那個字段的值,與當(dāng)前點(diǎn)擊的索引進(jìn)行匹配,相等則添加class。
大概是下面這樣

<nav class="st-top-category">
    <span class="st-item" :class="{cur:curcate === index}" v-for="(cat,index) in categoryList" :key="index" v-on:click="changecate(index,cat.type,cat.value)">{{cat.label}}</span>
</nav>


data () {
    return {
      curcate: 0,
      categoryList: []
    }
  },
methods:{
    changecate(index,type,value){
      this.curcate = index;
    }
}
2017年12月7日 05:14