Vue商品控件与购物车联动效果的实例代码

本篇我们将构建商品控件与购物车联动。

商品控件

商品控件的结构编写

 

在商品组件的<template>标签内完成项目结构,以及数据,事件的绑定,与判断逻辑的书写。

<template>

<div class="goods">

<div class="menu-wrapper" ref="menuScroll">

<ul>

<!--专场-->

<li class="menu-item" :class="{'current':currentIndex===0}" @click="selectMenu(0)">

<p class="text">

<img :src="container.tag_icon" v-if="container.tag_icon" class="icon">

{{container.tag_name}}

</p>

</li>

<li

class="menu-item"

v-for="(item,index) in goods"

:class="{'current':currentIndex===index+1}"

@click="selectMenu(index+1)"

>

<p class="text">

<img :src="item.icon" v-if="item.icon" class="icon">

{{item.name}}

</p>

</li>

</ul>

</div>

<!-- 右侧商品列表 -->

<div class="foods-wrapper" ref="foodScroll">

<!--专场-->

<ul>

<li class="container-list food-list-hook">

<div v-for="item in container.operation_source_list">

<img :src="item.pic_url">

</div>

</li>

<!-- 具体分类-->

<li v-for="item in goods" class="food-list food-list-hook">

<h3 class="title">{{item.name}}</h3>

<!--具体商品列表-->

<ul>

<li v-for="food in item.spus" class="food-item">

<div class="icon" :style="head_bg(food.picture)"></div>

<div class="content">

<h3 class="name">{{food.name}}</h3>

<p class="desc" v-if="food.description">{{food.description}}</p>

<div class="extra">

<span class="saled">{{food.month_saled_content}}</span>

<span class="praise">{{food.praise_content}}</span>

</div>

<img

class="product"

:src="food.product_label_picture"

v-show="food.product_label_picture"

>

<p class="price">

<span class="text">¥{{food.min_price}}</span>

<span class="unit">/{{food.unit}}</span>

</p>

</div>

<div class="cartcontrol-wrapper">

<Cartcontrol :food="food"></Cartcontrol>

</div>

</li>

</ul>

</li>

</ul>

</div>

<Shopcart :poiInfo="poiInfo" :selectFoods="selectFoods"></Shopcart>

</div>

</template>

Shopcart组件是Goods组件的子组件,在Shopcart组件初始化的时候我们可以传入给其参数poiInfo selectFoods.

请求数据,声明方法与计算属性

<script>

import BScroll from "better-scroll";//滚动组件

import Shopcart from "components/Shopcart/Shopcart";//购物车

import Cartcontrol from "components/Cartcontrol/Cartcontrol";//控制商品数量按钮

export default {

data() {

return {

container: {},

goods: [],

poiInfo: {},

listHeight: [],

menuScroll: {},

foodScroll: {},

scrollY: 0

};

},

components: {

BScroll,//引入组件

Shopcart,

Cartcontrol

},

created() {

this.$axios

.get("api/goods")

.then(response => {

let json = response.data;

if (json.code === 0) {

// 重点

this.container = json.data.container_operation_source;

this.goods = json.data.food_spu_tags;

this.poiInfo = json.data.poi_info;

this.$nextTick(function() {

this.initScroll();

// 左右联动

// 右->左

// 计算区间

this.caculateHeight();

});

}

})

.catch(function(error) {

// handle error

console.log(error);

});

},

computed: {

// 根据右侧判断左侧index

currentIndex() {

for (let i = 0; i < this.listHeight.length; i++) {

let start = this.listHeight[i];

let end = this.listHeight[i + 1];

if (this.scrollY >= start && this.scrollY < end) {

return i;

}

}

return 0;

},

selectFoods() {

let foods = [];

this.goods.forEach(good => {

good.spus.forEach(food => {

if (food.count > 0) {

foods.push(food);

}

});

});

return foods;

}

},

methods: {

head_bg(imgName) {

return "background-image: url(" + imgName + ");";

},

initScroll() {

this.menuScroll = new BScroll(this.$refs.menuScroll, {

click: true

});

this.foodScroll = new BScroll(this.$refs.foodScroll, {

probeType: 3,

click: true

});

this.foodScroll.on("scroll", pos => {

this.scrollY = Math.abs(Math.round(pos.y));

});

},

caculateHeight() {

let foodList = this.$refs.foodScroll.getElementsByClassName(

"food-list-hook"

);//获取到dom元素

let height = 0;

this.listHeight.push(height);

for (let i = 0; i < foodList.length; i++) {

height += foodList[i].clientHeight;

this.listHeight.push(height);

}

// [0, 215, 1343, 2425, 3483, 4330, 5823, 7237, 8022, 8788, 9443]

},

selectMenu(index) {

let foodlist = this.$refs.foodScroll.getElementsByClassName(

"food-list-hook"

);

// 根据下标,滚动到相对应的元素

let el = foodlist[index];

// 滚动到对应元素的位置

this.foodScroll.scrollToElement(el, 100);

}

}

};

</script>

定义商品组件的样式

<style scoped>

.goods {

display: -webkit-box;

display: -ms-flexbox;

display: flex;

position: absolute;

top: 190px;

bottom: 51px;

overflow: hidden;

width: 100%;

}

.goods .menu-wrapper {

-webkit-box-flex: 0;

-ms-flex: 0 0 85px;

flex: 0 0 85px;

background: #f4f4f4;

}

.goods .menu-wrapper .menu-item {

padding: 16px 23px 15px 10px;

border-bottom: 1px solid #e4e4e4;

position: relative;

}

.goods .menu-wrapper .menu-item.current {

background: white;

font-weight: bold;

margin-top: -1px;

}

.goods .menu-wrapper .menu-item:first-child.current {

margin-top: 1px;

}

.goods .menu-wrapper .menu-item .text {

font-size: 13px;

color: #333333;

line-height: 17px;

vertical-align: middle;

-webkit-line-clamp: 2;

display: -webkit-box;

-webkit-box-orient: vertical;

overflow: hidden;

}

.goods .menu-wrapper .menu-item .text .icon {

width: 15px;

height: 15px;

vertical-align: middle;

}

.goods .menu-wrapper .menu-item .num {

position: absolute;

right: 5px;

top: 5px;

width: 13px;

height: 13px;

border-radius: 50%;

color: white;

background: red;

text-align: center;

font-size: 7px;

line-height: 13px;

}

.goods .foods-wrapper {

-webkit-box-flex: 1;

-ms-flex: 1;

flex: 1;

/* background: blue; */

}

.goods .foods-wrapper .container-list {

padding: 11px 11px 0 11px;

border-bottom: 1px solid #e4e4e4;

}

.goods .foods-wrapper .container-list img {

width: 100%;

margin-bottom: 11px;

border-radius: 5px;

}

.goods .foods-wrapper .food-list {

padding: 11px;

}

.goods .foods-wrapper .food-list .title {

height: 13px;

font-size: 13px;

background: url(btn_yellow_highlighted@2x.png) no-repeat left center;

background-size: 2px 10px;

padding-left: 7px;

margin-bottom: 12px;

}

.goods .foods-wrapper .food-list .food-item {

display: flex;

margin-bottom: 25px;

position: relative;

}

.goods .foods-wrapper .food-list .food-item .icon {

flex: 0 0 63px;

background-position: center;

background-size: 120% 100%;

background-repeat: no-repeat;

margin-right: 11px;

height: 75px;

}

.goods .foods-wrapper .food-list .food-item .content {

flex: 1;

}

.goods .foods-wrapper .food-list .food-item .content .name {

font-size: 16px;

line-height: 21px;

color: #333333;

margin-bottom: 10px;

padding-right: 27px;

}

.goods .foods-wrapper .food-list .food-item .content .desc {

font-size: 10px;

line-height: 19px;

color: #bfbfbf;

margin-bottom: 8px;

/* 超出部分显示省略号*/

-webkit-line-clamp: 1;

display: -webkit-box;

-webkit-box-orient: vertical;

overflow: hidden;

}

.goods .foods-wrapper .food-list .food-item .content .extra {

font-size: 10px;

color: #bfbfbf;

margin-bottom: 7px;

}

.goods .foods-wrapper .food-list .food-item .content .extra .saled {

margin-right: 14px;

}

.goods .foods-wrapper .food-list .food-item .content .product {

height: 15px;

margin-bottom: 6px;

}

.goods .foods-wrapper .food-list .food-item .content .price {

font-size: 0;

}

.goods .foods-wrapper .food-list .food-item .content .price .text {

font-size: 14px;

color: #fb4e44;

}

.goods .foods-wrapper .food-list .food-item .content .price .unit {

font-size: 12px;

color: #bfbfbf;

}

</style>

商品数量控制组件

这里用了vue动画

cart-decrease类为商品数量减少结构。 使用指令v-show控制其显隐。有商品数量的时候会按照规定动画进行显示,反之则隐藏。

cart-count类为选中的商品数量。

cart-add类为商品数量增加结构。

通过vue全局api set进行第一次点击增加商品按钮时候的设置。

https://cn.vuejs.org/v2/api/#...

<template>

<div class="cartcontrol">

<transition name="move">

<div class="cart-decrease" @click="decreaseCart" v-show="food.count">

<span class="inner icon-remove_circle_outline"></span>

</div>

</transition>

<div class="cart-count" v-show="food.count">{{food.count}}</div>

<div class="cart-add icon-add_circle" @click="increaseCart">

<i class="bg"></i>

</div>

</div>

</template>

<script>

import Vue from 'vue'

export default {

props:{

food:{

type:Object

}

},

methods:{

decreaseCart(){

this.food.count--;

},

increaseCart(){

if(!this.food.count){

Vue.set(this.food,'count',1);

}else{

this.food.count++;

}

}

}

};

</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->

<style scoped>

.cartcontrol {

font-size: 0;

}

.cartcontrol .cart-decrease {

display: inline-block;

width: 26px;

height: 26px;

font-size: 26px;

color: #b4b4b4;

}

.cartcontrol .cart-count {

display: inline-block;

width: 25px;

text-align: center;

font-size: 12px;

line-height: 26px;

vertical-align: top;

}

.cartcontrol .cart-add {

display: inline-block;

width: 26px;

height: 26px;

font-size: 26px;

color: #ffd161;

position: relative;

}

.cartcontrol .cart-add .bg {

width: 20px;

height: 20px;

border-radius: 50%;

background: black;

position: absolute;

left: 3px;

top: 3px;

z-index: -1;

}

.move-enter-active,

.move-leave-active {

transition: all 0.5s linear;

}

.move-enter,

.move-leave-to {

transform: translateX(20px) rotate(180deg);

}

</style>

购物车组件

 

我们现在创建shopcart购物车组件。

<template>

<div class="shopcart" :class="{'highligh':totalCount>0}">

<div class="shopcart-wrapper">

<div class="content-left">

<div class="logo-wrapper" :class="{'highligh':totalCount>0}">

<span class="icon-shopping_cart logo" :class="{'highligh':totalCount>0}"></span>

<i class="num" v-show="totalCount">{{totalCount}}</i>

</div>

<div class="desc-wrapper">

<p class="total-price" v-show="totalPrice">¥{{totalPrice}}</p>

<p class="tip" :class="{'highligh':totalCount>0}">另需{{shipping_fee_tip}}</p>

</div>

</div>

<div class="content-right" :class="{'highligh':totalCount>0}">{{payStr}}</div>

</div>

</div>

</template>

<script>

// 导入BScroll

import BScroll from "better-scroll";

export default {

props: {

min_price_tip: {

type: String,

default: ""

},

shipping_fee_tip: {

type: String,

default: ""

},

selectFoods: {

type: Array,

default() {

return [

/* {

min_price: 10,

count: 3

},

{

min_price: 7,

count: 1

} */

];

}

}

},

computed: {

// 总个数 将所选商品的个数累加得到总个数。

totalCount() {

let num = 0;

this.selectFoods.forEach(food => {

num += food.count;

});

return num;

},

// 总金额

totalPrice() {

let total = 0;

this.selectFoods.forEach(food => {

total += food.min_price * food.count;

});

return total;

},

// 结算按钮显示

payStr() {

if (this.totalCount > 0) {

return "去结算";

} else {

return this.min_price_tip;

}

}

},

components: {

BScroll

}

};

</script>

<style>

.shopcart-wrapper {

width: 100%;

height: 51px;

background: #514f4f;

position: fixed;

left: 0;

bottom: 0;

display: flex;

z-index: 99;

}

.shopcart-wrapper.highligh {

background: #2d2b2a;

}

.shopcart-wrapper .content-left {

flex: 1;

}

.shopcart-wrapper .content-left .logo-wrapper {

width: 50px;

height: 50px;

background: #666666;

border-radius: 50%;

position: relative;

top: -14px;

left: 10px;

text-align: center;

float: left;

}

.shopcart-wrapper .content-left .logo-wrapper.highligh {

background: #ffd161;

}

.shopcart-wrapper .content-left .logo-wrapper .logo {

font-size: 28px;

color: #c4c4c4;

line-height: 50px;

}

.shopcart-wrapper .content-left .logo-wrapper .logo.highligh {

color: #2d2b2a;

}

.shopcart-wrapper .content-left .logo-wrapper .num {

width: 15px;

height: 15px;

line-height: 15px;

border-radius: 50%;

font-size: 9px;

color: white;

background: red;

position: absolute;

right: 0;

top: 0;

}

.shopcart-wrapper .content-left .desc-wrapper {

float: left;

margin-left: 13px;

}

.shopcart-wrapper .content-left .desc-wrapper .total-price {

font-size: 18px;

line-height: 33px;

color: white;

}

.shopcart-wrapper .content-left .desc-wrapper .tip {

font-size: 12px;

color: #bab9b9;

line-height: 51px;

}

.shopcart-wrapper .content-left .desc-wrapper .tip.highligh {

line-height: 12px;

}

.shopcart-wrapper .content-right {

flex: 0 0 110px;

font-size: 15px;

color: #bab9b9;

line-height: 51px;

text-align: center;

font-weight: bold;

}

.shopcart-wrapper .content-right.highligh {

background: #ffd161;

color: #2d2b2a;

}

.shopcart-wrapper .shopcart-list {

position: absolute;

left: 0;

top: 0;

z-index: -1;

width: 100%;

}

.shopcart-wrapper .shopcart-list.show {

transform: translateY(-100%);

}

.shopcart-wrapper .shopcart-list .list-top {

height: 30px;

text-align: center;

font-size: 11px;

background: #f3e6c6;

line-height: 30px;

color: #646158;

}

.shopcart-wrapper .shopcart-list .list-header {

height: 30px;

background: #f4f4f4;

}

.shopcart-wrapper .shopcart-list .list-header .title {

float: left;

border-left: 4px solid #53c123;

padding-left: 6px;

line-height: 30px;

font-size: 12px;

}

.shopcart-wrapper .shopcart-list .list-header .empty {

float: right;

line-height: 30px;

margin-right: 10px;

font-size: 0;

}

.shopcart-wrapper .shopcart-list .list-header .empty img {

height: 14px;

margin-right: 9px;

vertical-align: middle;

}

.shopcart-wrapper .shopcart-list .list-header .empty span {

font-size: 12px;

vertical-align: middle;

}

.shopcart-wrapper .shopcart-list .list-content {

max-height: 360px;

overflow: hidden;

background: white;

}

.shopcart-wrapper .shopcart-list .list-content .food-item {

height: 38px;

padding: 12px 12px 10px 12px;

border-bottom: 1px solid #f4f4f4;

}

.shopcart-wrapper .shopcart-list .list-content .food-item .desc-wrapper {

float: left;

width: 240px;

}

.shopcart-wrapper

.shopcart-list

.list-content

.food-item

.desc-wrapper

.desc-left {

float: left;

width: 170px;

}

.shopcart-wrapper

.shopcart-list

.list-content

.food-item

.desc-wrapper

.desc-left

.name {

font-size: 16px;

margin-bottom: 8px;

/* 超出部分隐藏*/

-webkit-line-clamp: 1;

display: -webkit-box;

-webkit-box-orient: vertical;

overflow: hidden;

height: 16px;

}

.shopcart-wrapper

.shopcart-list

.list-content

.food-item

.desc-wrapper

.desc-left

.unit {

font-size: 12px;

color: #b4b4b4;

}

.shopcart-wrapper

.shopcart-list

.list-content

.food-item

.desc-wrapper

.desc-left

.description {

font-size: 12px;

color: #b4b4b4;

/* 超出部分隐藏*/

overflow: hidden;

height: 12px;

}

.shopcart-wrapper

.shopcart-list

.list-content

.food-item

.desc-wrapper

.desc-right {

float: right;

width: 70px;

text-align: right;

}

.shopcart-wrapper

.shopcart-list

.list-content

.food-item

.desc-wrapper

.desc-right

.price {

font-size: 12px;

line-height: 38px;

}

.shopcart-wrapper .shopcart-list .list-content .food-item .cartcontrol-wrapper {

float: right;

margin-top: 6px;

}

.shopcart .shopcart-mask {

position: fixed;

top: 0;

right: 0;

width: 100%;

height: 100%;

z-index: 98px;

background: rgba(7, 17, 27, 0.6);

}

</style>

 

到此购物车与组件联动就结束了。下篇我们讲如何进行商品分类菜单数量提示。

总结

以上所述是小编给大家介绍的Vue商品控件与购物车联动效果的实例代码,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

以上是 Vue商品控件与购物车联动效果的实例代码 的全部内容, 来源链接: utcz.com/z/323695.html

回到顶部