美食杰项目(四)美食详情页

本文详细介绍了美食杰项目的美食详情页设计,包括头部、内容和评论的样式,以及实现效果和代码思路。通过组件化的方式,分别解析了detail-header、detail-content和comment组件的功能与代码实现,助读者理解并实现美食详情展示和评论功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:

  • 本节给大家讲的是美食杰项目的美食详情页的主要功能和具体样式,希望我的代码能够帮助到你,也希望你能够看懂有所收获

具体样式

  • 头部样式
    在这里插入图片描述

  • 内容样式
    在这里插入图片描述

  • 评论样式
    在这里插入图片描述

实现效果

完成具体样式的渲染
完成评论的渲染并且可以实现发布评论的功能

代码思路

通过点击美食图片实现跳转,跳转到食品详情页,并将用户的id传进路由
利用id请求到美食的详细信息
并将这些数据传给相应的组件实现低耦合高边距
各个组件拿到数据之后挨个进行渲染
评论思路:
	利用v-model将评论的内容拿到
	利用接口的将评论的内容保存到接口数据里

相应的组件

在这里插入图片描述

相关代码

  • detail组件为总组件,里面包含了页面的头部组件,内容组件,评论组件,路由跳转到此组件,相关代码:
<template>
  <div class="detail">
    <!-- 通过父传子将值传到响应的组件 -->
    <!-- 头部 -->
    <detailHeader :menuInfo="menuInfo"></detailHeader>
    <!-- 内容 -->
    <detailContent :menuInfo="menuInfo"></detailContent>
    <!-- 评论 -->
    <comment :menuInfo="menuInfo"></comment>
  </div>
</template>

<script>
import { menuInfo } from "@/connector/api";
import detailHeader from "./detail-header";
import detailContent from "./detail-content";
import comment from "./comment";
export default {
  data() {
    return {
      menuInfo: [],
    };
  },
  components: {
    // 组件
    detailHeader,
    detailContent,
    comment,
  },
  mounted() {
    // 将id结构出来
    let { menuId } = this.$route.query;
    console.log(menuId);
    // 通过id将数据拿出来,赋值给menuInfo
    menuInfo({ menuId }).then(({ data }) => {
      console.log(data);
      this.menuInfo = data.info;
    });
  },
};
</script>
  • detail-header组件里面的具体功能就是将菜品的详细介绍出来,并将作者的基本信息列举出来,detail-header头部组件代码:
<template>
  <div class="detail-header">
    <div class="header-left">
      <img :src="menuInfo.product_pic_url" alt="" />
    </div>
    <div class="header-right">
      <div class="header-right-title">
        <h1>{{ menuInfo.title }}</h1>
        <div class="collection" @click="collection">
          {{ menuInfo.isCollection ? "已收藏" : "收藏" }}
        </div>
      </div>
      <ul class="detail-property">
        <li v-for="item in menuInfo.properties_show" :key="item.type">
          <strong>{{ item.parent_name }}</strong>
          <span>{{ item.name }}</span>
        </li>
      </ul>
      <div class="user">
        <router-link class="img">
          <img :src="menuInfo.userInfo.avatar" />
        </router-link>
        <div class="info">
          <h4>
            <router-link to="">
              {{ menuInfo.userInfo.name }}
            </router-link>
          </h4>
          <span
            >菜谱:{{ menuInfo.userInfo.work_menus_len }}/ 关注:{{
              menuInfo.userInfo.following_len
            }} / 粉丝:{{ menuInfo.userInfo.follows_len }}</span
          >
          <strong>{{ menuInfo.userInfo.createdAt }}</strong>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { toggleCollection } from "@/connector/api";
export default {
  props: {
    menuInfo: {
      type: Object,
      default: () => {},
    },
  },
  methods: {
    // 收藏
    async collection() {
      // 将用户id结构出来
      const { userId } = this.$route.query;
      // 将data数据拿出来
      const { data } = await toggleCollection({ menuId: userId });
      // 将值赋值给menuInfo里面的isCollection
      // console.log(res);
      this.menuInfo.isCollection = data.isCollection;
    },
  },
};
</script>

  • detail-conten组件的主要功能是对菜品的主要介绍,将菜品的主料,辅料,具体步骤进行渲染。detail-content内容组件相关代码:
<template>
  <div class="detail-content">
    <div class="content-header">
      <p class="">
        <strong></strong>{{ menuInfo.product_story }}<strong></strong>
      </p>
      <h2>用料</h2>
      <div class="materials">
        <h3>主料</h3>
        <ul>
          <li
            class=""
            v-for="item in menuInfo.raw_material.main_material"
            :key="item._id"
          >
            {{ item.name }}
            <span>{{ item.space }}</span>
          </li>
        </ul>
      </div>
      <div class="materials">
        <h3>辅料</h3>
        <ul>
          <li
            class=""
            v-for="item in menuInfo.raw_material.accessories_material"
            :key="item._id"
          >
            {{ item.name }}
            <span>{{ item.space }}</span>
          </li>
        </ul>
      </div>
    </div>
    <div class="content">
      <h2>{{ menuInfo.title }}</h2>
      <div
        class="detail-steps"
        v-for="(item, index) in menuInfo.steps"
        :key="item._id"
      >
        <em class="detail-number">{{ index + 1 }}.</em>
        <div class="detail-explain-desc">
          <p>{{ item.describe }}</p>
          <img class="conimg" :src="item.img_url" v-if="item.img_url" alt="" />
        </div>
      </div>
      <h2>烹饪技巧</h2>
      <div class="skill">
        {{ menuInfo.skill }}
      </div>
    </div>
  </div>
</template>

<script>
export default {
  // 用props来接收父元素传过来的值
  props: {
    menuInfo: {
      type: Object,
      default: () => {},
    },
  },
};
</script>

  • comment组件为评论组件,主要功能就是渲染对菜品的评论,并且可以添加评论内容。comment评论组件相关代码
<template>
  <div class="discuss">
    <h2>{{ menuInfo.title }}”的讨论</h2>
    <div class="comment">
      <router-link to=""
        ><img :src="menuInfo.userInfo.avatar" alt=""
      /></router-link>
      <!-- 判断是否登录 -->
      <div v-if="!isLogin">
        请先登录后,再评论<router-link to="">登录</router-link>
      </div>
      <div class="comment-right">
        <el-input
          type="textarea"
          :rows="5"
          :cols="300"
          placeholder="请输入内容"
          v-model="commentText"
        >
        </el-input>
        <!-- 给提交写一个点击事件 -->
        <div class="comment-button">
          <el-button
            class="send-comment"
            type="primary"
            size="medium"
            style="float: left"
            @click="sendComment"
            >提交</el-button
          >
        </div>
      </div>
    </div>
    <div class="comment-list">
      <div class="comment-item" v-for="item in comments" :key="item.commentId">
        <div class="avatar">
          <img :src="item.userInfo.avatar" alt="" />
          <span>{{ item.userInfo.name }}</span>
        </div>
        <div class="discuss-content">
          <p>{{ item.commentText }}</p>
          <p>{{ item.createdAt }}</p>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { getComments, postComment } from "@/connector/api";
export default {
  // props接受父组件传过来的数据
  props: {
    menuInfo: {
      type: Object,
      default: () => {},
    },
  },
  data() {
    return {
      // 变量接收输入进去的值
      commentText: "",
      comments: [],
    };
  },
  computed: {
    // 看是否登录
    isLogin() {
      return this.$store.getters.isLogin;
    },
  },
  async mounted() {
    //向后端请求数据(评论的内容)
    //有两种情况
    console.log(this.$route.query);
    let { userId } = this.$route.query;
    // 判断是否有用户id
    if (userId) {
      // 将评论数据赋值给data
      let data = await getComments({ menuId: userId });
      console.log(data);
      // 将data的评论数据赋值给comments里面
      this.comments = data.data.comments;
    }
  },
  methods: {
    // 发送评论
    async sendComment() {
      // 将值传进接口
      let data = await postComment({
        menuId: this.menuInfo.menuId,
        commentText: this.commentText,
      });
      // 将输入进的评论添加到comments里面
      this.comments.unshift(data.data.comments);
      // console.log(data.data.comments);
    },
  },
};
</script>

总结:

以上就是 美食杰项目中美食详情页的具体样式和实现方法,不懂得也可以在评论区里问我,以后会持续发布一些新的功能,敬请关注。我的其他作品

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员--韩同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值