iT邦幫忙

2

使用vue製作Shoppingcart02

上次做了簡易的購物清單
這次來挑戰這個購物網站,還有很多還沒做好,但是想維持記錄學習

這次模仿的網站網址
Andenhud

HTML的架構

<div id="app">
  <div class="ShoppingList">
    <header>
      <div class="container-fluid"><ul>
        <li><a href="#"><i class="fa fa-file"></i>購物說明</a></li>
        <li><a href="#"><i class="fa fa-user"></i>我的帳戶</a></li>
        <li><a href="#"><i class="fa fa-shopping-cart"></i>購物車<span class="cart-count">{{count}}</span></a>
          <transition name="fade">
            <div class="buy_item">
            <img src="https://cdn.andenhud.tw/ahimages/_tw/products_color/20180719-1633385.jpg?image_version=0.91" alt="" width="100%" v-if="showBt == 1" class="title_green">
            <img src="https://cdn.andenhud.tw/ahimages/_tw/products_color/20180621-2592385.jpg?image_version=0.91" alt="" width="100%" v-if="showBt == 2">
            <img src="https://cdn.andenhud.tw/ahimages/_tw/products_color/20180621-2927385.jpg?image_version=0.91" alt="" width="100%" v-if="showBt == 3">
            <img src="https://cdn.andenhud.tw/ahimages/_tw/products_color/20180705-4841385.jpg?image_version=0.91" alt="" width="100%" v-if="showBt == 4">
            <div clas="buy_list">
               <div class="cart-name">凡爾賽拜金女-蕾絲織帶中腰三角褲</div>
               <div class="cart-color"><div v-if="showBt == 1" class="title_green">嫩綠</div>
                <div v-if="showBt == 2" class="title_lightpink">霧玫瑰粉</div>
                <div v-if="showBt == 3" class="title_purple">水晶紫</div>
                <div v-if="showBt == 4" class="title_red">霧玫瑰紅</div></div>
               <span class="cart-size">S</span>
              <div class="quantity">
                <button class="minus" @click="minus">-</button>
                <input type="text" class="quantity">
                <button class="add" @click="add">+</button>
              </div>
               <div class="cart-price">$159</div>
              </div>
              <div class="cart-total">總額 <b>$159</b></div>
            <button class="cart-button">前往結帳</button></div>
          </transition>
        </li>
      </ul></div>
    </header>
    <div class="container">
      <div class="row">
          <div class="col-5"><img src="https://cdn.andenhud.tw/ahimages/_tw/products_color/20180719-1633385.jpg?image_version=0.91" alt="" width="100%" v-if="showBt == 1" class="title_green">
            <img src="https://cdn.andenhud.tw/ahimages/_tw/products_color/20180621-2592385.jpg?image_version=0.91" alt="" width="100%" v-if="showBt == 2">
            <img src="https://cdn.andenhud.tw/ahimages/_tw/products_color/20180621-2927385.jpg?image_version=0.91" alt="" width="100%" v-if="showBt == 3">
            <img src="https://cdn.andenhud.tw/ahimages/_tw/products_color/20180705-4841385.jpg?image_version=0.91" alt="" width="100%" v-if="showBt == 4">
        </div>
          <div class="col-7">
            <div>
              <div class="name">【凡爾賽拜金女】蕾絲織帶中腰三角褲
                <div v-if="showBt == 1" class="title_green">嫩綠</div>
                <div v-if="showBt == 2" class="title_lightpink">霧玫瑰粉</div>
                <div v-if="showBt == 3" class="title_purple">水晶紫</div>
                <div v-if="showBt == 4" class="title_red">霧玫瑰紅</div>
              </div>
              <div class="color">          
                <div class="box green" @click="handleShow(1)" :class="show == 1?'active':''"></div>
                <div class="box lightpink" @click="handleShow(2)" :class="show == 2?'active':''">
                </div>
                <div class="box purple" @click="handleShow(3)" :class="show == 3?'active':''"></div>
                <div class="box red" @click="handleShow(4)" :class="show == 4?'active':''"></div>
              </div>
               <div class="size" v-for="item,index in items" :class="{'is-warning' : index === isWarning }">
                <input type="radio" name="size" v-model="isWarning" :value="index">{{item.size}}
              </div>
              <div class="quantity">
                <button class="minus" @click="decreument">-</button>
                <input type="text" class="quantity" v-model="num">
                <button class="add" @click="increument">+</button>
              </div>
              <div class="price"><span>${{price*num}}</span><s>定價 $199/<small>件</small></s></span></div>
              <button class="cart" @click="addToCart"><i class="fa fa-shopping-cart"></i>加入購物車</button>
              <tabs>
                <div slot="tabwrap">
                  <tab name="detail" text="產品說明" v-bind:selected="true">
                    <div slot="tabinner">
                      <div>材質:96%棉,4%彈性纖維</div>
                      <div>彈性:佳</div>
                      <div>透光:無</div>
                      <div>產地:台灣(堅持從原紗到成衣,均是台灣製造)</div>
                      <div>設計:典雅的色調搭配上十八世紀時尚代表的蝴蝶結,猶如置身在凡爾賽皇宮內享受雍容奢華~ 腰頭與褲口皆採用蕾絲織帶收邊,帶出微微的浪漫的氛圍,AH的蕾絲也是以細緻柔軟著名,可以完美的服貼於肌膚不會刺癢,百萬好友好評不斷!</div>
                      <div>貼心小提醒: 基於保障個人衛生,貼身內褲,請恕無法提供退換服務。</div>
                    </div>
                  </tab>
                  <tab name="info" text="模特兒資訊">
                    <div slot="tabinner">
                      <img src="https://cdn.andenhud.tw/icache/2018/model/Lena.jpg?image_version=0.91" alt="" class="col-4">
                      <div class="info col-8">
                        <h6>Lena 穿M號(舒適)</h6>
                        <p>HEIGHT/身高:174cm</p>
                        <p>WEIGHT/體重:60kg</p>
                        <p>BUST/胸圍:78cm</p>
                        <p>WAST/腰圍:61cm</p>
                        <p>HIPS/臀圍:89cm</p>
                      </div>
                      
                    </div>
                  </tab>
                  <tab name="notice" text="注意事項">
                    <div slot="tabinner">
                      <li>初次先以清水手洗,洗滌時有輕微染劑釋出為正常現象,請安心穿著。</li>
                      <li>避免變形,建議手洗或放入洗衣網以低速短程洗滌。</li>
                      <li>請勿使用漂白劑或深淺衣物一起洗滌,以免染色。</li>
                      <li>請勿浸泡與烘乾,以免衣物受損。</li>
                      <li>商品顏色會因電腦螢幕而略有差異,請以實際為準。</li>
                    </div>
                  </tab>
                  <tab name="size" text="尺寸表">
                    <div slot="tabinner">
                    </div>
                  </tab>
                </div>
              </tabs>
            </div>
        </div>
      </div>
    </div>
  </div>
</div>  

CSS(SCSS)

$color_green: #9cc4c3;
$color_lightpink: #e4b3ae;
$color_purple: #a193ad;
$color_red: #b82a36;

a,a:hover{
  color: #fff;
  text-decoration: none;
}

* {
  font-family: "Microsoft Yahei", sans-serif;
}

.container{
  padding: 1.8em 0;
}
header{
  background-color: #efefef;
  ul{
    display: flex;
    justify-content: flex-end;
    font-size: 0.8em;
    margin: 0;
    li{
      position: relative;
      list-style: none;
      a{
        display: inline-block;
        padding: 0.6em;
        color: #999;
        &:hover{
          color: #444;
        }
        i{
          margin-right: 5px;
        }
        .cart-count{
          color: $color_red;
          padding: 0 5px;
          font-weight: bold;
          font-size: 1em;
        }
      }
      .buy_item{
        display: none;
        position: absolute;
        top: 60px;
        right: 8px;
        width: 450px;
        padding: 15px;
        background-color: #efefef;
        border-radius: 4px;
        z-index: 2;
        &:before{
          position: absolute;
          top: -15px;
          right: 25px;
          z-index:5;
          content: '';
          border-left: 10px solid transparent;
          border-right: 10px solid transparent;
          border-bottom: 20px solid #efefef;
        }
        >*{
          display: inline-block;
          vertical-align: top;
          margin: 0;
        }
        img{
          width: 35%;
          margin-right: 8px;
        }
        .buy_list{
          display: flex;
          padding: 8px;
          width: 65%;
          >*{
            display: inline-block;
          }
      }
        .cart-button{
          outline: 0;
          border: 0;
          background-color: lighten($color_red,20%);
          color: #fff;
          width: 100%;
          height: 40px;
          line-height: 40px;
          transition: all 0.3s linear;
          &:hover {
            cursor: pointer;
            background-color: darken($color_red,5%);
          }
        }
        .cart-color{
          margin: 0.4em 0;
          opacity: 0.8;
        }
        .cart-size{
          border: 1px solid #999;
          padding: 0.1em 1.0em;
        }
        .cart-price{
          font-size: 1.2em;
        }
        .cart-total{
            color: $color_red;
            border-top: 1px solid #ccc;
            width: 100%;
            text-align: right;
            padding: 8px;
            margin-top: 15px;
            font-size: 1.4em;
            b{
              font-size: 1.4em;
            }
          }
        }
    }
    
  }
}
.quantity{
  margin: 0.6em 0;
}
.color{
  margin-top: 1.2em;
  .box{
    cursor: pointer;
    display: inline-block;
    margin-right: 8px;
    width: 30px;
    height: 30px;
    border: 1px solid #666;
  } 
}

.green{
  background-color: $color_green;
}

.lightpink{
  background-color: $color_lightpink;
}

.purple{
  background-color: $color_purple;
}

.red{
  background-color: $color_red;
}

.is-warning{
  background-color: #999;
  color: #fff;
}

.name{
  font-size: 1.4em;
  div{
    display: inline-block;
    font-size: 0.6em;
    opacity: 0.8;
  }
}
.size{
  border: 1px solid #ccc;
  text-align: center;
  margin-top: 1em;
  user-select: none;
  transition: all 0.3s linear;
  display: inline-block;
  width: 65px;
  height: 30px;
  line-height: 30px;
  margin-right: 8px;
  input{
    cursor: pointer;
    margin-right: 8px;
    border: 1px solid #999;
    text-align: center;
    width: 20px;
    height: 16px;
    font-size: 0.8em;
  }
}

.price{
  span{
    font-size: 1.4em;
    color: $color_red;
  }
  s{
    margin-left: 15px;
    color: #ccc;
    font-size: 0.8em;
    
  }
}

input{
  width: 50px;
  text-align: center;
}
.num {
  width: 10%;
  color: #fff;
  border: 1px solid #ccc;
  outline: 0;
  text-align: center;
  font-size: 0.8em;
}
.minus,
.add,.cart {
  background-color: #ccc;
  color: #444;
  border: 0;
  outline: 0;
  appearance: none;
  width: 25px;
  height: 25px;
  line-height: 25px;
  font-size: 18px;
  text-align: center;
  cursor: pointer;
  user-select: none;
  transition: all 0.3s linear;
  &:hover {
    background-color: #444;
    color: #ccc;
  }
}
.cart{
  margin-top: 1em;
  background-color: lighten($color_red,20%);
  color: #fff;
  width: 45%;
  height: 40px;
  line-height: 40px;
  i{
    margin-right: 10px;
  }
  &:hover {
    background-color: darken($color_red,5%);
  }
}


.fade-enter-active {
  transition: all .3s ease;
}
.fade-leave-active {
  transition: all .3s ease;
}
.fade-enter, .fade-leave-to {
  opacity: 0;
}

.nav-tabs{
  margin-top: 1.2em;
}

.nav-tabs .nav-link{
  margin-right: 3px;
  padding: .3rem .6rem;
  font-size: 16px;
  color: #fff;
  background-color: #ccc;
  &:hover{
    background-color: #b3b2b2;
    color: #fff;
  }
}
.nav-tabs .nav-link.active{
  color: #b3b2b2;
  background-color: #fff;
}
.tab-content{
  vertical-align: middle;
  min-height: 200px;
  padding: 12px 18px;
  font-size: 14px;
  line-height: 1.6;
  background-color: #fff;
  border-left: 1px solid #dee2e6;
  border-right: 1px solid #dee2e6;
  border-bottom: 1px solid #dee2e6;
  img{
    display: inline-block;
    float: left;
  }
  .info{
  }
  p{
    margin: 0;
    padding: 0;
  }
}

JS

Vue.component('tabs', {
  template: `
    <div>
      <ul class="nav nav-tabs" role="tablist">
        <li v-for="tab in tabs" class="nav-item" role="presentation">
          <a :href="'#' + tab.name" @click.prevent="selectTab(tab)" role="tab" class="nav-link" :class="{ 'active': tab.isActive }">{{ tab.text }}</a>
        </li>
      </ul>
      <div class="tab-content">
        <slot name="tabwrap"></slot>
      </div>
    </div>

    `,
    data() {
        return { tabs: [] };
    },
    created() {
        this.tabs = this.$children;
    },
    methods: {
      selectTab(selectedTab) {
        this.tabs.forEach(function(tab){
          tab.isActive = (tab.name == selectedTab.name);
        });
      }
    }
});

Vue.component('tab', {
  template: `
    <div :id="'#' + this.name" role="tabpanel" v-if="isActive">
      <slot name="tabinner"></slot>
    </div>
  `,
  data() {
    return {
      isActive: false
    };
  },
  props: {
    text: { required: true },
    name: { required: true },
    selected: { default: false }
  },
  mounted() {
    if(location.hash != ""){
      const url = location.hash;
      this.isActive = (url == '#' + this.name);
    }else{
      this.isActive = this.selected;
    }
  }
});

const app = new Vue({
  el: "#app",
  name: "ShoppingList",
  data() {
    return {
      msg: "MyBuylist 內褲清單",
      activeTab: 'All',
      isWarning: '',
      price: 159,
      showBt: 1,
      count: 0,
      num: '1',
      show:{
        title_green: {'title':'title_green','show':true},
        title_lightpink: {'title':'title_lightpink','show':false},
        title_purple: {'title':'title_purple','show':false},
        title_red: {'title':'title_red','show':false}
      },
      items: [
        {
          name: "嫩綠",
          size: 'S'
        },
        {
          name: "霧玫瑰粉",
          size: 'M'
        },
        {
          name: "水晶紫",
          size: 'L'
        },
        {
          name: "霧玫瑰紅",
          size: 'XL'
        }
      ]
    };
  },
  methods:{
    addToCart () {
      this.count++
    },
    decreument () {
      if(this.num>0){
        this.num--;
      }
    },
    increument () {
      this.num++
    },
    minus () {
      if(this.cart_count>0){
        this.cart_count--;
      }
    },
    add () {
      this.cart_count++
    },
    handleShow(bt){
      this.showBt = bt;
    },
    show: function(name){
      this.current = name;
    },
    isCurrent: function(name){
      return this.current == name;
    },
    selectTab(selectedTab){
      this.tabs.forEach(tab =>{
        tab.isActive = (tab.name == selectedTab.name);  
      });
    },
  },
  created(){
    this.tabs = this.$children;
  }
})

範例網址

v-if是這次大量使用的內容,也耗掉不少時間在研究
tab的部份嘗試用Component

尚未完成的購物清單

beat yesterday 贏過昨天的自己


尚未有邦友留言

立即登入留言