天天看點

Vue3留言牆項目——主體部分靜态、mock

文章目錄

    • 主體頭部
    • 主體關鍵部分
      • 小卡片元件
      • 建立mock資料以及使用

主體頭部

Vue3留言牆項目——主體部分靜态、mock
Vue3留言牆項目——主體部分靜态、mock

主體部分顯示的内容,根據頭部點選的是留言牆還是照片牆的按鈕,顯示不同的内容。

将照片牆和留言牆要渲染的資料抽取到一個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

⭐️實作效果:

Vue3留言牆項目——主體部分靜态、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,
    },
  ],
});
           

顯示效果為:

Vue3留言牆項目——主體部分靜态、mock

此時

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

繼續閱讀