美食杰项目—菜品主页展示
效果展示:
- 从内容精选点击进入菜品首页
- 把菜品页所需要要的数据进行渲染到页面上
- 当点击收藏时切换到已收藏,实现来回切换效果
- 输入评论点击提交时,让评论的数据显示在下方页面中
效果图展示:
- 点击进入菜品首页
- 数据渲染,及收藏,已收藏切换
- 数据渲染
- 评论提交显示
具体实现请看如下代码及理解:
1.detail.vue
- 把头部,内容及评论分三个组件
- 在此组件中请求数据以及保存数据
menuInfo
接收数据 ,userInfo
设置一个默认值
<template>
<div class="menu-detail">
<detail-header :info="menuInfo"></detail-header>
<detail-content :info="menuInfo"></detail-content>
<Comment :info="menuInfo"></Comment>
</div>
</template>
<script>
import DetailHeader from './detail-header'
import DetailContent from './detail-content'
import Comment from './comment'
import {menuInfo} from '@/service/api';
export default {
components: {DetailHeader, DetailContent, Comment},
data(){
return {
menuInfo:{
userInfo:{},
raw_material:{
main_material:[],
accessories_material:[]
},
steps:[]
} //接收菜谱的详细信息
}
},
watch:{
$route:{
handler(){
let {menuId} = this.$route.query;
if(menuId){//发送请求
menuInfo({menuId}).then(({data}) =>{
console.log(data)
// 返回值有两种 true: 未收藏转已收藏
// false:
this.menuInfo = data.info;
})
}else{
this.$message({
message:"重进",
type:"warrning"
})
}
},
immediate:true
}
}
}
</script>
2. 头部的一个数据的渲染
- 通过 props 把数据传递过来,进行页面渲染
- 收藏和已收藏也在此完成
- v-if="!isOnwer"判断在自己页面不显示收藏,只在他人主页显示
- info.isCollection ? ‘已收藏’ : ‘收藏’ 通过isCollection 的true和false判断显示隐藏
收藏显示红色,已收藏显示灰色 - 通过async 和await同步的方法放它在登录完成之后才可以收藏
<template>
<section class="detail-header">
<img class="detail-img" :src="info.product_pic_url" />
<div class="detail-header-right">
<div class="detail-title clearfix">
<h1 class="title">{{info.title}}</h1>
<!--
1. 不显示,这个菜谱是当前用户发布的
2. 显示,后端返回一个是否收藏的字段
-->
<div class="detail-collection" v-if="!isOnwer">
<!-- collection-at no-collection-at-->
<a
href="javascript:;"
class="collection-at"
:class="{ 'no-collection-at' :info.isCollection}"
@click="toggleCollection"
>
{{
info.isCollection ? '已收藏' : '收藏'
}}
</a>
</div>
</div>
<ul class="detail-property clearfix">
<li v-for="item in info.properties_show" :key="item.type">
<strong>{{item.parent_name}}</strong>
<span>{{item.name}}</span>
</li>
</ul>
<div class="user">
<router-link
id="tongji_author_img"
class="img"
:to="{name:'space',query:{userId:info.userInfo.userId}}"
>
<img :src="info.userInfo.avatar">
</router-link>
<div class="info">
<h4>
<router-link id="tongji_author" :to="{name:'space',query:{userId:info.userInfo.userId}}">
{{info.userInfo.name}}
</router-link>
</h4>
<span>菜谱:{{info.userInfo.work_menus_len}}/ 关注:{{info.userInfo.following_len}} / 粉丝:{{info.userInfo.follows_len}}</span>
<strong>{{info.userInfo.createdAt}}</strong>
</div>
</div>
</div>
</section>
</template>
<script>
import {toggleCollection} from '@/service/api'
export default {
props:{
info: {
type: Object,
default: () => ({})
}
},
computed: {
isOnwer(){
return this.info.userInfo.userId === this.$store.state.userInfo.userId
}
},
methods:{
async toggleCollection(){
//先判断是否登录
if(!this.$store.getters.isLogin){
this.$message({
showClose:true,
message:'请先登录,再收藏',
type:'warning'
})
}
const data=await toggleCollection({menuId:this.info.menuId});
// console.log(data)
this.info.isCollection=data.data.isCollection;
}
}
}
</script>
3. 渲染内容数据
- 通过props把数据传递过来,查找每一个节点进行渲染
**<template>
<section class="detail-content">
<div class="detail-materials">
<p class=""><strong>“</strong>{{info.product_story}}<strong>”</strong></p>
<h2>用料</h2>
<div class="detail-materials-box clearfix" v-if="info.raw_material.main_material.length">
<h3>主料</h3>
<ul>
<li class="" v-for="item in info.raw_material.main_material" :key="item._id">
{{item.name}}
<span>{{item.space}}</span>
</li>
</ul>
</div>
<div class="detail-materials-box clearfix" v-if="info.raw_material.accessories_material.length">
<h3>辅料</h3>
<ul>
<li class="" v-for="item in info.raw_material.accessories_material" :key="item._id">
{{item.name}}
<span>{{item.space}}</span>
</li>
</ul>
</div>
</div>
<div class="detail-explain">
<h2>{{info.title}}的做法</h2>
<section class="detail-section clearfix" v-for="(item,index) in info.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>
</section>
<div class="skill">
<h2>烹饪技巧</h2>
<p>{{info.skill}}</p>
</div>
</div>
</section>
</template>
<script>
export default {
name: 'DetailContent',
props:{
info: {
type: Object,
default: () => ({})
}
}
}
</script>
4.评论
- 通过props传递数据
comments
接收数据,commentText
设置内容为空- 把评论的图片以及数据渲染出来
- v-model="commentText"通过v-model双向数据绑定内容
- @click=“send” 点击事件send发送
- 使用unshift向前添加
<template>
<div class="comment-box">
<h2>{{info.title}}的讨论</h2>
<div class="comment-text">
<a href="javascript:;" class="useravatar">
<img :src="userInfo.avatar">
</a>
<div v-if="!isLogin"><router-link to="">登录</router-link></div>
<div class="comment-right">
<el-input
type="textarea"
:rows="5"
:cols="50"
placeholder="请输入内容"
v-model="commentText"
>
</el-input>
<div class="comment-button" >
<el-button
class="send-comment"
type="primary"
size="medium"
@click="send"
>提交</el-button>
</div>
</div>
</div>
<div class="comment-list-box">
<ul class="comment-list">
<li v-for="item in comments" :key="item.commentId">
<a target="_blank" href="https://i.meishi.cc/cook.php?id=14026963" class="avatar">
</a>
<router-link :to="{name:'space',query:{userId: item.userInfo.userId}}" class="avatar">
<img :src="item.userInfo.avatar">
<h5>{{item.userInfo.name}}</h5>
</router-link>
<div class="comment-detail">
<p class="p1">{{item.commentText}}</p>
<div class="info clearfix">
<span style="float: left;">{{item.createdAt}}</span>
</div>
</div>
</li>
</ul>
</div>
</div>
</template>
<script>
import {getComments,postComment} from '@/service/api';
export default {
name: 'Comment',
props:{
info: {
type: Object,
default: () => ({})
}
},
data(){
return {
comments:[],
commentText:''
}
},
computed: {
userInfo(){
return this.$store.state.userInfo
},
isLogin(){
return this.$store.getters.isLogin
}
},
async mounted(){
let {menuId} = this.$route.query;
if(menuId){
let data = await getComments({menuId:menuId});
// console.log(data)
this.comments=data.data.comments
}
},
methods:{
async send(){
let data=await postComment({menuId:this.info.menuId,commentText:this.commentText})
console.log(data)
this.comments.unshift(data.data.comments);
this.commentText="";
}
},
}