[Day 20] 实作-主题推荐页面 组件传递资料

好的~ 首页完成了,接下来就换主题推荐页面啦

记取之前的教训,这次先上UI图!

UI图

https://ithelp.ithome.com.tw/upload/images/20211005/20140745gMNbJoKu00.png

设计概念

我有先参考了一下 主题推荐API 的内容,格式如下:

{
    "title": "期间限定!报名从速,解封後不复见"
    "note": "短短几个月,我们的生活模式已被改变,\r\n学习、获得新知,不一定需要面对面。\r\n开学啦!同学们,线上见!",
    "issue": [...],
}

参数说明

Title : 主题

Note : 主题说明

issue : 符合主题的所有活动

所以最上方会放Title,大图片右侧放 note,下方的活动列表就是issue里的资料


ok 开工啦!

建立新页面

在 /src/components 里新增 TopicPage.vue

WebStorm其实有个建立特定档案的功能

在资料夹右键 > New > 可以看到有多个档案类型可以选,这边选择 Vue Component

https://ithelp.ithome.com.tw/upload/images/20211005/20140745Splqf7o7bR.png

输入档案名称,不用加 .vue

https://ithelp.ithome.com.tw/upload/images/20211005/20140745TGt6oxsSQ4.png

建好一个Vue标准格式+带好预设名字的component啦~

https://ithelp.ithome.com.tw/upload/images/20211005/20140745nWf4RNSANG.png

新增 router

回到 /router/index.js

在上方import TopicPage页面,然後在routes里加上TopicPage的路径

import Vue from 'vue';
import Router from 'vue-router';
import HelloWorld from '@/components/HelloWorld';
import HomePage from '@/components/HomePage';
import TopicPage from '@/components/TopicPage'; //加这个

Vue.use(Router);

export default new Router({
  routes: [
    {
      path: '/',
      name: 'HelloWorld',
      component: HelloWorld,
    },
    {
      path: '/home',
      name: 'home',
      component: HomePage,
    },
    //加入路径
    {                 
      path: '/topic',
      name: 'topic',
      component: TopicPage,
    },
  ],
});

新增资料

有需要原始资料可到 主题推荐API 获取,这边因为篇幅关系,仅保留一笔 issue

TopicPage.vue

<script>
export default {
  name: 'TopicPage',
  data() {
    return {
      title: '期间限定!报名从速,解封後不复见',
      note: '短短几个月,我们的生活模式已被改变,\r\n学习、获得新知,不一定需要面对面。\r\n开学啦!同学们,线上见!',
      issue:
      [
        {
          version: '1.4',
          UID: '6139d19eaaa3cf0fc41b991f',
          title: '达人讲座x苏滢无所畏敢输才会赢',
          category: '7',
          showInfo: [
            {
              time: '2021/09/28 19:00:00',
              location: '台中市线上zoom平台',
              locationName: '线上zoom平台',
              onSales: 'N',
              price: '',
              latitude: null,
              longitude: null,
              endTime: '2021/09/28 20:00:00',
            },
          ],
          showUnit: '歌伦比亚美语顾问',
          discountInfo: '免费',
          descriptionFilterHtml: '在你的小小心中也有个大大的梦想,但是却觉得很遥远吗?\r\n或是你正在前往梦想目标的过程中,快要被现实打败了?\r\n来吧~ 苏滢有些话想要跟你分享!\r\n\r\n在成为网红KOL之前的苏滢,\r\n曾经是个在梦想与现实之间挣扎的舞台剧演员。\r\n除了将过去打拼的历程写进新书「苏滢无所畏 敢输才会赢」以外,\r\n也诚挚地邀请您一同来和苏滢线上面对面聊聊如何拥有面对失败的勇气。',
          imageUrl: 'https://cloud.culture.tw/e_new_upload/cms/image/A0/B0/C0/D9/E171/F926/54220f2d-f0f3-47f3-8ceb-a18359f2ecff.jpg',
          masterUnit: [
            '歌伦比亚美语顾问',
          ],
          subUnit: [
            'https://www.facebook.com/%E8%98%87%E7%80%85-Suri-771188916397653',
          ],
          supportUnit: [],
          otherUnit: [],
          webSales: 'https://www.clue.com.tw/webinars/LandingPage/Get/NmLH6',
          sourceWebPromote: 'https://www.clue.com.tw/webinars/LandingPage/Get/NmLH6',
          comment: '',
          editModifyDate: '',
          sourceWebName: '王怡苹',
          startDate: '2021/09/28',
          endDate: '2021/09/28',
          hitRate: 13,
        },
				... 这边有约17笔资料,篇幅关系只保留一笔,其他先省略
      ],
    };
  },
};
</script>

新增Title及图片

TopicPage.vue

<template>
  <v-container>
    <h1>{{title}}</h1> <!-- 渲染title字段 -->
    <v-row>
      <v-col sm="8"> <!-- 插入图片 -->
        <v-img
          :src="require('../assets/topic_img.png')"
        ></v-img>
      </v-col>
      <v-col sm="4"> <!-- 渲染note字段 -->
        <div class="align-center text-left note">
          <h2>{{note}}</h2>
        </div>
      </v-col>
    </v-row>
  </v-container>
</template>

目前成果

https://ithelp.ithome.com.tw/upload/images/20211005/20140745nUsSz1gYn5.png


接下来就是重头戏啦~

活动清单里有多笔资料,如果我们每一笔都写一次程序,会产生大量的重复code

这时候就可以把这种会重复使用的东西做成Component,

只要传不同的资料进去,就会依照格式渲染出画面

话不多说,做看看就知道了!

组件的基本概念可参考官方文件

建立子Componet

首先照上面的步骤新增一个 Topic.vue

然後要把这个子组件放到在TopicPage.vue里

<template>
...
	<v-row>
		...
		<v-col sm="4">
		     <Topic></Topic>  <!-- Topic子组件 -->
		</v-col>
	</v-row>
...
</template>

<script>
import Topic from './Topic'; // 记得要先import
export default {
  name: 'TopicPage',
  components: { Topic }, // 有使用到那些子component
...
}
...
</script>

一样先找一个Vuetify的范例来改

这次用这个v-card的 范例

https://ithelp.ithome.com.tw/upload/images/20211005/20140745fq2m37blUS.png

把它放到Topic.vue里

<template>
  <v-card
    class="mx-auto"
    max-width="400"
  >
    <v-img
      class="white--text align-end"
      height="200px"
      src="https://cdn.vuetifyjs.com/images/cards/docks.jpg"
    >
      <v-card-title>Top 10 Australian beaches</v-card-title>
    </v-img>

    <v-card-subtitle class="pb-0">
      Number 10
    </v-card-subtitle>

    <v-card-text class="text--primary">
      <div>Whitehaven Beach</div>

      <div>Whitsunday Island, Whitsunday Islands</div>
    </v-card-text>

    <v-card-actions>
      <v-btn
        color="orange"
        text
      >
        Share
      </v-btn>

      <v-btn
        color="orange"
        text
      >
        Explore
      </v-btn>
    </v-card-actions>
  </v-card>
</template>

看看效果

https://ithelp.ithome.com.tw/upload/images/20211005/20140745YdFVainwub.png

好像有点样子了喔~


父组件传递资料到子组件

我们原始资料放在TopicPage.vue里,但是渲染是在Topic.vue,这样要怎麽拿到资料呢?

Vue都帮你想好了!

最简单的单向绑定就是在父层把资料绑定给组件,在子层用props把资料接过来

那接过来的props是不能做修改的

组件资料传递可参考 官方文件这篇

直接实做看看,因为我们的 issue 是一个 List 格式,而我们每次只需要传递List的其中一笔资料就好

我们先利用 v-for 逐笔取出List,再一个一个塞到Topic组件里

TopicPage.vue

<v-col 
	sm="4"
  v-for="item in issue"
  :key="item.UID"
>
     <Topic :topic="item"></Topic>
</v-col>

Topic.vue

<template>
...
	<v-img
      class="white--text align-end"
      height="200px"
      src="https://cdn.vuetifyjs.com/images/cards/docks.jpg"
    >
      <v-card-title>{{topic.title}}</v-card-title> <!-- 把本来的card title 改成渲染 topic的title -->
    </v-img>
...
</template>

<script>
export default {
  name: 'Topic',
  props: ['topic'], //接收父组件传来的值
}
</script>

成果

https://ithelp.ithome.com.tw/upload/images/20211005/20140745CxutClI8S9.png

成功~ 这样子组件就有接收到资料了!

明天再来改造一下子组件,让他符合我的需求


<<:  不只懂 Vue 语法:试解释嵌套路由与嵌套命名视图的概念?

>>:  19 - Remote - Containers - 在容器中开发

[Day - 17 ] - Spring 导入选择器原理与开发

Abstract 我们前面已经讨论了相当多种取得Bean的方法,如:自动注入(@Autowired、...

Day 4 - Using Argon2 for Salted Password Hashing with ASP.NET Web Forms C# 使用 Argon2 替密码加盐後杂凑加密

=x= 🌵 User Manager - Content Page 替後台管理者密码加盐加密。 密码...

《老师爱说故事,专家爱讲模型》

这本书内容少少的,但我划的重点跟思考颇多。 例如我们因为模型常要复杂但又易懂,最终得到的归纳就是那些...

[day20]谈购物流程设计

本来想除了管理功能外全部都在Line介面里面解决,但做了一阵子觉得越想越不对劲,重新考量了一下思路,...