阶段案例系列:

案例 链接
【前端】vue阶段案例:购物车 https://blog.csdn.net/karshey/article/details/127473654
【前端】vue阶段案例:父子组件通信-tabControl栏 https://blog.csdn.net/karshey/article/details/127480941
【前端】vue阶段案例:组件化-房源展示 https://blog.csdn.net/karshey/article/details/127520175
【前端】vue阶段案例:vue-router使用流程 https://blog.csdn.net/karshey/article/details/127554171

文章目录

  • 目标
  • 代码
    • 0.准备工作
      • 0.1 数据
      • 0.2 reset.css
      • 0.3 main.js
    • 1.AreaHeader
      • 1.1 结构
      • 1.2 样式
      • 1.3 抽取到组件
    • 2.RoomItem
      • 2.1 结构
      • 2.2 样式
      • 2.3 抽取到组件
      • 2.4 完善title
      • 2.5 完善price
      • 2.6 完善buttom
  • 总代码
    • App.vue
    • AreaHeader.vue
    • Roomitem.vue
  • 参考

目标

完成如上页面,要组件化

代码

0.准备工作

0.1 数据

以json的形式给出:

{"title": "高分好评房源","subtitle": "来看看这些颇受房客好评的房源吧","list": [{"id": "47773281","picture_url": "https://z1.muscache.cn/im/pictures/miso/Hosting-47773281/original/de5df68f-8582-4ee6-82c4-a52443d9e83b.jpeg?aki_policy=large","verify_info": {"messages": ["整套公寓型住宅","1室1卫1床"],"text_color": "#767676"},"name": "价格真实 实图拍摄 整套单独使用每客消毒 高清投影【方糖】人民北路地铁|龙湖上城|火车北站|密码锁|","price": 158,"price_format": "¥158","star_rating": 5,"star_rating_color": "#008489","reviews_count": 1282,"reviews": [{"comments": "还不错","created_at": "2022-06-21T00:00:00Z","is_translated": false,"localized_date": "2022年6月","reviewer_image_url": "https://a0.muscache.com/im/pictures/user/762d2557-cdd5-427f-bcc8-26d61d885ab9.jpg?aki_policy=x_medium","review_id": 653751197167823900}],"bottom_info": {"content": "超赞房东","content_color": "#767676","font_size": "10","visibility": "LIST_VIEW"},"lat": 30.6816,"lng": 104.07032,"image_url": "/springdiscount/8ee76f60e2777c6c01195b318ace9656.jpg"},{"id": "54376288","picture_url": "https://z1.muscache.cn/im/pictures/miso/Hosting-54376288/original/71d12acc-ee2c-4721-8809-8a2b4666bb01.jpeg?aki_policy=large","verify_info": {"messages": ["整套公寓型住宅","1室1卫1床"],"text_color": "#767676"},"name": "漫漫 | 杨桃 轻奢一居室/地铁口/近春熙路太古里/4米9挑高/全景落地窗","price": 201,"price_format": "¥201","star_rating": 5,"star_rating_color": "#008489","reviews_count": 76,"reviews": [{"comments": "总体好评,房间的搭配是更讨女性喜欢的,比较强的ins风,东西比较齐全,比如洗衣机和冰箱都是有的,然后去太古里不是特别近需要骑车,另外门窗很薄。","created_at": "2022-06-22T00:00:00Z","is_translated": false,"localized_date": "2022年6月","reviewer_image_url": "https://a0.muscache.com/im/pictures/user/986322dc-5205-445f-8274-ebd71ee748ed.jpg?aki_policy=x_medium","review_id": 654502854910423900}],"bottom_info": {"content": "超赞房东","content_color": "#767676","font_size": "10","visibility": "LIST_VIEW"},"lat": 30.672022,"lng": 104.088898,"image_url": "/springdiscount/2f461f589f4a0b7784ef1c35875837a6.jpg"},{"id": "45817721","picture_url": "https://z1.muscache.cn/im/pictures/miso/Hosting-45817721/original/80f99830-f104-4404-86fd-1af856ac9b73.jpeg?aki_policy=large","verify_info": {"messages": ["独立房间","1室1卫1床"],"text_color": "#767676"},"name": "【可月租】【网红美食街区】/近春熙路/宽窄巷子/熊猫基地//【轻奢大床房】","price": 150,"price_format": "¥150","star_rating": 5,"star_rating_color": "#008489","reviews_count": 507,"reviews": [{"comments": "挺好的","created_at": "2022-06-09T00:00:00Z","is_translated": false,"localized_date": "2022年6月","reviewer_image_url": "https://a0.muscache.com/im/pictures/user/7b8fb8de-6437-4d10-bc37-d878fa084c5d.jpg?aki_policy=x_medium","review_id": 645148062181591700}],"bottom_info": {"content": "超赞房东","content_color": "#767676","font_size": "10","visibility": "LIST_VIEW"},"lat": 30.68856,"lng": 104.09887,"image_url": "/springdiscount/9b88e80dbe461f427cbe97c1e6265bb9.jpg"},{"id": "47434782","picture_url": "https://z1.muscache.cn/im/pictures/miso/Hosting-47434782/original/8e550632-acec-4478-a641-7ecc0062b1db.jpeg?aki_policy=large","verify_info": {"messages": ["整套公寓型住宅","1室1卫1床"],"text_color": "#767676"},"name": "可月租!品质大床!高空观景露台/步行地铁站/白天免费停车/直达春熙路/近建设巷小吃街","price": 146,"price_format": "¥146","star_rating": 5,"star_rating_color": "#008489","reviews_count": 1184,"reviews": [{"comments": "在永立住过几家公寓,这一家老板很热情,房间在35楼,晚上住高层很安静,大早上外面有点施工的声音,关上窗户基本可以隔绝。房间很整洁,从洗衣机 热水器 花洒还有洗手台的购置看出来老板比较用心。靠窗有桌子,但房间内没有沙发,不过也对得起这个价格了。楼下有一个小商业体,有许多餐馆和麦当劳,便利店也有开到很晚的。最近的地铁站是李家沱3号线,去7号线驷马桥路途稍微远一些。","created_at": "2022-06-08T00:00:00Z","is_translated": false,"localized_date": "2022年6月","reviewer_image_url": "https://a0.muscache.com/im/pictures/user/f0e1a670-a96c-46a7-a995-126e317b77f6.jpg?aki_policy=x_medium","review_id": 644366154235822300}],"bottom_info": {"content": "超赞房东","content_color": "#767676","font_size": "10","visibility": "LIST_VIEW"},"lat": 30.69036,"lng": 104.10039,"image_url": "/springdiscount/f5dd50f6ad6c307f11f30f3d77521079.jpg"},{"id": "40356486","picture_url": "https://z1.muscache.cn/im/pictures/e4aa2fdd-70f5-43dc-90ee-8a6d1d739d84.jpg?aki_policy=large","verify_info": {"messages": ["整套公寓型住宅","1室1卫1床"],"text_color": "#767676"},"name": "「精致mini房」楼下商场|地铁直达近春熙路太古里|建设巷小吃街|白天免费停车|可开发票|行李寄存","price": 146,"price_format": "¥146","star_rating": 5,"star_rating_color": "#008489","reviews_count": 1139,"reviews": [{"comments": "位置比较好 楼下全是吃的 性价比很高 建议老板可以加装个避光窗帘要不早上光太强了还有就是电视换个系统 电影感觉好少哈哈 别的都还不错 下次还会来","created_at": "2022-06-18T00:00:00Z","is_translated": false,"localized_date": "2022年6月","reviewer_image_url": "https://a0.muscache.com/im/pictures/user/fe5bb0d1-4a85-4bb7-b417-3b1ec2c296c0.jpg?aki_policy=x_medium","review_id": 651640404764253600}],"bottom_info": {"content": "超赞房东","content_color": "#767676","font_size": "10","visibility": "LIST_VIEW"},"lat": 30.68856,"lng": 104.09887,"image_url": "/springdiscount/b85ac5ad3658912e6d9d66aafee87f92.jpg"},{"id": "45098754","picture_url": "https://z1.muscache.cn/im/pictures/6e739539-940e-456f-a10d-0e8526feb943.jpg?aki_policy=large","verify_info": {"messages": ["整套公寓","1室1卫1床"],"text_color": "#767676"},"name": "【住.颜23】免清洁费/下楼就是太古里春熙路/高空浴缸/落地窗带阳台/百寸极米投影双地铁/其他点头像","price": 212,"price_format": "¥212","star_rating": 5,"star_rating_color": "#008489","reviews_count": 156,"reviews": [{"comments": "位置很便利,房间简洁干净,但浴缸热水用不起。","created_at": "2022-06-05T00:00:00Z","is_translated": false,"localized_date": "2022年6月","reviewer_image_url": "https://a0.muscache.com/im/pictures/user/c7e52930-6432-4310-9de1-0cacfcb56b14.jpg?aki_policy=x_medium","review_id": 642180681003801200}],"bottom_info": {"content": "超赞房东","content_color": "#767676","font_size": "10","visibility": "LIST_VIEW"},"lat": 30.65122,"lng": 104.08556,"image_url": "/springdiscount/872952d67cc83e0135faea56e6587a32.jpg"}]
}

0.2 reset.css

一些如h1、h2、h3的会有自己的margin和padding,我们把它清除一下:

body,h1,h2,h3{margin: 0;padding: 0;
}

0.3 main.js

import { createApp } from 'vue'import App from './案例copy/App.vue'
import './assert/css/reset.css'
createApp(App).mount('#app')

剩下的在App.vue里开发。

1.AreaHeader

1.1 结构

<template><div class="app"><div class="area-header"><h3 class="title">{{ HighScore.title }}</h3><div class="subtitle">{{ HighScore.subtitle }}</div></div></div>
</template><script setup>
import HighScore from '../data/high_score.json'
</script>

1.2 样式

<style lang="less" scoped>
.app {width: 1032px;padding: 40px;margin: 0 auto;.area-header{height: 84px;.title{font-size: 22px;}.subtitle{margin-top: 20px;font-size: 16px;}}}
</style>

1.3 抽取到组件

App.vue:

<template><div class="app"><!-- 1.AreaHeader 传入数据--><area-header :title="HighScore.title" :subtitle="HighScore.subtitle"></area-header></div>
</template><script setup>
import HighScore from '../data/high_score.json'
import AreaHeader from './components/AreaHeader.vue';
</script><style lang="less" scoped>
.app {width: 1032px;padding: 40px;margin: 0 auto;
}
</style>

组件AreaHeader.vue:

<template><div class="area-header"><!-- 这里直接用title数据 --><h3 class="title">{{ title }}</h3><div class="subtitle">{{ subtitle }}</div></div>
</template><script setup>
// 定义父组件传入的数据
defineProps({title: {type: String,default: "默认title"},subtitle: {type: String,default: "默认subtitle"}
})
</script><style lang="less" scoped>
.area-header {height: 84px;.title {font-size: 22px;}.subtitle {margin-top: 20px;font-size: 16px;}
}
</style>

效果:抽取组件前后效果没变。

2.RoomItem

2.1 结构

<!-- 2.RoomList -->
<div class="roomlist"><!-- RoomItem 要用循环显示--><template v-for="item in HighScore.list" :key="item.id"><div class="room-item"><div class="room-inner"><div class="cover"><img :src="item.picture_url" alt=""></div><div class="info"><div class="title">{{`todo`}}</div><div class="name">{{item.name}}</div><div class="price">{{item.price}}</div><div class="bottom">{{`todo`}}</div></div></div></div></template>
</div>

2.2 样式

.room-list {// 弹性布局display: flex;flex-wrap: wrap;// 没有-8的话标题和下面内容靠左不会对齐margin: 30px -8px 0;.room-item {width: 33.333333%;.room-inner {margin: 0 8px 12px;color: #484848;font-size: 800;img {width: 100%;// 外边框圆角border-radius: 3px;}.info {.title {margin-top: 8px;font-size: 12px;}.name {margin-top: 3px;font-size: 16px;// 2行:超出部分省略...overflow: hidden;text-overflow: ellipsis;display: -webkit-box;-webkit-line-clamp: 2;-webkit-box-orient: vertical;}.price {margin: 3px 0;font-size: 14px;font-weight: 400;}}}}
}

2.3 抽取到组件

App.vue:

<!-- 2.RoomList -->
<div class="room-list"><!-- RoomItem 要用循环显示--><template v-for="item in HighScore.list" :key="item.id"><room-item :item="item"></room-item></template>
</div>

RoomItem.vue:

<template><div class="room-item"><div class="room-inner"><div class="cover"><img :src="item.picture_url" alt=""></div><div class="info"><div class="title">{{ `todo` }}</div><div class="name">{{ item.name }}</div><div class="price">{{ item.price }}</div><div class="bottom">{{ `todo` }}</div></div></div></div>
</template><script setup>
// 父组件传来的数据
defineProps({item:{type:Object,default:()=>{}}
})
</script><style lang="less" scoped>
.room-item {width: 33.333333%;.room-inner {margin: 0 8px 12px;color: #484848;font-size: 800;img {width: 100%;// 外边框圆角border-radius: 3px;}.info {.title {margin-top: 8px;font-size: 12px;}.name {margin-top: 3px;font-size: 16px;// 2行:超出部分省略...overflow: hidden;text-overflow: ellipsis;display: -webkit-box;-webkit-line-clamp: 2;-webkit-box-orient: vertical;}.price {margin: 3px 0;font-size: 14px;font-weight: 400;}}}
}
</style>

2.4 完善title

目标:显示数据中的title,把verify_info中的messages连起来展示,颜色为text_color,要对空值进行处理。

js:把数据拼接

// title
const itemTitle=computed(()=>{return{title:props.item?.verify_info?.messages.join(" ")??'',color:props.item?.verify_info?.text_color??'#767676'}
})

html和css:插值语法和动态绑定style

<div class="title"
:style="{color:itemTitle.color}">
{{ itemTitle.title }}
</div>

效果:

2.5 完善price

目标:规范化显示:¥price / 天

js:

// price
function priceFormat(price){return '¥'+price+' / 天'
}

html:

<div class="price">{{ priceFormat(item.price) }}</div>

2.6 完善buttom

json数据中的buttom信息如下:

"bottom_info": {"content": "超赞房东","content_color": "#767676","font_size": "10","visibility": "LIST_VIEW"
},

目标:显示content,style是content_color和font_size,对空值处理(虽然没有空值,但严谨起见,我们还是要处理一下)。

js:显然要用计算属性。

// buttom
const bottomInfo=computed(()=>{return{content:props.item?.bottom_info?.content??'',style:{color:props.item?.bottom_info?.content_color??'#767676',fontSize:props.item.bottom_info.font_size+'px'}}
})

html和css:插值语法和动态绑定style

<div class="bottom" :style="bottomInfo.style">{{ bottomInfo.content }}</div>

效果:

总代码

App.vue

<template><div class="app"><!-- 1.AreaHeader 传入数据--><area-header :title="HighScore.title" :subtitle="HighScore.subtitle"></area-header><!-- 2.RoomList --><div class="room-list"><!-- RoomItem 要用循环显示--><template v-for="item in HighScore.list" :key="item.id"><room-item :item="item"></room-item></template></div></div>
</template><script setup>
import HighScore from '../data/high_score.json'
import AreaHeader from './components/AreaHeader.vue';
import RoomItem from './components/RoomItem.vue'
</script><style lang="less" scoped>
.app {width: 1032px;padding: 40px;margin: 0 auto;.room-list {// 弹性布局display: flex;flex-wrap: wrap;// 没有-8的话标题和下面内容靠左不会对齐margin: 30px -8px 0;}
}
</style>

AreaHeader.vue

<template><div class="area-header"><!-- 这里直接用title数据 --><h3 class="title">{{ title }}</h3><div class="subtitle">{{ subtitle }}</div></div>
</template><script setup>
// 定义父组件传入的数据
defineProps({title: {type: String,default: "默认title"},subtitle: {type: String,default: "默认subtitle"}
})
</script><style lang="less" scoped>
.area-header {height: 84px;.title {font-size: 22px;}.subtitle {margin-top: 20px;font-size: 16px;}
}
</style>

Roomitem.vue

<template><div class="room-item"><div class="room-inner"><div class="cover"><img :src="item.picture_url" alt=""></div><div class="info"><div class="title" :style="{color:itemTitle.color}">{{ itemTitle.title }}</div><div class="name">{{ item.name }}</div><div class="price">{{ priceFormat(item.price) }}</div><div class="bottom" :style="bottomInfo.style">{{ bottomInfo.content }}</div></div></div></div>
</template><script setup>
import { computed } from "@vue/runtime-core"// 父组件传来的数据:因为后面会用到item,所以要定义一个props,否则取不到item
const props= defineProps({item:{type:Object,default:()=>{}}
})// title
const itemTitle=computed(()=>{return{title:props.item?.verify_info?.messages.join(" ")??'',color:props.item?.verify_info?.text_color??'#767676'}
})// price
function priceFormat(price){return '¥'+price+' / 天'
}// buttom
const bottomInfo=computed(()=>{return{content:props.item?.bottom_info?.content??'',style:{color:props.item?.bottom_info?.content_color??'#767676',fontSize:props.item.bottom_info.font_size+'px'}}
})
</script><style lang="less" scoped>
.room-item {width: 33.333333%;.room-inner {margin: 0 8px 12px;color: #484848;font-weight: 800;img {width: 100%;// 外边框圆角border-radius: 3px;}.info {.title {margin-top: 8px;font-size: 12px;}.name {margin-top: 3px;font-size: 16px;// 2行:超出部分省略...overflow: hidden;text-overflow: ellipsis;display: -webkit-box;-webkit-line-clamp: 2;-webkit-box-orient: vertical;}.price {margin: 3px 0;font-size: 14px;font-weight: 400;}}}
}
</style>

参考

CSS3属性之text-overflow:ellipsis详解_Topepy的博客-CSDN博客_text-overflow:ellipsis
ES6中js的运算符(?.、?:、? ?、? ?=、)_小靳小盆友i.的博客-CSDN博客_es6中?

【前端】vue阶段案例:组件化-房源展示相关推荐

  1. VUE 前端中如何进行组件化开发?

    1.前端里面常说的视图层是什么? 我们把HTML中的DOM就可以与其他的部分独立开来划分出一个层次,这个层次就叫做视图层. Vue 的核心库只关注视图层 图1: dom对象树结构 图2:DOM和CSS ...

  2. Vue入门之组件化开发

    Vue入门之组件化开发 http://www.jianshu.com/p/6718ab1caa81 组件其实就是一个拥有样式.动画.js逻辑.HTML结构的综合块.前端组件化确实让大的前端团队更高效的 ...

  3. 【Vue】Vite 组件化开发

    文章目录 组件化开发 一.组件化开发思想 二.Vue 组件的构成 2.1 组件组成结构 2.2 组件 template 节点 2.2.1 在 template 中使用指令 2.2.2 在 templa ...

  4. 360奇舞团钟恒:选用Vue.js进行组件化开发,我们遇到了哪些坑?

    责编:陈秋歌,关注前端开发领域,寻求报道或者投稿请发邮件chenqg#csdn.net. 欢迎加入"CSDN前端开发者"微信群,参与热点.难点技术交流.请加群主微信「Rachel_ ...

  5. 前端vue项目(使用pdf.js) pdf展示及pdf工具栏放大缩小功能实现

    前端vue项目(使用pdf.js) pdf展示及pdf工具栏放大缩小功能实现 1.vue项目pdf展示 2.pdf工具栏放大缩小功能 文章目录 前端vue项目(使用pdf.js) pdf展示及pdf工 ...

  6. Vue.js教程-组件化开发

    Vue.js教程-组件化开发 前言 Vue组件化 什么是组件化 Vue单页面开发的解释 组件化思想 组件的使用 原理 实际开发中的使用-父子组件 父子组件传递数据 父传子-props用法 子传父-th ...

  7. Vue.js-Day02-PM【组件化开发(全局注册组件、局部注册组件、案例)、组件的配置选项、轮播图实例(左右切换按钮、底部导航栏、定时器、鼠标移入-图片静止)】

    Vue.js实训[基础理论(5天)+项目实战(5天)]博客汇总表[详细笔记] 目   录 4.组件化开发 4.1.组件的注册 全局注册 局部注册(只能在当前整个Vue实例的范围内才可以使用) 使用组件 ...

  8. 前端-vue(修饰符-组件)

    内置对象Vue new Vue():它是Vue里的内置对象,传递参数是对象类型传递 <script src="js/vue.js"></script>< ...

  9. Vue基础知识+组件化开发+模块化开发总结

    三.内容: 一.MVVM View层 视图层,我们前端开发时候的DOM层 主要就是给用户展示各种信息 Model层 数据层:可能是我们固定的思数据,更多的是来自我们的服务器,在网路上请求下来的数据 V ...

  10. Vue.js-资料-组件化思想 —上

    一.Vue中的组件 Vue视图层的灵魂 -  组件化 组件(Component)是 Vue.js 最强大的功能之一: 组件可以扩展 HTML 元素,封装可重用的代码: 在较高层面上,组件是自定义元素, ...

最新文章

  1. 深度学习之误差反向传播法
  2. 【转】MFC下用ADO连接SQL SERVER,保存图片,BLOB
  3. iOS开发隐藏键盘方法总结
  4. 用Backbone.js创建一个联系人管理系统(一)
  5. laravel框架中文手册_laravel请求参数校验方法
  6. java内部类为什么会持有外部类的引用_java中内部类为什么会持有外部类的引用?...
  7. java 关闭串口_java – 打开和关闭串行端口
  8. [通俗易懂]深入理解TCP协议(下):RTT、滑动窗口、拥塞处理
  9. Android中生成库文件与移除以及导入jar包重复问题
  10. H3C官网-inode客户端下载
  11. python爬虫气象数据_python爬虫入门,获取全国气象站24小时整点气象数据(二)...
  12. [统计学笔记] 方差分析表的解读
  13. 计算机网络一、什么是计算机网络
  14. 不支持16位应用程序,%1和64位电脑不兼容问题
  15. 为什么网站打开速度慢?
  16. wamp php打不开,wamp无法打开phpmyadmin
  17. windows下bat文件一直循环一句话如何解决
  18. PA-1190201215-冯开来(计算机系统大作业)
  19. 一个软件项目的组成成员及分工
  20. ngnix配置cgi和fastcgi

热门文章

  1. 磊科linux无线网卡驱动安装步骤,无线网卡驱动安装方法
  2. 【考研攻略】北京交通大学网络空间安全专业2018-2022年考研数据分析
  3. 如何用excel快速实现“平均值±标准差”
  4. 苹果CMS V10后台登录验证码错误解决方法
  5. 微信文件管理更改文件夹移动报错
  6. php单引号的作用,PHP中单引号和双引号的区别与作用
  7. 神经网络的数学原理(二):神经元与神经网络
  8. 一本通题解——1436:数列分段II
  9. 【96】太空射击游戏_笔记
  10. 微软浏览器Edge不能上网的解决办法