文章目錄
-
- 主體頭部
- 主體關鍵部分
-
- 小卡片元件
- 建立mock資料以及使用
主體頭部
![](https://img.laitimes.com/img/9ZDMuAjOiMmIsIjOiQnIsIyZuBnLjljMycTMiZzM0UWMwgjM5YjNyQjM2Q2M2YTOkFTYxU2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
主體部分顯示的内容,根據頭部點選的是留言牆還是照片牆的按鈕,顯示不同的内容。
将照片牆和留言牆要渲染的資料抽取到一個js中,在導入的
Main.vue
(主體頁面)中渲染。
将頁面中的文字記錄在
src/utils/data.js
中
// 牆的性質
// 這樣記錄後wallType[0]為留言牆内容 wallType[1]為照片牆内容
export const wallType = [
{
name: "留言牆",
slogan: "很多事情值得記錄,當然也值得回味。",
},
{
name: "照片牆",
slogan: "很多事情值得記錄,當然也值得回味。",
},
];
// 分類标簽
// label[0]為留言牆内容 label[1]為照片牆内容
export const label = [
[
"留言",
"目标",
"理想",
"過去",
"将來",
"愛情",
"親情",
"秘密",
"信條",
"無題",
],
[
"我",
"ta",
"喜歡的",
"有意義的",
"值得紀念的",
"母校",
"生活",
"天空",
"我在的城市",
"大海",
],
];
根據id渲染照片牆或留言牆& 點選标簽樣式切換 實作這兩個功能的
Main.vue
代碼為:
<template>
<div class="main">
<div class="message">
<p class="name">{{ wallType[id].name }}</p>
<p class="slogan">{{ wallType[id].slogan }}</p>
</div>
<div class="labels">
<ul>
<li :class="{ liselected: liIndex == -1 }" @click="changeIndex(-1)">
全部
</li>
<li
v-for="(item, index) in label[id]"
:key="index"
@click="changeIndex(index)"
:class="{ liselected: liIndex == index }"
>
{{ item }}
</li>
</ul>
</div>
</div>
</template>
<script>
import { wallType, label } from "@/utils/data";
import { ref } from "vue";
export default {
setup() {
let id = ref(0); // 留言牆id為0 之後做事件使得id為1
let liIndex = ref(-1); // 目前選中狀态小li的下标
const changeIndex = (index) => {
liIndex.value = index;
};
return {
wallType,
label,
id,
liIndex,
changeIndex,
};
},
};
</script>
<style lang="scss" scoped>
.main {
margin-top: 52px;
.message {
padding-top: 46px;
.name {
font-size: 56px;
color: $gray-1;
font-weight: 600;
}
.slogan {
font-size: 14px;
color: $gray-3;
padding-bottom: 44px;
}
}
.labels {
padding: 0 400px;
ul {
display: flex;
justify-content: space-around;
align-items: center;
li {
font-size: $font-14;
color: $gray-3;
}
.liselected {
display: flex;
align-items: center;
justify-content: center;
width: 56px;
height: 28px;
border: 1px solid rgba(32, 32, 32, 1);
border-radius: 14px;
color: $gray-1;
}
}
}
}
</style>
主體關鍵部分
主體部分渲染許多留言卡片
小卡片元件
卡片元件有不同的背景顔色,目前時間 留言标簽,跟主體部分的label對應,主要留言内容,點贊數量,評論數量,發表人。
資料:
卡片背景顔色
時間
标簽
内容
點贊數量
評論數量
發表人
這些資料可以通過Mock出來,不過這裡先靜态寫死好樣式,再mock
⭐️實作效果:
代碼:
components/MyNote/MyNote.vue
<template>
<div class="my-note">
<div class="top">
<span class="time">2022.11.20</span>
<span class="label">留言</span>
</div>
<p class="content">
這是一段暖心的話,它或許不長,但是它是我現在最想說的。放在這裡就留一個紀念吧,不用回頭看,應為現在才是當下最好的。這是一段暖心的話,它或許不長,但是它是我現在最想說的。
</p>
<div class="bottom">
<div class="left">
<div class="like">
<i class="iconfont icon-xiai"></i>
<span>12</span>
</div>
<div class="comment">
<i class="iconfont icon-liuyan"></i>
<span>4</span>
</div>
</div>
<span class="right">Zemoz</span>
</div>
</div>
</template>
<script>
export default {};
</script>
<style lang="scss" scoped>
.my-note {
width: 288px;
height: 240px;
background: rgba(255, 227, 148, 0.3);
padding: 10px $pd-20;
box-sizing: border-box;
.top {
display: flex;
justify-content: space-between;
font-size: $font-12;
}
.content {
font-size: $font-14;
text-align: left;
padding: $pd-20 0;
}
.bottom {
display: flex;
justify-content: space-between;
padding-top: 30px;
.left {
display: flex;
.like {
margin-right: $pd-8;
}
.iconfont {
color: $gray-3;
margin-right: $pd-4;
}
span {
color: $gray-3;
font-size: $font-14;
}
}
.right {
font-size: $font-14;
color: $gray-1;
}
}
}
</style>
Main.vue
中使用
<template>
<div class="main">
<main class="mainbody">
<my-note-vue></my-note-vue>
</main>
</div>
</template>
<script>
import { wallType, label } from "@/utils/data";
import { ref } from "vue";
import MyNoteVue from "@/components/MyNote/MyNote.vue";
export default {
components: {
MyNoteVue,
},
};
</script>
<style>
.mainbody {
padding: 30px;
}
</style>
建立mock資料以及使用
yarn add mockjs --save
src/mock/index.js
let Mock = require("mockjs");
// 留言note
export const note = Mock.mock({
"data|19": [
{
// 建立時間
moment: new Date(),
// id
"id|+1": 1,
// userid
"userId|+1": 10,
// 内容
"message|24-96": "@cword",
// 标簽label
"label|0-9": 0,
// name
name: "@cname",
// like
"like|0-120": 0,
// 評論
"comment|0-120": 0,
// 背景顔色
"imgurl|0-4": 0,
// 是否撤銷
"revoke|0-20": 0,
// 是否舉報
"report|0-20": 0,
// 類型
type: 0,
},
],
});
顯示效果為:
此時
Main.vue
<template>
<div class="main">
<div class="message">
<p class="name">{{ wallType[id].name }}</p>
<p class="slogan">{{ wallType[id].slogan }}</p>
</div>
<div class="labels">
<ul>
<li :class="{ liselected: liIndex == -1 }" @click="changeIndex(-1)">
全部
</li>
<li
v-for="(item, index) in label[id]"
:key="index"
@click="changeIndex(index)"
:class="{ liselected: liIndex == index }"
>
{{ item }}
</li>
</ul>
</div>
<main class="mainbody">
<div class="blocks">
<my-note-vue
v-for="(item, i) in note.data"
:key="i"
:note="item"
class="note"
></my-note-vue>
</div>
</main>
</div>
</template>
<script>
import { wallType, label } from "@/utils/data";
import { ref } from "vue";
import MyNoteVue from "@/components/MyNote/MyNote.vue";
import { note } from "@/mock/index";
export default {
components: {
MyNoteVue,
},
setup() {
let id = ref(0); // 留言牆id為0 之後做事件使得id為1
let liIndex = ref(-1); // 目前選中狀态小li的下标
const changeIndex = (index) => {
liIndex.value = index;
};
return {
wallType,
label,
id,
liIndex,
changeIndex,
note,
};
},
};
</script>
<style lang="scss" scoped>
.main {
box-sizing: border-box;
margin-top: 52px;
// width: 1500px;
// margin: auto;
.message {
padding-top: 46px;
.name {
font-size: 56px;
color: $gray-1;
font-weight: 600;
}
.slogan {
font-size: 14px;
color: $gray-3;
padding-bottom: 44px;
}
}
.labels {
padding: 0 400px;
ul {
display: flex;
justify-content: space-around;
align-items: center;
li {
font-size: $font-14;
color: $gray-3;
// transition: all 0.3s;
}
.liselected {
display: flex;
align-items: center;
justify-content: center;
width: 56px;
height: 28px;
border: 1px solid rgba(32, 32, 32, 1);
border-radius: 14px;
color: $gray-1;
}
}
}
.mainbody {
padding-top: 30px;
width: 99%;
margin: auto;
box-sizing: border-box;
.blocks {
width: calc(100% + 12px);
margin-left: -12px;
display: flex;
flex-wrap: wrap;
.note {
margin-bottom: 10px;
margin-left: 12px;
}
}
}
}
</style>
MyNote.vue
<template>
<div class="my-note">
<div class="top">
<span class="time">2022.11.20</span>
<span class="label">{{ label[card.type][card.label] }}</span>
</div>
<p class="content">
{{ card.message }}
</p>
<div class="bottom">
<div class="left">
<div class="like">
<i class="iconfont icon-xiai"></i>
<span>{{ card.like }}</span>
</div>
<div class="comment">
<i class="iconfont icon-liuyan"></i>
<span>{{ card.comment }}</span>
</div>
</div>
<span class="right">{{ card.name }}</span>
</div>
</div>
</template>
<script>
import { label } from "@/utils/data";
import { toRef, onMounted } from "vue";
export default {
props: ["note"],
setup(props) {
let card = toRef(props, "note");
onMounted(() => {
console.log(card);
});
return {
label,
card,
};
},
};
</script>
<style lang="scss" scoped>
.my-note {
width: 288px;
height: 240px;
background: rgba(255, 227, 148, 0.3);
padding: 10px $pd-20;
box-sizing: border-box;
.top {
display: flex;
justify-content: space-between;
font-size: $font-12;
}
.content {
font-size: $font-14;
text-align: left;
padding-top: $pd-20;
width: 100%;
height: 140px;
}
.bottom {
display: flex;
justify-content: space-between;
padding-top: $pd-20;
.left {
display: flex;
.like {
margin-right: $pd-8;
}
.iconfont {
color: $gray-3;
margin-right: $pd-4;
}
span {
color: $gray-3;
font-size: $font-14;
}
}
.right {
font-size: $font-14;
color: $gray-1;
}
}
}
</style>
具體改動代碼——可檢視gitee