5.首页模块
5.1构建首页
- 步骤一:创建 ~/pages/index.vue页面
- 步骤二:复制静态index.html页面到 index.vue中,并修改js和css引用方式
<template>
<div>
<!-- 复制需要的index.html,此处省略 html原有内容 -->
</div>
</template>
<script>
export default {
head: {
title: '首页',
link: [
{rel:'stylesheet',href: '/style/index.css'},
{rel:'stylesheet',href: '/style/bottomnav.css'}
],
script: [
{ type: 'text/javascript', src: '/js/header.js' },
{ type: 'text/javascript', src: '/js/index.js' },
]
}
}
</script>
<style>
</style>
- 步骤三:引入已有公共组件
<template>
<div>
<!-- 顶部导航 start -->
<TopNav></TopNav>
<!-- 顶部导航 end -->
<div style="clear:both;"></div>
<!-- 头部 start -->
<!-- 省略 html原有内容 -->
<!-- 底部导航 end -->
<div style="clear:both;"></div>
<!-- 底部版权 start -->
<Footer></Footer>
<!-- 底部版权 end -->
</div>
</template>
<script>
import TopNav from '../components/TopNav'
import Footer from '../components/Footer'
export default {
head: {
title: '首页',
link: [
{rel:'stylesheet',href: '/style/index.css'},
{rel:'stylesheet',href: '/style/bottomnav.css'}
],
script: [
{ type: 'text/javascript', src: '/js/header.js' },
{ type: 'text/javascript', src: '/js/index.js' },
]
},
components: {
TopNav,
Footer
},
}
</script>
<style>
</style>
-
步骤四:将所有“头部”抽取到“HeaderSearch”组件
-
1)修改图片路径
-
步骤五:将所有“底部导航”抽取“BottomNav”组件
-
步骤六:修改 ~/pages/index.vue,添加“HeaderSeach”和“BottomNav”组件
<template>
<div>
<!-- 顶部导航 start -->
<TopNav></TopNav>
<!-- 顶部导航 end -->
<div style="clear:both;"></div>
<!-- 头部 start -->
<HeaderSearch></HeaderSearch>
<!-- 头部 end-->
<div style="clear:both;"></div>
<!--
省略 html原有内容
-->
<div style="clear:both;"></div>
<!-- 底部导航 start -->
<BottomNav></BottomNav>
<!-- 底部导航 end -->
<div style="clear:both;"></div>
<!-- 底部版权 start -->
<Footer></Footer>
<!-- 底部版权 end -->
</div>
</template>
<script>
import TopNav from '../components/TopNav'
import Footer from '../components/Footer'
import HeaderSearch from '../components/HeaderSearch'
import BottomNav from '../components/BottomNav'
export default {
head: {
title: '首页',
link: [
{rel:'stylesheet',href: '/style/index.css'},
{rel:'stylesheet',href: '/style/bottomnav.css'}
],
script: [
{ type: 'text/javascript', src: '/js/header.js' },
{ type: 'text/javascript', src: '/js/index.js' },
]
},
components: {
TopNav,
Footer,
HeaderSearch,
BottomNav
},
}
</script>
<style>
</style>
5.2快报
- 5.2.1接口
GET http://localhost:10010/web-service/news?pageNum=1&pageSize=5&sortWay=desc
- 5.2.2后端实现:JavaBean
- 步骤一:修改pojo项目,创建分页基类 PageRequest
package com.czxy.changgou4.vo;
import lombok.Data;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@Data
public class PageRequest {
private Integer pageNum; //当前页
private Integer pageSize; //每页条数
private Integer limit; //限制条数
private Integer offset; //偏移
private String sortBy; //排序字段
private String sortWay; //排序方式(asc | desc)
}
- 步骤二:修改pojo项目,创建NewsVo类,继承PageRequest类
- NewsVo在PageRequest基础上,进行特殊定制。如果不需要任何增强,可以直接使用PageRequest
package com.czxy.changgou4.vo;
import lombok.Data;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@Data
public class NewsVo extends PageRequest {
}
- 步骤三:根据数据库表创建News对象
package com.czxy.changgou4.pojo;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.util.Date;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@TableName("tb_news")
@Data
public class News {
@TableId
private Integer id;
@TableField(value = "title")
private String title;
@TableField(value = "content")
private String content;
@TableField(value = "author")
private String author;
@TableField(value = "created_at")
private Date createdAt;
@TableField(value = "updated_at")
private Date updatedAt;
}
- 5.2.3后端实现:查询功能
- 步骤一:创建mapper
package com.czxy.changgou4.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czxy.changgou4.pojo.News;
import org.apache.ibatis.annotations.Mapper;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@Mapper
public interface NewsMapper extends BaseMapper<News> {
}
- 步骤二:创建service接口
package com.czxy.changgou4.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.czxy.changgou4.pojo.News;
import com.czxy.changgou4.vo.NewsVo;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
public interface NewsService extends IService<News> {
/**
* 查询所有新闻
* @param newsVo
* @return
*/
public Page<News> findAll(NewsVo newsVo);
}
- 步骤三:创建service实现类,按照创建时间,根据排序方式进行排序
package com.czxy.changgou4.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.czxy.changgou4.mapper.NewsMapper;
import com.czxy.changgou4.pojo.News;
import com.czxy.changgou4.service.NewsService;
import com.czxy.changgou4.vo.NewsVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@Service
@Transactional
public class NewsServiceImpl extends ServiceImpl<NewsMapper, News> implements NewsService {
@Override
public Page<News> findAll(NewsVo newsVo) {
//1 条件
QueryWrapper<News> queryWrapper = new QueryWrapper<News>();
if("asc".equals(newsVo.getSortWay())) {
queryWrapper.orderByAsc("created_at");
} else {
queryWrapper.orderByDesc("created_at");
}
//2 分页
Page<News> page = new Page<>(newsVo.getPageNum(), newsVo.getPageSize());
//3 查询
baseMapper.selectPage(page, queryWrapper);
return page;
}
}
- 步骤四:修改controller
package com.czxy.changgou4.controller;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.czxy.changgou4.pojo.News;
import com.czxy.changgou4.service.NewsService;
import com.czxy.changgou4.vo.BaseResult;
import com.czxy.changgou4.vo.NewsVo;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@RestController
@RequestMapping("/news")
public class NewsController {
@Resource
private NewsService newsService;
@GetMapping
public BaseResult findAll(NewsVo newsVo){
//1 查询
Page<News> page = this.newsService.findAll( newsVo );
//2 封装
return BaseResult.ok("成功", page);
}
}
5.2.4前端实现
- 步骤一:编写服务端apiserver.js
- 步骤二:编写服务端apiserver.js,修改nuxt.config.js 配置仅服务器可用
plugins: [
{ src: '~plugins/apiclient.js',mode: 'client'},
{ src: '~plugins/apiserver.js'},
],
- 步骤三:修改“apiserver.js”,查询快报
const request = {
//快报
findNews : () => {
return axios.get('/web-service/news' , {
params : {
pageNum : 1,
pageSize : 8 ,
sortWay : 'asc'
}
})
}
}
var axios = null
export default ({ $axios, redirect, process }, inject) => {
//赋值
axios = $axios
//4) 将自定义函数交于nuxt
// 使用方式1:在vue中,this.$request.xxx()
// 使用方式2:在nuxt的asyncData中,content.app.$requestServer.xxx()
inject('requestServer', request)
}
- 步骤四:修改首页 index.vue,服务端查询快报
async asyncData( { app } ) {
let { data } = await app.$requestServer.findNews()
return {
newsList : data.data.records
}
},
- 步骤五:遍历数据
<!-- 偶数显示 odd 样式 -->
<li v-for="(n,index) in newsList" :title="n.title" :key="index" :class="{'odd': index%2==0 }">
<a href="">{{n.title}}</a>
</li>
- 步骤六:优化,超过的字符串显示“…”
<style>
.news li a {
display: block; /* 当前元素本身是inline的,因此需要设置成block模式 */
white-space: nowrap; /* 因为设置了block,所以需要设置nowrap来确保不换行 */
overflow: hidden; /* 超出隐藏结合width使用截取采用效果*/
text-overflow: ellipsis; /* 本功能的主要功臣,超出部分的剪裁方式 */
-o-text-overflow: ellipsis; /* 特定浏览器前缀 */
text-decoration: none; /* 无用 */
}
</style>
5.3分类
- 5.3.1接口
GET http://localhost:10010/web-service/categorys
- 5.3.2后端实现:JavaBean
package com.czxy.changgou4.pojo;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@TableName("tb_category")
@Data
public class Category {
@TableId
private Integer id;
@TableField(value = "cat_name")
@JsonProperty("cat_name")
private String catName;
@TableField(value = "parent_id")
@JsonProperty("parent_id")
private Integer parentId;
@TableField(value = "is_parent")
@JsonProperty("is_parent")
private Boolean isParent;
//当前分类具有的所有孩子
@TableField(exist = false)
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<Category> children = new ArrayList<>();
}
- 5.3.3后端实现:查询
- 步骤一:创建mapper
package com.czxy.changgou4.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czxy.changgou4.pojo.Category;
import org.apache.ibatis.annotations.Mapper;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@Mapper
public interface CategoryMapper extends BaseMapper<Category> {
}
- 步骤二:创建service接口, 添加查询所有方法
package com.czxy.changgou4.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.czxy.changgou4.pojo.Category;
import java.util.List;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
public interface CategoryService extends IService<Category> {
/**
* 查询所有一级分类,每一个分类中含子分类
* @return
*/
public List<Category> findAll();
}
- 步骤三:创建service实现类,按照parentId升序排序,并将所有的分类进行按照级别进行处理。
package com.czxy.changgou4.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.czxy.changgou4.mapper.CategoryMapper;
import com.czxy.changgou4.pojo.Category;
import com.czxy.changgou4.service.CategoryService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@Service
@Transactional
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {
@Override
public List<Category> findAll() {
//1 条件
QueryWrapper<Category> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByAsc("parent_id");
//2 查询所有
List<Category> findList = baseMapper.selectList(queryWrapper);
//2 存放所有的一级分类
List<Category> list = new ArrayList<>();
// 3.1 存放每一个分类(此分类将来要做父分类的)
Map<Integer , Category> cache = new HashMap<>();
for (Category category : findList) {
//2.1 过滤所有一级 parentId==0
if(category.getParentId() == 0){
list.add( category );
}
//3.2 向map存一份
cache.put( category.getId() , category );
//3.3 获得当前父分类
Category parentCategory = cache.get( category.getParentId() );
if( parentCategory != null) {
parentCategory.getChildren().add( category );
}
}
//2.2 返回处理结果
return list;
}
}
- 步骤四:创建controller
package com.czxy.changgou4.controller;
import com.czxy.changgou4.pojo.Category;
import com.czxy.changgou4.service.CategoryService;
import com.czxy.changgou4.vo.BaseResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.List;
/**
* @author 桐叔
* @email liangtong@itcast.cn
*/
@RestController
@RequestMapping("/categorys")
public class CategoryController {
@Resource
private CategoryService categoryService;
@GetMapping
public BaseResult findAll(){
//1 查询
List<Category> list = categoryService.findAll();
//2 封装
return BaseResult.ok("查询成功" , list );
}
}
5.3.4前端实现
- 步骤一:修改“apiserver.js”,查询所有分类
//查询所有分类
findCategorys : () => {
return axios.get("/web-service/categorys")
}
- 步骤二:修改index.vue,使用asyncData查询分类
- asyncData函数只能在 pages 目录下使用
async asyncData( { app } ) {
// 查询快报 + 查询分类
let [{data:newsData}, {data: categoryData}] = await Promise.all([
app.$requestServer.findNews(),
app.$requestServer.findCategorys()
])
return {
newsList : newsData.data.records,
categorysList : categoryData.data
}
},
- 步骤三:修改index.vue,将查询的结果,通过属性传递给组件
<!-- 头部 start -->
<HeaderSearch :list="categorysList"></HeaderSearch>
<!-- 头部 end-->
- 步骤四:修改组件,声明list属性
export default {
props: {
isFirst: { //是否是首页
type: Boolean,
default: true
},
list: { //数据
type: Array
}
}
}
- 步骤五:遍历数据
<div class="cat " :class="{'item1': k1==0 }" v-for="(c1,k1) in list" :key="k1">
<h3><a href="">{{c1.cat_name}}</a> <b></b></h3>
<div class="cat_detail none">
<dl :class="{'dl_1st' : k2==0}" v-for="(c2,k2) in c1.children" :key="k2">
<dt><a href="">{{c2.cat_name}}</a></dt>
<dd>
<nuxt-link :to="'list/' + c3.id" v-for="(c3,k3) in c2.children" :key="k3">{{c3.cat_name}}</nuxt-link>
</dd>
</dl>
</div>
</div>