shopchart中的methods,el打印不出来,购物小球后续的操作都没办法做了
来源:17-18 购物车小球动画实现(1)

qq_上帝之手_3
2018-01-10
//goods.vue
<template>
<div class="goods">
<div class="menu-wrapper" ref='menuWrapper'>
<ul>
<!-- 当当前轮到的$index是当前的index的时候,给它添加一个current的样式,设置高亮 -->
<!-- 点击事件selectMenu在methods里面定义 -->
<li v-for="(item,$index) in goods" class="menu-item" :class="{'current':currentIndex===$index}"
@click="selectMenu($index,$event)">
<span class="text border-1px">
<span v-show="item.type>0" class="icon" :class="classMap[item.type]"></span>{{item.name}}
</span>
</li>
</ul>
</div>
<div class="foods-wrapper" ref='foodsWrapper'>
<ul>
<li v-for="item in goods" class="food-list" ref="foodList">
<h1 class="title">{{item.name}}</h1>
<ul>
<li v-for="food in item.foods" class="food-item">
<div class="icon">
<img width="57" height="57" :src="food.icon">
</div>
<div class="content">
<h2 class="name">{{food.name}}</h2>
<p class="desc">{{food.description}}</p>
<div class="extra">
<span class="count">月售{{food.sellCount}}份</span>
<span>好评率{{food.rating}}%</span>
</div>
<div class="price">
<span class="now">¥{{food.price}}</span>
<span v-show="food.oldPrice" class="old">¥{{food.oldPrice}}</span>
</div>
<div class="cartcontrol-wrapper">
<!-- cartcontrol组件,把food传入关联 -->
<cartcontrol :food="food"></cartcontrol>
</div>
</div>
</li>
</ul>
</li>
</ul>
</div>
<!-- 组件 -->
<!-- 如果这里写了:deliveryPrice="seller.deliveryPrice" :minPrice="seller.minPrice"却
还是报错,记得去app.vue的router-view标签设:seller="seller"属性传递拥有的数据 -->
<shopcart ref="shopcart" :select-foods="selectFoods" :deliveryPrice="seller.deliveryPrice" :minPrice="seller.minPrice"></shopcart>
</div>
</template>
<script type="text/ecmascript-6">
import shopcart from "../shopCart/shopCart.vue"; //import~之后记得在components里面注册这个组件
import cartcontrol from "../cartcontrol/cartcontrol.vue"; //import~之后记得在components里面注册这个组件
import BScroll from "better-scroll"; //接受BSroll实例化的时候要接受一个dom
const ERR_OK = 0;
export default {
props: {
seller: {
type: Object
}
},
data() {
return {
goods: [],
listHeight: [], //用一个变量来存滚动屏幕高度的数据
scrollY: 0, //跟踪y方向上的变量
selectedFood: {}
};
},
computed: {
//计算属性
currentIndex() {
//左侧当前的索引
for (var i = 0; i < this.listHeight.length; i++) {
//获得当前索引值对应的高度
let height1 = this.listHeight[i];
let height2 = this.listHeight[i + 1];
//height1he height2分别对应一个区间的高点和低点
if (!height2 || (this.scrollY >= height1 && this.scrollY < height2)) {
//如果是最后一个或者是落在当前正常高度区间
return i;
}
}
return 0; //如果什么都没有就返回0
},
selectFoods() {
//:select-foods="selectFoods"要的数据从这里找
//select-foods它观测的是goods这个对象,goods发生变化以后就会被重新计算,重新计算,以下的逻辑会再被执行一遍
let foods = [];
this.goods.forEach(good => {
good.foods.forEach(food => {
if (food.count) {
//如果这个商品的count值有的话,就加入到foods数组中
foods.push(food);
}
});
});
return foods; //return foods给selectFoods,这样就能让cartcontrol和和购物车shopcart联动了
}
},
created() {
this.classMap = [
"decrease",
"discount",
"guarantee",
"special",
"invoice",
"guarantee"
];
this.$http.get("../static/data.json").then(res => {
// if (response.errno === ERR_OK) {
this.goods = res.data.goods;
console.log(this.goods);
this.$nextTick(() => {
this._initScroll();
this._calculateHeight(); //定义求滚动屏幕高度的方法
});
// }
});
},
methods: {
//方法属性
selectMenu($index, $event) {
//$event指的是click所传递的事件
//在better-scroll里面派发的事件和原生event事件有一个属性区别,
//当属于我们(better-scroll)自己派发出来的事件的时候$event._constructed是true,
//而pc端浏览器原生里是没有_constructed这个属性的,所以如果是浏览器一生的点击事件要设置!$event._constructed,
//当!$event._constructed的时候return不执行
//只有当我们自定义事件派发的时候$event._constructed为true,就会走到下面的逻辑
if (!$event._constructed) {
return; //
}
console.log($index);
// console.log($event);
let foodList = this.$refs.foodList; //拿到所有的foodList列表
let el = foodList[$index]; //拿到el的dom元
this.foodsScroll.scrollToElement(el, 300); //滚动的接口scrollToElement,传入滚动的dom元素el和滚动的动画时间300毫秒
},
_drop(target) {
// 体验优化,异步执行下落动画
this.$nextTick(() => {//通过$refs访问子组件对象
this.$refs.shortcart.drop(target);//通过this.$refs.shortcart访问到子组件,调用它的drop方法同时把它的子组件传进去
});
},
_initScroll() {
this.meunScroll = new BScroll(this.$refs.menuWrapper, {
click: true //因为better-scroll(实现原理是监听了一些touchstart,touchend事件)会阻止默认事件click,所以要设置一下点击事件才能阻止默认的事件
});
this.foodsScroll = new BScroll(this.$refs.foodsWrapper, {
click: true,
probeType: 3 //希望滚动的时候实时告诉我们滚动的位置,相当于探针的效果
});
this.foodsScroll.on("scroll", pos => {
this.scrollY = Math.abs(Math.round(pos.y)); //scrollY必须是正值,所以用绝对值函数,实时拿到scrollY,接下来是把scrollY和左侧的索引做映射
});
},
_calculateHeight() {
let foodList = this.$refs.foodList;
let height = 0;
this.listHeight.push(height); //先拿到第0个的高度
for (let i = 0; i < foodList.length; i++) {
let item = foodList[i];
height += item.clientHeight;
this.listHeight.push(height); //其实是一个区间数组,它标识着每个区间的高度
}
}
},
components: {
//注册shopcart组件,这样页面才看得到,模板才可以使用这个组件
shopcart,
cartcontrol, //注册组件
// food
},
events: {//先在cartcontrol用$emit传递时间,再在这里写事件
//这里需要调用子组件的方法
'cart.add'(target) {
console.log(target);
//cart.add事件
this._drop(target); //把target传进来
}
}
};
//shopcart.vue
<template>
<div class="shopcart">
<div class="content">
<div class="content-left">
<div class="logo-wrapper">
<!-- :class="{'highLight':totalCount>0}"当totalCount>0时,只要我们选择了商品,显示class为highLight的样式 -->
<div class="logo" :class="{'highlight':totalCount>0}">
<i class="icon-shopping_cart" :class="{'highlight':totalCount>0}"></i>
</div>
<div class="num" v-show="totalCount>0">{{totalCount}}</div>
</div>
<div class="price" :class="{'highlight':totalPrice>0}">¥{{totalPrice}}元</div>
<div class="desc">另需配送费¥{{deliveryPrice}}元</div>
</div>
<div class="content-right">
<!-- 多少钱起送 -->
<div class="pay" :class="payClass">{{payDesc}}</div>
</div>
</div>
<div class="ball-container">
<div v-for="ball in balls" v-show="ball.show" transiton="drop" class="ball">
<div class="inner inner-hook"></div>
</div>
</div>
</div>
</template>
<script>
import BScroll from 'better-scroll';
import cartcontrol from 'components/cartcontrol/cartcontrol';
export default {
props:{//shopcart组件传进来的变量要用props接收
selectFoods:{//selectFoods保存了一个选择商品的数组,price就可以根据整个数组进行计算了
type:Array,
default(){//如果default的值是Object或者Array,default就必需写成一个函数
return [
{
price:30,
count:1
}
];//return一个空数组
}
},
deliveryPrice: {
type: Number,//变成习惯,prop属性一般最好指定数据类型
default: 0//默认值是0
},
minPrice: {
type: Number,
default: 0
}
},
data(){
return{
balls:[//抛物线小球需要创建一个数组
{
show:false
},
{
show:false
},
{
show:false
},
{
show:false
},
{
show:false
}
],
dropBalls:[],//已经下落的小球,数组
fold:true
};
},
computed:{//利用计算属性表示price
totalPrice(){//totalPrice依赖于selectFoods
let total=0;
this.selectFoods.forEach((food)=>{//遍历数组
total+=food.price*food.count;//food指的是当前食物的数量
});
return total;
},
totalCount(){
let count=0;
this.selectFoods.forEach((food)=>{
count+=food.count;//把所有选择了的都加起来
});
return count;
},
payDesc(){
if(this.totalPrice===0){//当总价是0的时候默认显示20元起送
return `¥${this.minPrice}元起送`;//用``代替用+号拼接字符串,写起来更加方便
}else if(this.totalPrice<this.minPrice){//当总价低于最低起送价时显示还差##元起送
let diff=this.minPrice-this.totalPrice;//声明一个变量说明离最低起送价还差多少
return `还差¥${diff}元起送`;
}else{//剩下的就是满足条件的了
return '去结算';//没有变量的时候就用普通的单引号就可以了
}
},
payClass(){//根据实际情况切换enough或者not-enough的class属性
if(this.totalPrice<this.minPrice){
return 'not-enough'
}else{
return 'enough';
}
}
},
methods:{
drop(el){//el指元素
console.log(el);
}
}
};
//cartcontrol.vue
<template>
<div class="cartcontrol">
<transition name="move">
<div class="cart-decrease" v-show="food.count>0" @click.stop.prevent="decreaseCart" transition="move">
<span class="inner icon-remove_circle_outline"></span>
</div>
</transition>
<div class="cart-count" v-show="food.count>0">{{food.count}}</div>
<div class="cart-add icon-add_circle" @click.stop.prevent="addCart"></div>
</div>
</template>
<script>
import Vue from 'vue';//引入全局vue
export default{
props:{
food:{
type:Object
}
},
created(){
// console.log(this.food);
},
methods:{
addCart(event){
if(!event._constructed){
return;
}
// console.log('click');
if (!this.food.count) {//判断food.count是否存在
Vue.set(this.food,'count',1);//给vue增加一个count属性,同时设为1;
//通过Vue.set()添加的属性vue就能观测到
// this.food.count=1;
}else{
this.food.count++;
}
this.$emit('cart.add', event.target);//派发cart.add事件
},
decreaseCart(event){
if(!event._constructed){
return;
}
// console.log('click');
if (this.food.count) {//判断food.count是否存在,有就减
this.food.count--;
}
}
}
};
1回答
-
qq_上帝之手_3
提问者
2018-01-10
已经可以打印了,谢谢
112018-03-02
相似问题