Koa2 SSR打造官网PC展示页 2

本文档详细介绍了如何构建一个全栈轮播图系统,从数据库模型到服务端API,再到前端模板和控制器的实现。同时,还涵盖了推荐课程的数据获取和模板编写,展示了如何在Node.js环境中整合数据库查询、模板引擎和页面渲染。此外,还涉及了轮播图的自动化播放、事件绑定以及推荐课程的展示逻辑。
摘要由CSDN通过智能技术生成

四.获取轮播图数据以及父子模板拆分

(1).在services文件夹中新建slider.js

const SliderModel = require('../db/models/slider');
class SliderService{
    async getSliderData(){
        return await SliderModel.findAll({
            where:{status:1},
            attributes:{
                exclude:['cid','imgUrl','createdAt','updatedAt']
            }
        })
    }
}
module.exports = new SliderService();

(2).controllers中

const PAGE_CONF = require('../configs/page'),
      navData = require('../configs/nav');
const {getSliderData} = require('../services/slider')      
class Home{
    async index(ctx,next){
        const sliderData = await getSliderData();
        await ctx.render('index',{
            title:'首页',
            PAGE_CONF:PAGE_CONF.INDEX,
            navData,
            sliderData
        })
    }

(3).建立模板文件

在views中的templates中建立Index文件

再在其中建立carousel文件夹

其中建立index.ejs  indicator.ejs drector.ejs slider..ejs item.ejs

index.ejs中

<div class="carousel J_carousel">
    <%- include('slider.ejs',{sliderData}) %>
    <%- include('indicator.ejs',{len:sliderData.length}) %>
    <%- include('director.ejs')  %>
</div>

controller中导入七牛路径

const PAGE_CONF = require('../configs/page'),
      navData = require('../configs/nav'),
      {IMG_BASE_URL} = require('../configs/url');
const {getSliderData} = require('../services/slider')      
class Home{
    async index(ctx,next){
        const sliderData = await getSliderData();
        await ctx.render('index',{
            title:'首页',
            PAGE_CONF:PAGE_CONF.INDEX,
            navData,
            sliderData,
            IMG_BASE_URL
        })
    }

views下的index.ejs中

<%- include('layout/head.ejs', { PAGE_CONF }) %>


<div class="container">
    <%- include('template/common/header/index.ejs') %> 
    <%- include('template/index/carousel/index.ejs',{
        sliderData,
        IMG_BASE_URL
    }) %> 
</div>


<%- include('layout/foot.ejs', { PAGE_CONF }) %>

slider.ejs

<div class="slider-wrapper clearfix">
    <ul class="slider-list">
        <% for (let i = 0; i < sliderData.length; i++) {
            const item = sliderData[i];
            
         %> 
         <%- include('item.ejs',{i,item,IMG_BASE_URL})%>
        <% } %> 
    </ul>
</div>i

item.ejs

<li class="<%= !i ? 'slider-item current': 'slider-item' %> ">
    <a href="<%= item.href  %> " target="_balck">
        <img src="<%= IMG_BASE_URL +item.imgKey %> "
             alt="<%= item.title %> "
             class="slider-img"
        />
    </a>
    
</li>

index.js入口文件中导入样式

import '../styles/carousel.scss';

drector.ejs中

<button class="iconfont icon-arrow-left"></button>
<button class="iconfont icon-arrow-right"></button>

indicator.ejs

<div class="indicator clearfix"
    style="width:<%= 50 * len + 20 %>px;
           margin-left: <%= -( 50 * len + 20)/2 %>px;
    ">
<% for(var i = 0; i<len;i++){ %> 
    <i class="<%= !i ? 'indicator-item current' : 'indicator-item' %> "></i>
<% } %> 
</div>

五.轮播图配置、入口文件导入与模块编写

(1).src中的config/config.js

const URL = {
    IMG_BASE_URL: '//tximg.jsplusplus.com/'
}
const CAROUSEL = {
    duration:5000,
    autoplay:true
}
export{
    URL,
    CAROUSEL
}

(2).在src的modules中建立Carousel.js

import $ from 'jquery'
import {CAROUSEL} from '../config/config';
export default class Carousel{
    constructor(){
        this.$carousel = $('.J_carousel');
        this.$sliders = this.$carousel.find('.slider-item');
        this.$indicators = this.$carousel.find('.indicator-item');
        this.curIdx = 0;
    }
    init(){
        CAROUSEL.autoplay && this.autoPlay();
        this.bindEvent();
    }
    autoPlay(){
        Carousel.timer = setInterval(()=>{
            this.setIndex('next')
        },CAROUSEL.duration)
    }
    bindEvent(){

    }
    setIndex(direction){
        switch(direction){
            case 'next':
                this.curIdx = this.curIdx === this.$sliders.length - 1
                            ? 0
                            :this.curIdx +1
                break;
            case 'prev':
                this.curIdx = this.curIdx === 0
                ? this.$sliders.length - 1
                :this.curIdx - 1
                break;
            default:
                break;        
        }
        this.sliderAction(this.curIdx)
    }
    sliderAction(index){
        
            this.$sliders.eq(index).fadeIn(300).siblings().fadeOut(300);
            this.$indicators.eq(index).addClass('current').siblings().removeClass('current')
        
    }
}

入口文件导入模块

import $ from 'jquery';

import '../styles/resets.css';
import '../styles/common.css';
import '../styles/iconfont.css';
import '../styles/ui.scss';
import '../styles/header.scss';
import '../styles/carousel.scss';
import '../styles/mainTitle.scss';
import '../styles/recomCourse.scss';
import '../styles/collection.scss';
import '../styles/courseItem.scss';
import '../styles/teacher.scss';
import '../styles/footer.scss';
import Carousel from '../modules/Carousel';
;(($)=>{
    const init = () =>{
        new Carousel().init()
    }
    init();
})($);

在utils中的tools中写

function getTarget(ev){
    const e = ev || window.event;
    return e.target || e.srcElement;
}
function getEventType(ev){
    const e = ev || window.event;
    return e.type;
}
export{
    getTarget,
    getEventType
}

编写bindevent

导入并使用

bindEvent(){
        this.$carousel.on('nouseenter',$.proxy(this.mouseInOut,this))
        this.$carousel.on('nouseleave',$.proxy(this.mouseInOut,this))
        this.$carousel.on('click',$.proxy(this.onCarouseClick,this))
    }
    mouseInOut(ev){
        const tar = getTarget(ev),
              eventType = getEventType(ev);
        switch(eventType){
            case 'mouseenter':
                clearInterval(Carousel.timer)
                break;
            case 'mouseleave':
                CAROUSEL.autoplay && this.autoPlay();
                break;
            default:
                break;    
        }      
    }
    onCarouseClick(ev){
        const tar = getTarget(ev),
              className = tar.className;
        switch(className){
            case 'indicator-item':
                this.curIdx = $(tar).index;
                this.sliderAction(this.curIdx);
                break;
            case 'iconfont icon-arrow-right':
                this.setIndex('next');
                break;
            case 'iconfont icon-arrow-left':
                this.setIndex('prev');
                break;
            default:
                break;            
        }      
    }

六.获取推荐课程数据、推荐课程模板编写

1.service中新建RecomCourse.js

const RecomCourseModel = require('../db/models/recomCourse');
class RecomCourseService{
    async getRecomCourseData(){
        return  await RecomCourseModel.findAll({
            where:{status:1},
            attributes:{
                exclude:['cid','posterUrl','createdAt','updatedAt']
            }
        })
    }
}
module.exports = new RecomCourseService();

2.控制器中

const PAGE_CONF = require('../configs/page'),
      navData = require('../configs/nav'),
      {IMG_BASE_URL} = require('../configs/url');
const {getSliderData} = require('../services/slider'),
      {getRecomCourseData} = require('../services/recomcourse')
class Home{
    async index(ctx,next){
        const sliderData = await getSliderData(),
              recomCourseData = await getRecomCourseData();
        await ctx.render('index',{
            IMG_BASE_URL,
            title:'首页',
            PAGE_CONF:PAGE_CONF.INDEX,
            navData,
            sliderData,
            recomCourseData
            
        })
    }

3.在templates的index中新建recomCourse

建立index.ejs item.ejs

index.ejs

<div class="recom-course-board">
    <%  for(var i = 0; i < recomCourseData.length;i++){
        var item = recomCourseData[i];    
    %>
        <%- include('item.ejs',{item,IMG_BASE_URL}) %> 
    <% } %>      
</div>

item.ejs

<div class="recom-course-item">
    <div class="course-cover">
        <a 
          href="<%= item.href %>"
      class="course-lk"
      target="_blank"
        >
            <img 
              src="<%= IMG_BASE_URL + item.posterKey %>" 
              alt="<%= item.title %>"
              class="course-img"
            />
        </a>
    </div>
    <div class="course-info">
        <h1 class="course-tt">
            <a 
              href="<%= item.href %>"
              class="course-lk"
              target="_blank"
            >
              <%= item.title %>
            </a>
        </h1>
        <p class="course-desc"><%= item.description %></p>
        <div class="spread-info">
            <img 
              src="<%= IMG_BASE_URL + item.teacherImgKey %>" 
              alt="<%= item.teacherName %>"
              class="teacher-img"
            />
            <span class="teacher-name"><%= item.teacherName %></span>
            <i></i>
            <span class="count"><%= item.studentCount %>人正在学习</span>
        </div>
        <div class="price">¥<%= item.price %>.00</div>
        <div class="btn-wrap">
            <a 
              href="<%= item.href %>"
              class="btn btn-success"
              target="_blank"
            >
                立即报名
            </a>
            <a 
              href="http://wpa.qq.com/msgrd?v=3&uin=2697726307&site=qq&menu=yes"
              class="btn btn-search"
              target="_blank"
            >
                课程咨询
            </a>
        </div>
    </div>
</div>

index中导入

  <%- include('template/index/recomCourse/index.ejs',{
        recomCourseData,
        IMG_BASE_URL
    }) %> 

入口文件导入样式

import '../styles/recomCourse.scss';

import '../styles/recomCourse.scss';

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值