使用nuxt,express,mysql,nginx创建个人博客系列-17

238
2020-01-24 18:37
10 个月前

首先我们写一下博客列表页面咯

首先我们来看看博客列表页面
目录:pages/articles/index.vue 这个会生成一个vue路由 /articles

<template>
  <section class="container" v-if="result">
    <div class="content-wrap clearfix">
      <div class="content">
        <article class="excerpt clearfix" 
        :class="{'excerpt-img':item.articles_img}" 
         v-for="(item,index) in result.data.articles" 
         :key="item+index">
          <div class="excerpt-img-box" v-if="item.articles_img">
            <nuxt-link :to="`/${item.id}`" class="excerpt-img-href" >
              <img :src="item.articles_img" alt="">
            </nuxt-link>
          </div>
          <header>
            <nuxt-link class="label" :to="`/category/${item.category_id}`">{{item.category_name}}</nuxt-link>
            <h2><nuxt-link :to="`/${item.id}`">{{item.title}}</nuxt-link></h2>
          </header>
          <p class="note">{{item.introduction}}</p>
        </article>
        <div class="pagination" v-if="result.data.pageCount>1">
           <ul>
             <li v-for="(item,index) in result.data.pageCount" :key="item+index">
               <nuxt-link v-if="item != result.data.curPage" :to="{name:'articles',query:{page:item}}" >{{item}}</nuxt-link>
               <span v-else>{{item}}</span>
             </li>
           </ul>
        </div>
      </div>
    </div>
    <my-right :tags="result.data.tags"></my-right>
  </section>
</template>

<script>
import axios from "~/plugins/axios";
import MyRight from '~/components/Right.vue';
export default {
  asyncData({ params, query,error }) {
    let url = '/api/allData';
    if(query.page){
      url = `/api/allData?page=${query.page}`;
    }
    return axios
      .get(url)
      .then(resp => {
        let { data } = resp;
        return { result: data };
      })
      .catch(e => {
        error({ statusCode: 500, message: `${e}` });
      });
  },
  components:{
    MyRight
  }
};
</script>

我们来看看请求的api/allData是怎么实现的
目录:server/api/index.js

import articles from './articles'
router.use(articles)

引入articles,所以我们去看看articles.js怎么实现


目录:server/api/articles.js

import {
  Router
} from 'express'
const router = Router();
import _ from 'lodash'
import mysql from '../libs/mysql';
import util from '../util';
let tagsSql = `select t.name ,t.id, t.articles_num from tags as t 
              where t.deleted_at is null
              order by t.articles_num desc`;
/* GET users listing. */
router.get('/allData', async (req, res, next) => {
  try {
    let myConnect = await mysql.getConnect();
    let sql = `select SQL_CALC_FOUND_ROWS a.title, a.articles_img ,a.id ,a.introduction ,a.category_id 
              ,c.name as category_name,t.name as tag_name from articles as a 
              left join category as c on a.category_id = c.id 
              left join tags as t on a.tag_id = t.id
              where a.deleted_at is null
              order by a.updated_at desc limit ? ; SELECT FOUND_ROWS()`;
    let count = 10;
    let page = 1;
    let sqlParams = null;
    let tagParams = null;
    if(+req.body.page){
      page = +req.body.page;
    }
    let offset = (page-1)*count;
    sqlParams = [offset,count]

    if(req.body.tag_id){
      sql = `select SQL_CALC_FOUND_ROWS a.title, 
      a.articles_img ,a.id ,a.introduction ,a.category_id ,
      c.name as category_name,t.name as tag_name from articles as a
      left join category as c on a.category_id = c.id 
      left join tags as t on a.tag_id = t.id 
      where a.deleted_at is null 
      and t.id = ${myConnect.escape(req.body.tag_id)} 
      order by a.updated_at desc limit ? ; SELECT FOUND_ROWS()`;
    }
    if(req.body.category_id){
      sql = `select SQL_CALC_FOUND_ROWS a.title, a.articles_img ,a.id ,a.introduction ,a.category_id ,
      c.name as category_name,t.name as tag_name from articles as a 
      left join category as c on a.category_id = c.id 
      left join tags as t on a.tag_id = t.id 
      where a.deleted_at is null and c.id = ${myConnect.escape(req.body.category_id)}
       order by a.updated_at desc limit ? ; SELECT FOUND_ROWS()`;

    }
    let tags = await mysql.query(myConnect, tagsSql);
    let articles = await mysql.query(myConnect,sql,sqlParams);
    let resultCount = articles[1][0]['FOUND_ROWS()'];
    await mysql.release(myConnect);
    res.send(util.resSuccess({
      data: {
        articles:articles[0],
        tags,
        count:resultCount,
        curPage:page,
        pageCount :Math.ceil(resultCount / count)
      }
    }))
  } catch (error) {
    next(error);
  }
})
router.get('/article/:id', async (req, res, next) => {
  try {
    let myConnect = await mysql.getConnect();
    let sql = `select a.title,a.user_id, a.articles_img, a.keyword ,a.id ,a.introduction,a.content ,a.category_id ,a.tag_id 
              from articles as a where id = ? limit 1`;
    let tags = await mysql.query(myConnect, tagsSql);
    let articles = await mysql.query(myConnect, sql,req.params.id);
    let commentSql = `SELECT id,p_id,content,username,email,created_at 
                      FROM comments 
                      WHERE articles_id = ? AND p_id = 0 order by created_at desc`;
    let commentFirstResult = await mysql.query(myConnect,commentSql,req.params.id);
    let childCommentSql = `SELECT id,p_id,content,username,email,created_at FROM comments 
                            WHERE articles_id = ? AND p_id <> 0 order by created_at desc`;
    let childCommentResult = await mysql.query(myConnect,childCommentSql,req.params.id); 
    await mysql.release(myConnect);
    _.map(commentFirstResult,(item)=>{

      let child =zTree(item.id)
      item.commentList = child
      // item.child = 
    });
    function zTree(pid){
      let child = []
      if(!childCommentResult.length){
        return child;
      }
      child = _.remove(childCommentResult,(childItem)=>{
        return childItem.p_id == pid
      })
      if(child.length){
        _.map(child,(item)=>{
          item.commentList = zTree(item.id)
        })
      }
      return child;
    }
    if(articles.length){
      res.send(util.resSuccess({
        data: {
          item:articles[0],
          tags,
          comment:commentFirstResult,
          // childComment:childCommentResult
        }
      }))
    }
  } catch (err) {
    next(err)
  }
})

此时可以看到网站首页是这样的了
articles.vue


大家看到图肯定疑问头部怎么实现的呢? 这里面有个layouts的目录,修改一下这个文件就可以把所有页面的头部改成公共的
目录:layouts/default.vue

<template>
  <div>
    <my-header/>
    <nuxt/>
  </div>
</template>

<script>
import MyFooter from '~/components/Footer.vue'
import MyHeader from '~/components/header.vue'

export default {
  components: {
    MyFooter,
    MyHeader
  }
}
</script>
<style lang="scss">
@import '../assets/css/mixins.scss';
.header{
  padding:10px;
  background: #494961;
  .logo{
    color:#fff;
    float:left;
    @include xsmall{
      float:none;
      text-align:center;
    } 
  }
  .header-nav{
    color:#fff;
    float: right;
     @include xsmall{
        float:none;
        text-align:center;
     }
  }
}
.button, .button:visited
{
  display: inline-block;
  color: black;
  letter-spacing: 1px;
  background-color: #fff;
  border: 2px solid #000;
  text-decoration: none;
  text-transform: uppercase;
  padding: 15px 45px;
}

.button:hover, .button:focus
{
  color: #fff;
  background-color: #000;
}

.title
{
  color: #000;
  font-weight: 300;
  font-size: 2.5em;
  margin: 0;
}
</style>

上面引入了mixins.scss,所以我们要添加这个mixins文件 目录:assets/css/mixins.scss

$xsmall-break:768px;
@mixin xsmall(){
  @media screen and (max-width: $xsmall-break) {
    @content;
  }
}
@mixin minxsmall(){
  @media screen and (min-width: 320px) and (max-width: $xsmall-break) {
    @content;
  }
}
@mixin minsmall414(){
  @media screen and (max-width: 414px) {
    @content;
  }
}
@mixin small(){
  @media screen and (min-width: $xsmall-break) {
    @content;
  }
}
@mixin smallh800(){
  @media screen and (max-height: 800px) {
    @content;
  }
}
@mixin lgallh1280(){
    @media screen and (max-height: 1280px) {
        @content;
    }
}
// ip4
@mixin max320(){
   @media screen and (max-width: 320px) {
    @content;
   }
}
// ip6
@mixin max375(){
   @media screen and (min-width: 321px)  and (max-width: 375px){
    @content;
   }
}
// ip6plus
@mixin max414(){
   @media screen and (min-width: 376px) and (max-width: 414px){
    @content;
   }
}
// ipad
@mixin max768(){
   @media screen and (min-width: 415px) and (max-width: 768px){
    @content;
   }
}
//大于ipad
@mixin min768(){
   @media screen and (min-width: 769px){
    @content;
   }
}

提示(因为你用了scss的文件,计算机是不认识这个写法的,所以需要使用sass_loader,sass_loader又是基于node-sass,所以要npm install node-sass,windows使用sass比较困难,需要安装ruby,可自行百度。不行可留言给我)


上一篇-使用nuxt,express,mysql,nginx创建个人博客系列-16
下一篇-使用nuxt,express,mysql,nginx创建个人博客系列-18