Node系列学习之简单博客前台(三)

233 阅读1分钟

这是我参与更文挑战的第23天,活动详情查看:更文挑战

今天完成了博客详情页面, 并且与后端数据联调成功~

话不多说,先看一下效果图:

image-20210623233312157

因为现在还没有新建的页面, 所以数据的话可能有点尴尬...

先将就着看下, 等新建页面弄好后就可以了~

关键文件

src/BlogList/index.vue

<template>
  <div class="blog-list">
    <h1>Tmier的博客</h1>
    <div class="tmier-list-item" v-for="item in dataList">
      <div class="content-item">
        <div class="content-item-header">
          <div class="item-info">
            <span class="header-author">{{item.author}}</span>
            <span class="dividing">|</span>
            <span class="header-public-time">{{item.createtime | Time}}</span>
          </div>
          <div class="tags-list">
            <div class="tag-item">前端</div>
            <div class="tag-item">Node</div>
          </div>
        </div>
        <div class="item-title">{{item.title}}</div>
        <div class="main-row">
          <div class="main-box">
            <div class="abstract">{{item.abstract}}</div>
          </div>
          <div class="cover-img">
            <img :src="imgURL" alt />
          </div>
        </div>
      </div>
      <div class="right-box">
        <h3>推荐指数</h3>
        <el-rate v-model="value" disabled text-color="#ff9900" :max="9" score-template="{value}"></el-rate>
      </div>
    </div>
    <div class="fixed-button">
      <el-button type="primary" size="small">写文章</el-button>
      <el-button type="primary" size="small">管理后台</el-button>
    </div>
  </div>
</template>

<script>
//import x from ''
import { getBlogListAPI } from '@/api/blog.js'
export default {
  components: {},
  data() {
    return {
      dataList: [],
      value: 9,
      imgURL: 'http://oss.emier.cn/images/20210622232101.png'
    }
  },
  computed: {},
  created() {
    this.getListData()
  },
  methods: {
    async getListData() {
      try {
        const res = await getBlogListAPI()
        if (res.errno == 0) {
          this.dataList = res.data || []
        }
      } catch (error) {
        console.log(error);
      }
    }
  }
}
</script>

<style lang='scss' scoped>
//@import url()
.blog-list {
  width: 100%;
  height: 100%;
  text-align: center;
  // padding-top: 30px;
  background: #f4f5f5;
  overflow-y: auto;
  box-sizing: border-box;
  .tmier-list-item {
    width: 960px;
    display: flex;
    margin: 0 auto;
    // height: 100%;
    .content-item {
      width: 700px;
      height: 170px;
      background: #fff;
      cursor: pointer;
      border-bottom: 1px solid #e5e6eb;
      box-sizing: border-box;
      padding: 16px 20px 0;
      text-align: left;
      &:hover {
        background: #fafafa;
      }
      .content-item-header {
        display: flex;
        justify-content: space-between;
        align-items: center;
        font-size: 14px;
        .item-info {
          .header-author {
            margin-right: 10px;
            opacity: 0.81;
          }
          .dividing {
            margin-right: 10px;
            height: 18px;
            overflow: hidden;
            opacity: 0.3;
            font-size: 14px;
          }
          .header-public-time {
            opacity: 0.6;
          }
        }
        .tags-list {
          display: flex;
          .tag-item {
            flex-shrink: 0;
            margin-left: 8px;
            padding: 0 8px;
            background: #fafafa;
            border-radius: 2px;
            font-size: 14px;
            line-height: 22px;
            color: #4e5969;
          }
        }
      }
      .item-title {
        text-align: left;
        margin-top: 14px;
        margin-bottom: 12px;
        font-size: 18px;
      }
      .main-row {
        width: 100%;
        padding-bottom: 16px;
        display: flex;
        .main-box {
          flex-grow: 1;
          display: flex;
          flex-direction: column;
          align-items: flex-start;
          .abstract {
            margin-bottom: 14px;
            font-size: 14px;
            line-height: 22px;
            overflow: hidden;
            text-overflow: ellipsis;
            display: -webkit-box;
            -webkit-line-clamp: 3;
            -webkit-box-orient: vertical;
            color: #4e5969;
            height: 70px;
          }
        }
        .cover-img {
          flex: 0 0 auto;
          width: 142px;
          height: 80px;
          margin-left: 16px;
          background-color: #fff;
          border-radius: 2px;
          img {
            width: 100%;
            height: 100%;
            object-fit: cover;
          }
        }
      }
    }
    .right-box {
      margin-left: 2px;
      width: 250px;
      height: 170px;
      background: #fff;
      cursor: pointer;
      border-bottom: 1px solid #e5e6eb;
      box-sizing: border-box;
    }
  }
  .fixed-button {
    position: fixed;
    right: 50px;
    top: 30px;
  }
}
</style>

src/api/blog.js

import request from '@/utils/request.js'
export function getBlogListAPI(params = {}) {
  return request({
    url: '/api/blog/list',
    method: 'get',
    params
  })
}

关于时间的处理

使用了dayjs来处理, 简单封装了个Vue过滤器

安装
npm install dayjs --save
使用与封装

src/filters/index.js

const dayjs = require('dayjs')
require('dayjs/locale/zh-cn') // 使用中文
dayjs.locale('zh-cn') 
const relativeTime = require('dayjs/plugin/relativeTime')
dayjs.extend(relativeTime)
function transformTime(timestamp = +new Date()) {
  if (timestamp) {
    return dayjs(timestamp).fromNow()
  } else {
    return ''
  }
}

export const Time = value => {
  return transformTime(value)
}

src/plugins/index.js

import Vue from 'vue' //Vue引入
import * as glofilter from '@/filters/index.js' // 全局过滤器
//遍历注册过滤器
Object.keys(glofilter).forEach(item => Vue.filter(item, glofilter[item]))

然后将 plugins/index.js 放入 main.js中使用.

main.js

...
import './plugins'
...
使用过滤器
...
<span class="header-public-time">{{item.createtime | Time}}</span>
...

今天先写到这里了, 刚刚发现接口那有点问题, 改接口了去了~