当前位置:   article > 正文

Vue3 + uni-app 微信小程序:仿知乎日报详情页设计及实现_vue3 uniapp

vue3 uniapp

引言

在移动互联网时代,信息的获取变得越来越便捷,而知乎日报作为一款高质量内容聚合平台,深受广大用户喜爱。本文将详细介绍如何利用Vue 3框架结合微信小程序的特性,设计并实现一个功能完备、界面美观的知乎日报详情页。我们将从需求分析、UI设计、前端开发到最终的调试优化,一步步构建出一个既符合用户体验又具有高性能的页面。

知乎日报这个案例很经典,有比较完整的API,很值得模仿学习。 也很简单,唯一需要注意的是日报详情的设计,因为知乎日报的详情接口,竟返回的是html,这.....,在小程序端肯定无法渲染。

接上文,关于知乎详情页接口返回的是html内容的处理,参见博主这篇博文介绍:

go 语言爬虫库goQuery 的详细使用(知乎日报详情页解析示例)-CSDN博客

关于知乎日报首页列表页的实现,参见博主的这篇博文:

uni-app的uni-list列表组件高效使用举例 (仿知乎日报实现)-CSDN博客

由于知乎日报后台接口有访问限制和机器人检测,频繁访问会报403错误,这里博主使用golang+mongoDB搞了个数据采集服务,仅用于学习研究目的。详见:

Go-Zero 框架使用 MongoDB,数据采集入库如此简单_gozero mongo json-CSDN博客

以下着重介绍知乎日报详情页的设计及实现。 附实现效果:

体验地址:imovie: 爱电影小程序uni-app

一、需求分析

在开始设计之前,我们首先需要明确页面的主要功能和目标用户。知乎日报详情页主要应包括以下功能:

文章上方的banner图,带文章标题。

文章标题展示:清晰展示文章标题,吸引用户注意力。

作者信息:展示文章作者的名称和简介,增加可信度。

文章内容:呈现文章正文,支持图片、视频等多种媒体格式,段落标题没事。

二、UI设计

考虑到微信小程序的屏幕尺寸和阅读体验,我们选择简洁明快的设计风格,确保文字易读,图片清晰,同时留有足够的空白区域,避免视觉疲劳。

三、前端开发

原始后台接口返回的内容是html格式的。如:https://daily.zhihu.com/story/9773554网页所示,用以下curl命令可以访问查看。

curl http://news-at.zhihu.com/api/4/news/9773554

经过后台处理后,返回的json数据格式,如下:

  1. {
  2. "author": "鑫波和他的小鱼干,",
  3. "avatar": "https://picx.zhimg.com/v2-7f800acc9b76bd4223d00fd2918a0e62_l.jpg?source=8673f162",
  4. "bio": "你觉得我是鑫波? 不,我是他的小鱼干!",
  5. "code": 0,
  6. "content": [{
  7. "types": "p.strong",
  8. "value": "【摘要】 感性运动电信号化学信号膨压变化机制是比较保守的化学信号幅度比较小"
  9. }, {
  10. "types": "p",
  11. "value": "植物营固着生长,植物体本身不能挪动位置,但它们并不是静止不动的。植物的运动可以分为向性运动、感性运动、近似昼夜节奏的生物钟运动。"
  12. }, {
  13. "types": "p",
  14. "value": "植物受无定向的外界刺激(如光暗转变、震动、电触、骤冷、烧灼、触模等)所引起的运动,叫感性运动,运动的方向与外界刺激方向无关。"
  15. }, {
  16. "types": "img",
  17. "value": "https://pic1.zhimg.com/v2-53f2a8c785650e973c94e43969883d00_720w.jpg?source=8673f162"
  18. }, {
  19. "types": "p",
  20. "value": "比如合欢、含羞草在夜晚的时候小叶合拢,叶柄下垂。这是由细胞膨压的变化引起的,属于感性运动里边的感震性,也被称为紧张性运动或膨胀性运动,而不是由于生长不均匀造成的生长性运动。"
  21. }, {
  22. "types": "p.strong",
  23. "value": "电信号"
  24. }, {
  25. "types": "p",
  26. "value": " 植物通过电流传递信息,引起运动 https://www.zhihu.com/video/1185507313678426112 "
  27. }, {
  28. "types": "p",
  29. "value": "含羞草小叶受到接触、热或电、震动等刺激时,小叶成对合拢;如刺激较强,可快速通过生物电、化学物质传递,使邻近的小叶依次合拢,并逐渐传递到叶柄基部,使整个复叶下垂;强刺激甚至可使整株植物的小叶合拢,复叶叶柄下垂。"
  30. }, {
  31. "types": "img",
  32. "value": "https://picx.zhimg.com/v2-66cd3015da22b603f97f0c5e54468fe2_720w.jpg?source=8673f162"
  33. }, {
  34. "types": "p",
  35. "value": "含羞草复叶的总叶柄和小叶柄基部膨大,称为叶枕。叶枕上部细胞壁厚,下部细胞壁较薄,下部细胞的间隙比上部大。当外界刺激传来时,叶枕下部细胞透性迅速增大,水分和钾离子外流,进入细胞间隙的质外体空间,使叶枕下部细胞膨压下降变软,而上部组织仍保持紧张状态,进而使叶柄由叶枕处弯曲下垂。研究证明,水分和钾离子从叶枕下部细胞流出,是由于电波传来的刺激促进蔗糖从韧皮部卸载,导致质外体水势降低触发的。"
  36. }, {
  37. "types": "p",
  38. "value": " 触碰引发含羞草产生生物电 https://www.zhihu.com/video/1185508896713691136 "
  39. }, {
  40. "types": "p",
  41. "value": "捕虫草叶子的运动也是一种感震运动,它的叶片特化为捕虫器,当小动物踏上捕虫器,触发感震运动,叶子合拢,将入侵的小动物捕获。也是由类似含羞草小叶合拢的机制决定的。主要是生物电传递触碰信息,进而刺激水势变化,通过改变膨压,影响叶片倾角。"
  42. }, {
  43. "types": "p.strong",
  44. "value": "其他植物受到机械伤害能产生生物电吗?"
  45. }, {
  46. "types": "p",
  47. "value": "含羞草、捕虫草是通过生物电信号和化学信号引起运动的,那么我们就想知道,其他植物被触碰、受伤、被虫咬的时候,会不会也产生类似的电流或者有类似的化学信号产生?答案是肯定的。"
  48. }, {
  49. "types": "p",
  50. "value": " 虫咬拟南芥老叶,电信号传到新叶 https://www.zhihu.com/video/1185510410676125696 "
  51. }, {
  52. "types": "p",
  53. "value": "植物的电信号是普遍存在的,不仅仅存在于这些运动幅度大,肉眼可见的器官运动过程中。很多时候我们看不见植物运动,也不能立刻看到植物对外界环境的响应,但是生物电已经作为长距离信号传递的一种方式,传递了外界环境变化的信息。"
  54. }, {
  55. "types": "p",
  56. "value": " 虫咬拟南芥新叶,电信号传到老叶 https://www.zhihu.com/video/1185511384678326272 "
  57. }, {
  58. "types": "p",
  59. "value": "比如受伤的植物会在叶片的局部和远端传播损伤信号,以获得对昆虫、食草动物和病原体的系统抗性。长距离 Ca 波以约 1mm/sec 的速度通过维管系统快速传输,膜电位变化位于系统性创伤响应的上游。"
  60. }, {
  61. "types": "p",
  62. "value": " 叶柄机械创伤引起植株 Ca 信号传递 https://www.zhihu.com/video/1185512729502158848 缺失 GLR 创伤信号不能向远方传递 https://www.zhihu.com/video/1185520303021797376 "
  63. }, {
  64. "types": "p",
  65. "value": "植物在创伤后,将谷氨酸作为一种机械损伤的信号物质释放。拟南芥中两种谷氨酸受体样蛋白(GLR3.3 和 GLR3.6)将创伤诱导的叶片内谷氨酸积累转化为电信号和钙振荡,并将胁迫信号传递给远处叶片,以增强茉莉酸下游响应基因的表达。韧皮部和木质部共同作用,通过 Ca 波响应创伤,介导 GLR 依赖的系统性响应。"
  66. }, {
  67. "types": "p",
  68. "value": " 伤口处施谷氨酸促进损伤信号传递 https://www.zhihu.com/video/1185521982665297920 "
  69. }, {
  70. "types": "p.strong",
  71. "value": "其他植物产生的生物电能引起植物运动吗?"
  72. }, {
  73. "types": "p",
  74. "value": "既然含羞草、捕虫草以外的植物也会产生生物电,那么它们的电流会不会在植株传递并引发受伤部位以及受伤以外部位的运动呢?"
  75. }, {
  76. "types": "p",
  77. "value": "研究人员让虫子咬伤、取食拟南芥的叶片 8,咬伤叶片诱导生物电的产生。当虫子咬断主脉时,与其相邻的叶片 13 中也能检测到电信号,说明拟南芥中会有类似含羞草的结果,虫子取食诱导的电信号可以从损伤部位传递到未损伤部位。"
  78. }, {
  79. "types": "img",
  80. "value": "https://picx.zhimg.com/v2-e439a1fe34f7542d5d02ad6502cf9b1c_720w.jpg?source=8673f162"
  81. }, {
  82. "types": "p",
  83. "value": " 虫子取食叶片 8 时 叶片 13 的电信号 https://www.zhihu.com/video/1185529031180599296 "
  84. }, {
  85. "types": "p",
  86. "value": "并且叶片 13 中这样一种表面电流变化(视频中红色),可以引起力的变化(蓝色线条)。"
  87. }, {
  88. "types": "p",
  89. "value": " 叶片 13 中表面电流和力的变化 https://www.zhihu.com/video/1185537839034454016 "
  90. }, {
  91. "types": "p",
  92. "value": "然而缺失 GLR的拟南芥突变体(glr3.3/glr3.6)以及木质部不规则的拟南芥突变体(irx)中,叶片 8 损伤后,叶片 13 的表面电信号变化幅度降低,叶片 13 的力也减小。说明昆虫取食后,损伤部位传递到未损伤部位的信息依赖于 GLR 和木质部。"
  93. }, {
  94. "types": "img",
  95. "value": "https://picx.zhimg.com/v2-3e07b122b2b13c16e5d602d31ecb8ef2_720w.jpg?source=8673f162"
  96. }, {
  97. "types": "p",
  98. "value": "虫子取食叶片 8 后,叶片 13 产生电流变化和力的变化,那这些变化可以促使拟南芥叶片运动吗?对叶片 13 进行监控,发现确实检测到持续至少 15 分钟的缓慢向下运动。"
  99. }, {
  100. "types": "p",
  101. "value": " 叶片 13 的运动 https://www.zhihu.com/video/1185542125135036416 "
  102. }, {
  103. "types": "p",
  104. "value": "该研究表明,昆虫取食造成的叶片维管束损伤会诱导生物电信号。该信号可以传递到未损伤部位,并使未损伤叶片产生电流变化,产生力的变化,进而运动,以做好防御避开伤害。且电信号和化学信号都在这一过程中发挥作用。"
  105. }, {
  106. "types": "p",
  107. "value": "因此,含羞草的运动模式可能不是独有的,这种运动很可能在植物界广泛存在。只是有些植物运动幅度大,运动较快,较为明显,而另一些植物运动幅度小,运动慢,不易察觉。"
  108. }, {
  109. "types": "p.strong",
  110. "value": "参考文献"
  111. }, {
  112. "types": "li",
  113. "value": "李合生.现代植物生理学.高等教育出版社."
  114. }, {
  115. "types": "li",
  116. "value": "Masatsugu T , Dirk S , Satoe S T , et al.Glutamate triggers long-distance, calcium-based plant defense signaling[J]. Science, 2018 DOI:10.1126/science.aat7744"
  117. }, {
  118. "types": "li",
  119. "value": "Kurenda A, Nguyen C T , Chételat A , et al. Insect-damaged Arabidopsis moves like wounded Mimosa pudica [J]. PNAS , 2019 DOI:10.1073/pnas.1912386116"
  120. }],
  121. "image": "https://picx.zhimg.com/v2-cc80c3a247493e21a9abec90841da138_fhd.jpg?source=8673f162",
  122. "message": "200 OK",
  123. "more": "",
  124. "title": "捕蝇草和含羞草的运动机制是什么,其他植物有这些机制吗,为什么其他植物受伤或触碰不会运动?"
  125. }

前端页面设计

  1. <template>
  2. <view>
  3. <view class="banner">
  4. <image class="banner-img" :src="article.image" mode="widthFix"></image>
  5. <view class="banner-title">{{ article.title }}</view>
  6. </view>
  7. <view class="article">
  8. <view class="author-info">
  9. <text>作者:{{ article.author }}</text>
  10. <text v-if="article.bio">,{{ article.bio }}</text>
  11. </view>
  12. <view class="content">
  13. <view v-for="(item, index) in article.content" :key="index">
  14. <view v-if="item.types === 'p'" class="paragraph">{{ item.value }}</view>
  15. <view v-else-if="item.types === 'p.strong'" class="strong-paragraph">{{ item.value }}</view>
  16. <image class="content-image" :src="item.value" mode="widthFix"></image>
  17. </view>
  18. </view>
  19. </view>
  20. </view>
  21. </template>

详情页接口实现

  1. // 知乎日报 列表页
  2. /**
  3. * date 日期 格式:yyyymmdd
  4. */
  5. export const getZhihuNewsList = async (date) => {
  6. try {
  7. console.log('getZhihuNewsList request');
  8. let date_ = date.replace(/-/g, '')
  9. const response = await uni.$http.get('/zhihunews/'+date_);
  10. console.log(response);
  11. if (response.statusCode !== 200) {
  12. uni.showToast({
  13. title: '数据请求失败! ',
  14. duration: 1500,
  15. icon: 'none',
  16. });
  17. return [];
  18. }
  19. return response.data;
  20. } catch (error) {
  21. console.error('Network request failed:', error);
  22. uni.showToast({
  23. title: '网络请求失败! ',
  24. duration: 1500,
  25. icon: 'none',
  26. });
  27. return [];
  28. }
  29. };
  30. export const getZhihuDetail = async (id) => {
  31. try {
  32. console.log('getZhihuDetail request');
  33. const response = await uni.$http.get('/zhihudetail/'+id);
  34. console.log(response);
  35. if (response.statusCode !== 200) {
  36. uni.showToast({
  37. title: '数据请求失败! ',
  38. duration: 1500,
  39. icon: 'none',
  40. });
  41. return [];
  42. }
  43. return response.data;
  44. } catch (error) {
  45. console.error('Network request failed:', error);
  46. uni.showToast({
  47. title: '网络请求失败! ',
  48. duration: 1500,
  49. icon: 'none',
  50. });
  51. return [];
  52. }
  53. };

 样式实现

CSS 样式定义了一个包含 banner、文章、标题、作者信息、内容段落和图片的页面布局。实现也简单,主要是这个banner图,实现了个标题悬浮在图片上的效果。

  1. <script>
  2. import { getZhihuDetail } from '@/api/zhihu.js';
  3. export default {
  4. data() {
  5. return {
  6. id:"",
  7. article:{}
  8. }
  9. },
  10. onLoad(params) {
  11. console.log('detail onload');
  12. console.log(params);
  13. this.id = params.id;
  14. },
  15. methods: {
  16. },
  17. mounted() {
  18. console.log("mounted")
  19. console.log(this.id)
  20. getZhihuDetail(this.id).then(result => {
  21. console.log("getZhihuDetail,result:");
  22. console.log(result);
  23. this.article = result;
  24. });
  25. }
  26. }
  27. </script>
  28. <style scoped>
  29. page {
  30. display: flex;
  31. flex-direction: column;
  32. box-sizing: border-box;
  33. background-color: #efeff4;
  34. min-height: 100%;
  35. height: auto;
  36. }
  37. .banner {
  38. position: relative;
  39. width: 100%;
  40. height: 550rpx;
  41. overflow: hidden;
  42. }
  43. .banner-img {
  44. position: absolute;
  45. width: 100%;
  46. height: auto;
  47. object-fit: cover;
  48. display: block;
  49. margin-bottom: 30rpx;
  50. }
  51. .banner-title {
  52. display: flex;
  53. align-items: center;
  54. position: absolute;
  55. padding: 0 15px;
  56. width: 100%;
  57. bottom: 10rpx;
  58. height: 110rpx;
  59. font-size: 30rpx;
  60. color: #fff;
  61. background: rgba(0, 0, 0, 0.4);
  62. overflow: hidden;
  63. box-sizing: border-box;
  64. }
  65. /* 文章容器样式 */
  66. .article {
  67. padding: 20rpx;
  68. font-family: Arial, sans-serif;
  69. }
  70. /* 标题样式 */
  71. .title {
  72. font-size: 24px;
  73. font-weight: bold;
  74. color: #333;
  75. margin-bottom: 10px;
  76. }
  77. /* 作者信息样式 */
  78. .author-info {
  79. font-size: 24rpx;
  80. color: #999;
  81. margin-top: 10px;
  82. margin-bottom: 20px;
  83. }
  84. /* 内容容器样式 */
  85. .content {
  86. margin-top: 10rpx;
  87. }
  88. /* 段落样式 */
  89. .paragraph {
  90. font-size: 30rpx;
  91. color: #666;
  92. line-height: 1.6;
  93. margin-bottom: 10rpx;
  94. }
  95. /* 粗体段落样式 */
  96. .strong-paragraph {
  97. font-size: 30rpx;
  98. color: #333;
  99. font-weight: bold;
  100. line-height: 1.6;
  101. margin-bottom: 10rpx;
  102. }
  103. /* 内容图片样式 */
  104. .content-image {
  105. width: 100%;
  106. height: auto;
  107. margin-bottom: 20rpx;
  108. }
  109. </style>

.banner

  1. - `position: relative;`:设置元素的定位方式为相对定位,这样其内部的绝对定位元素可以相对于它进行定位。
  2. - `width: 100%;`:设置元素的宽度为父容器的100%。
  3. - `height: 550rpx;`:设置元素的高度为550rpx(rpx是微信小程序中的一种单位,表示响应式像素)。
  4. - `overflow: hidden;`:隐藏超出元素框的内容。

.banner-img

  1. - `position: absolute;`:设置元素的定位方式为绝对定位,相对于最近的非static定位祖先元素进行定位。
  2. - `width: 100%;`:设置元素的宽度为父容器的100%。
  3. - `height: auto;`:设置元素的高度根据内容自动调整。
  4. - `object-fit: cover;`:设置图片的缩放方式,使其覆盖整个容器,同时保持图片的宽高比。
  5. - `display: block;`:将元素显示为块级元素。
  6. - `margin-bottom: 30rpx;`:设置元素的下边距为30rpx。

.banner-title

  1. - `display: flex;`:设置元素为弹性盒子布局,使其子元素可以灵活布局。
  2. - `align-items: center;`:设置弹性盒子中的子元素在交叉轴上居中对齐。
  3. - `position: absolute;`:设置元素的定位方式为绝对定位,相对于最近的非static定位祖先元素进行定位。
  4. - `padding: 0 15px;`:设置元素的内边距,上下为0,左右为15px。
  5. - `width: 100%;`:设置元素的宽度为父容器的100%。
  6. - `bottom: 10rpx;`:设置元素相对于父容器底部的距离为10rpx。
  7. - `height: 110rpx;`:设置元素的高度为110rpx。
  8. - `font-size: 30rpx;`:设置元素的字体大小为30rpx。
  9. - `color: #fff;`:设置元素的文字颜色为白色。
  10. - `background: rgba(0, 0, 0, 0.4);`:设置元素的背景颜色为半透明的黑色。
  11. - `overflow: hidden;`:隐藏超出元素框的内容。
  12. - `box-sizing: border-box;`:设置元素的盒模型为border-box,即内边距和边框包含在元素的宽度和高度内。

 .article

- `padding: 20rpx;`:设置元素的内边距为20rpx。

- `font-family: Arial, sans-serif;`:设置元素的字体为Arial,如果没有则使用无衬线字体。

 .strong-paragraph

  1. - `font-size: 30rpx;`:设置元素的字体大小为30rpx。
  2. - `color: #333;`:设置元素的文字颜色为深灰色。
  3. - `font-weight: bold;`:设置元素的字体加粗。
  4. - `line-height: 1.6;`:设置元素的行高为1.6倍字体大小。
  5. - `margin-bottom: 10rpx;`:设置元素的下边距为10rpx。

 .content-image

  1. - `width: 100%;`:设置元素的宽度为父容器的100%。
  2. - `height: auto;`:设置元素的高度根据内容自动调整。
  3. - `margin-bottom: 20rpx;`:设置元素的下边距为20rpx。

四、总结

通过本文的介绍,我们不仅学习了如何使用Vue 3结合微信小程序构建知乎日报详情页,还深入了解了从前端设计到开发调试的全过程。希望这篇文章能帮助你提升前端开发技能,为用户提供更优质的移动阅读体验。

最后附完成项目源码

资源下载地址:https://download.csdn.net/download/qq8864/89377440

https://download.csdn.net/download/qq8864/89377440

人到了一定年纪,你再去回首过往,曾经那些重大的时刻,我们也一步步咬紧牙关挺过去,一步步熬过许多最黑暗的日子,走到如今。关关难过,关关通过,一路上,我们也练就了一身的本领,也拥有一些处事不惊的能力和适应生活的心态。

杨绛先生说:“生活并非都是繁花锦簇,所有的好,不过是来自内心的知足,眼里的热爱,以及对万千世界删繁就简的态度。与独处相安,与万事言和。这烟火人间,事事值得,事事也遗憾。”

生活不可能都是鲜花和阳光,也充满无数的荆棘和坎坷,走过的每一段岁月,曾经都有美好照亮前行,也有一些遗憾留在心中。

生活总是喜忧参半,没有十全十美,万事只求半称心,所有的美好不过都是来自于懂得知足常乐。

生活都是在于选择之中,选择了一条路,注定也会失去另一条路的风景,遗憾是人生常态而已。不如充实自己,什么让你快乐,你就去做什么,不要非要去求什么意义。对我来说,虽然天色以晚,别人喜欢刷抖音,而我喜欢敲代码和写文字,简称码字。这使我快乐,我走在充实自己的路上,足以。

如果钓鱼的意义是为了吃鱼肉,那生活将是多么无趣。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/1021715
推荐阅读
相关标签
  

闽ICP备14008679号