Vue Actual Warfare - Realize Commodity Details Page (12)

Keywords: Javascript Vue

This is our product details page:

Clicking on an item on the first page displays the details of the item.As shown in the following figure:

Create good component

Create a component good

  • Transitions to define the form of page presentation;
  • Use v-show with variable showFlag to control display and hide, ref with BScroll to control page sliding;
  • References to data that are present in the structure are handled in script.

    <template>
    <transition name="food-detail">

    <div class="food" v-show="showFlag" ref="foodView">
      <div class="food-wrapper">
        <div class="food-content">
          <div class="img-wrapper">
            <img class="food-img" :src="food.picture">
            
            <span class="close-bt icon-close" @click="closeView"></span>
            <img class="share-bt" src="./share.png">
            <img class="more-bt" src="./more.png">
          </div>
          <div class="content-wrapper">
            <h3 class="name">{{food.name}}</h3>
            <p class="saled">{{food.month_saled_content}}</p>
            <img
              class="product"
              v-show="food.product_label_picture"
              :src="food.product_label_picture"
            >
            <p class="price">
              <span class="text">¥{{food.min_price}}</span>
              <span class="unit">/{{food.unit}}</span>
            </p>
            <div class="cartcontrol-wrapper">
              <Cartcontrol :food="food"></Cartcontrol>
            </div>
            <div class="buy" v-show="!food.count || food.count==0" @click="addFirst">Select Specification</div>
          </div>
        </div>
        <div class="rating-wrapper">
          <div class="rating-title">
            <div class="like-ratio" v-if="food.rating">
              <span class="title">{{food.rating.title}}</span>
              <span class="ratio">
                (
                {{food.rating.like_ratio_desc}}
                <i>{{food.rating.like_ratio}}</i>
                )
              </span>
            </div>
            <div class="snd-title" v-if="food.rating">
              <span class="text">{{food.rating.snd_title}}</span>
              <span class="icon icon-keyboard_arrow_right"></span>
            </div>
          </div>
    
          <ul class="rating-content" v-if="food.rating">
            <li v-for="comment in food.rating.comment_list" class="comment-item">
              <div class="comment-header">
                <img :src="comment.user_icon" v-if="comment.user_icon">
                <img src="./anonymity.png" v-if="!comment.user_icon">
              </div>
              <div class="comment-main">
                <div class="user">{{comment.user_name}}</div>
                <div class="time">{{comment.comment_time}}</div>
                <div class="content">{{comment.comment_content}}</div>
              </div>
            </li>
          </ul>
        </div>
      </div>
    </div>

    </transition>
    </template>

Processing data, behavior.

  • Monitor the status of showFlag through data;
  • The food data obtained by props passing in the parent component loop Foods;
  • The method showView() can be called by the parent component, and the form of the call will be described later.
  • The closeView() method is bound to the template exit icon to close the page and reset the showFlag variable to false.
  • The method addFirst() is used to add a quantity of goods;

    <script>
    //Import BScroll
    import BScroll from "better-scroll";
    //Import Cartcontrol
    import Cartcontrol from "components/Cartcontrol/Cartcontrol";
    //Import Vue
    import Vue from "vue";

    export default {
    data() {

    return {
      showFlag: false
    };

    },
    props: {

    food: {
      type: Object
    }

    },
    methods: {

    // The showView method can be called by the parent component
    showView() {
      this.showFlag = true;
      // BScroll Initialization
      this.$nextTick(() => {
        if (!this.scroll) {
          this.scroll = new BScroll(this.$refs.foodView, {
            click: true
          });
        } else {
          this.scroll.refresh();
        }
      });
    },
    closeView() {
      this.showFlag = false;
    },
    addFirst() {
      Vue.set(this.food, "count", 1);
    }

    },
    components: {

    Cartcontrol,
    BScroll

    }
    };
    </script>

food component style

<style>
.food {
  position: fixed;
  left: 0;
  top: 0;
  bottom: 51px;
  background: white;
  width: 100%;
  z-index: 90;
}

.food-detail-enter-active,
.food-detail-leave-active {
  transition: 1s;
}
.food-detail-enter,
.food-detail-leave-to {
  transform: translateX(100%);
}

.food .food-wrapper .food-content .img-wrapper {
  position: relative;
  width: 100%;
  height: 0;

  /* How does the height stretch?
     In positioning, use padding-top or padding-bottom to set to 100%, actually the height of the box is calculated according to the width of the box
     */
  padding-top: 100%;
}
.food .food-wrapper .food-content .img-wrapper .food-img {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
}
.food .food-wrapper .food-content .img-wrapper .close-bt {
  width: 30px;
  height: 30px;
  position: absolute;
  left: 10px;
  top: 10px;
  text-align: center;
  font-size: 30px;
  color: white;
  background: #7f7f7f;
  border-radius: 50%;
}
.food .food-wrapper .food-content .img-wrapper .share-bt,
.food .food-wrapper .food-content .img-wrapper .more-bt {
  width: 30px;
  height: 30px;
  position: absolute;
  top: 10px;
}
.food .food-wrapper .food-content .img-wrapper .share-bt {
  right: 50px;
}
.food .food-wrapper .food-content .img-wrapper .more-bt {
  right: 10px;
}

.food .food-wrapper .food-content .content-wrapper {
  padding: 0 0 16px 16px;
  position: relative;
}
.food .food-wrapper .food-content .content-wrapper .name {
  font-size: 15px;
  color: #333333;
  line-height: 30px;
  font-weight: bold;
}
.food .food-wrapper .food-content .content-wrapper .saled {
  font-size: 11px;
  color: #9d9d9d;
  margin-bottom: 6px;
}
.food .food-wrapper .food-content .content-wrapper .product {
  height: 15px;
  margin-bottom: 16px;
}
.food .food-wrapper .food-content .content-wrapper .price {
  font-size: 0;
}
.food .food-wrapper .food-content .content-wrapper .price .text {
  font-size: 17px;
  color: #fb4e44;
}
.food .food-wrapper .food-content .content-wrapper .price .unit {
  font-size: 11px;
  color: #9d9d9d;
}
.food .food-wrapper .food-content .cartcontrol-wrapper {
  position: absolute;
  right: 12px;
  bottom: 10px;
  padding: 2px;
}
.food .food-wrapper .food-content .buy {
  width: 64px;
  height: 30px;
  font-size: 12px;
  line-height: 30px;
  text-align: center;
  background: #ffd161;
  border-radius: 30px;
  position: absolute;
  right: 12px;
  bottom: 10px;
}

.food .food-wrapper .rating-wrapper {
  padding-left: 16px;
}
.food .food-wrapper .rating-wrapper .rating-title {
  padding: 16px 16px 16px 0;
}
.food .food-wrapper .rating-wrapper .rating-title .like-ratio {
  float: left;
  font-size: 0;
}
.food .food-wrapper .rating-wrapper .rating-title .like-ratio .title {
  font-size: 13px;
}
.food .food-wrapper .rating-wrapper .rating-title .like-ratio .ratio {
  font-size: 11px;
}
.food .food-wrapper .rating-wrapper .rating-title .like-ratio .ratio i {
  color: #fb4e44;
  font-size: 11px;
}

.food .food-wrapper .rating-wrapper .rating-title .snd-title {
  float: right;
  font-size: 0;
}
.food .food-wrapper .rating-wrapper .rating-title .snd-title .text,
.food .food-wrapper .rating-wrapper .rating-title .snd-title .icon {
  font-size: 13px;
  color: #9d9d9d;
  display: inline-block;
}
.food .food-wrapper .rating-wrapper .rating-title .snd-title .icon {
  margin-left: 12px;
}

.food .food-wrapper .rating-wrapper .comment-item {
  padding: 15px 14px 17px 0;
  border-bottom: 1px solid #f4f4f4;
  width: 100%;
  box-sizing: border-box;
  display: flex;
}
.food .food-wrapper .rating-wrapper .comment-item .comment-header {
  flex: 0 0 41px;
  margin-right: 10px;
}
.food .food-wrapper .rating-wrapper .comment-item .comment-header img {
  width: 41px;
  height: 41px;
  border-radius: 50%;
}

.food .food-wrapper .rating-wrapper .comment-item .comment-main {
  flex: 1;
  margin-top: 6px;
}
.food .food-wrapper .rating-wrapper .comment-item .comment-main .user {
  width: 50%;
  float: left;
  font-size: 12px;
  color: #333333;
}
.food .food-wrapper .rating-wrapper .comment-item .comment-main .time {
  width: 50%;
  float: right;
  text-align: right;
  font-size: 10px;
  color: #666666;
}
.food .food-wrapper .rating-wrapper .comment-item .comment-main .content {
  margin-top: 17px;
  font-size: 13px;
  line-height: 19px;
}
</style>


Referencing a food component within the foods parent component

In the parent component, the selectedFood variable does not select any items by default

When we click on a commodity through showDetail(), we pass the selected food into selectedFood.

The details page is displayed by calling the method of the child component from the parent component template ref="this.$refs.foodView.showView() within the foodView and script tags.

Note that variable names do not duplicate event names.If the method name is the same as data, it can be accessed through this, which risks overwriting.Do not repeat.

<template>
    <!--foods Component Other Content-->
    

    <!--Commodity details-->
    <Food :food="selectedFood" ref="foodView"></Food>

</template>



<script>
    // Import Food
    import Food from "components/Food/Food";
    // Import Cartcontrol
    import Cartcontrol from "components/Cartcontrol/Cartcontrol";
    

 export default {
     data() {
        return {
              selectedFood: {}
        };
     },
     methods:{
         showDetail(food) {
              // Pass Value
              this.selectedFood = food;

              // Show Details Page
              this.$refs.foodView.showView();
        }
     }
 }
    

</script>


summary

We first created the good component, defined the data, methods, and

Notice that the method of the child component can be called by the parent component, and we know how the method in the child component is called in the parent component.However, a child component cannot call a parent component's method.

We then reference the child component in the parent component foods.There is a detail in the data that the variable name should not be duplicated with the method name to avoid being accessed by this.xx, overwriting it and causing errors.We also understand how parent components invoke child component methods.

As shown in the figure above, we have implemented the commodity details page.

Next we'll implement the evaluation list on the commodity details page.

Posted by SidewinderX on Fri, 30 Aug 2019 21:13:29 -0700