前言
-
时间:2021.8.3
-
内容:
- 关于jQuery,导入路径和一个踩坑点
- 小众网前端,点击不同分类显示对应的列表。
-
备注:
- 其实这几天的学习基本都是前面小结的反复横跳,连不太熟练的jQuery也摸清了些。
- 本篇后半部分主要是理一理,小众网前端首页的制作过程。还是有点乱乱的,再摸索吧…
关于jQuery
- 想记录一下关于jQuery的使用,主要因为自己之前踩了太多的坑,每次都只能看缘分保佑不要搞出bug,但对于新手孩子来说怎么可能呢!这里就几个问题稍微提一下~(以下只是我的理解,如果需要更官方的说法,左拐去百度百科
jQuery是什么东西呢?
- 可以看作是前辈们用Js语言写了个框架,然后封装起来,给我们更方便去使用的东西。
jQuery怎么使用呢?
-
追溯到原生js的使用,假如是直接在页面写js,是一个一个方法堆砌起来的:要么用到时候搞个点击或者失焦调用一下,要么onload让页面加载时候调用。比如:
<script type="text/javascript"> function f() { ... }; function f1() { ... }; function f2() { ... }; ...... </script>
-
jQuery的使用,以下方为例:
<script type="text/javascript" src="resources/js/jquery-3.6.0.min.js"></script> <script type="text/javascript"> $(function () { $('#insertCustomer').click(function () { alert("hh") $.ajax({ url:"insertCustomer", data:$('#frm').serialize(), type:'get', dataType:'json', success:function (data) { alert("okk:"+data.result) } }) }) }) </script>
导入路径
- 前面说了它是被封装起来的一个js框架,那么我们必须要引用到包才行(下方第一句),引用的路径比较难搞。
- 在我的研究下,找到了下方这种最方便的路径(加项目名之类的也可以,…/这种不稳定试不出来)
- 怎么检验是不是我说的这个路径呢?假如在resources前面加个/之后,idea里这一段的背景黄色会消失掉,能够点进去,那么应该就是我说的方便路径了。
- 顺便提一下js的全局路径:src/main/webapp/resources/jquery.3.3.1.min.js
以及ftl的全局路径:src/main/webapp/WEB-INF/ftl/index.ftl - 至于为啥会这样呢?明明背景不报警告黄的看起来正确的路径,访问页面时候却查不到,反而是去掉/的下方这种形式的路径可以正常访问呢?明明在一定程度上绝对路径和相对路径是可以相对转换的,为什么…/这种形式总是找不到合适的路径呢?以及加上项目名怎么样才能确保这是一个可以访问的路径呢?以上是我困惑的,目前还没找到结论的,咱现在的目的只是为了导入个jQuery包嘛,那就按照我这个方法来去导就好了(不然真的找事儿…但如果知道原理、原因的话,还是欢迎分享啦~
踩坑点
-
jQuery以$()这种形式为标志,如果分不清用的原生js还是jQuery,直接看有没有这个美元符号就好啦~
-
最外面那个$(function () {}是在网页一加载时候就调用到的,不可以漏掉噢!往中间填充多少的事件都没关系,用分号隔开就行,但不能像元素js那样每个方法都裸露在最外面,必须要有个罩在最外面,以保证页面加载时候能加载出来这些。我之前没加外面的罩时候,里面连alert都出不来。对啦,初学不会网页端打断点的,alert弹窗和console.log打印在控制台的方法贼好用!(虽然我学挺久了也不太会网页端的debug…
-
另外ajax是一种特殊使用,用于前后端交互,同样不能裸露在最外面,外衣看起来和点击失焦是类似的,区别就在于传递数据的部分,这里稍微记录下。
-
url:假如触发了这个ajax,系统会去你的控制器Controller里找同名的map路径(如果其他配置是没问题的话)
-
data:传过去的数据,可以是任何的数据,例子里给的是表单序列化的数据。通俗来说,就是定位到指定id的表单form,在触发该ajax时候,自动搜刮表单里所有的数据,序列化打包好。
-
type:数据传输的方式,这个用get、post影响都不大,但是在控制器Controller里注解时候必须是同样的。
-
dataType:数据打包好,以什么样的类型传输过去,目前使用到过text和json之类的。
-
success:function(data){} 这里的data是控制器对应方法返回的数据,我比较熟悉map的用法,控制器里用map.put(“result”,…)的方式把获得到的后台数据放到result里,前端这里可以用data.result获得相应的数据。(其他的不是特别清楚,主要是没有手动试过…懒鬼。为了看的清楚一点,再把控制器的代码放上来对照看吧:
@Controller public class CustomerController { @Autowired private CustomerService customerService; @GetMapping("/") public ModelAndView index() { ModelAndView mav = new ModelAndView("/index"); List<Customer> customerList = customerService.selectAll(); mav.addObject("customerList", customerList); return mav; } @GetMapping("/insertCustomer") @ResponseBody public void insertCustomer(Customer customer){ customerService.insert(customer); System.out.println("---添加客户成功---"); } }
-
- 前面说了它是被封装起来的一个js框架,那么我们必须要引用到包才行(下方第一句),引用的路径比较难搞。
五个如何任务
1 如何看到首页?
-
备注
- 首先,我们一开始是有一个比较完善的静态首页页面的。
- 通过网页访问到这个静态首页页面,主要是用到了最近几天练习的ssm。
- 后端的处理主要分为配置文件、java包这两部分,配置文件通过一些操作把各个java文件链接起来。
-
总结过程(附代码):
-
(web.xml) tomcat跑起来,web.xml、applicationContext.xml即可加载(为整个项目创造一个背景)
<load-on-startup>1</load-on-startup>
<init-param> <param-name>contextConfigLocation</param-name> <param-value>classpath:applicationContext.xml</param-value> </init-param>
-
(applicationContext.xml) 访问http://localhost:8080/页面时,根据applicationContext.xml里的扫描包,去扫描java包下带@Service和@Controller的文件
<context:component-scan base-package="com.pro"/>
-
(BookController.java) 在含有@Controller注解的控制器类中,查找符合访问页面的方法,单纯的斜杠代表直接访问上面这个地址就会到这个方法。这个方法做了两个操作:
@GetMapping("/") public ModelAndView a() { List<Category> categoryList = categoryService.selectAll(); ModelAndView mav = new ModelAndView("/index"); mav.addObject("categoryList", categoryList); return mav; }
-
(CategoryServiceImpl.java) 一是用注入的categoryService调用自定义业务方法selectAll()获得分类列表。
public List<Category> selectAll() { QueryWrapper<Category> queryWrapper = new QueryWrapper<>(); List<Category> categoryList = categoryDao.selectList(queryWrapper); return categoryList; }
-
(BookDao.java) 而该业务方法是通过注入的categoryDao去调用baomidou里的查询方法。
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.pro.domain.Book; public interface BookDao extends BaseMapper<Book> { }
-
(applicationContext.xml) 数据获取完毕,回到控制器类。二是在视图映射的帮助下,去找到同名(index)的的ftl文件。
<property name="suffix" value=".ftl"/>
-
-
2 如何显示所有类别?
-
前面说到,在访问路径时候,已经做了那个把数据填入视图的操作。
mav.addObject("categoryList", categoryList);
-
那么我们只需要在前端用list遍历显示这个类别数组的元素就好。(这里把暂时不说的类给删了,后面写到再说)
<#list categoryList as category> <a style="cursor: pointer" data-category="${category.categoryId}">${category.categoryName}</a> <#if category_has_next>|</#if> </#list>
3 如何分页显示图书?
-
分页显示图书需要从service层的业务方法开始着手。
@Service @Transactional(propagation = Propagation.NOT_SUPPORTED,readOnly = true) public class BookServiceImpl implements BookService { @Autowired private BookDao bookDao; /** * 分页 * @param categoryId 分类 * @param order 排序 * @param page 页码 * @param rows 页显示行数 * @return 分页对象 */ public IPage<Book> pageing(Long categoryId, String order, Integer page, Integer rows) { Page<Book> p = new Page<>(page,rows); QueryWrapper<Book> queryWrapper = new QueryWrapper<>(); //类别已选,可以加入sql中 if(categoryId!=null && categoryId!=-1){ queryWrapper.eq("categoryId",categoryId); } //按条件加入排序的sql if(order!=null){ if("quantity".equals(order)){ queryWrapper.orderByDesc("evaluationQuantity"); }else if("score".equals(order)){ queryWrapper.orderByDesc("evaluationScore"); } } Page<Book> bookPage = bookDao.selectPage(p, queryWrapper); return bookPage; } }
-
查到啥就显示啥,前端请求一次,后端查下一页,返回给前端新页面显示,如此反复,直到查完。
如果没查完,就显示”加载下一页“的按钮;查完了,就显示”已经到底部“。
if(data.current<data.pages){ //将隐藏域中的值+1 $('#nextPage').val(parseInt(data.current)+1); $('#btnMore').show(); $('#divNoMore').hide(); } else { $('#btnMore').hide(); $('#divNoMore').show(); }
-
如果是第一次加载,就要清空页面列表,初始化"下一页"为1。
if(isFirst==true){ $('#bookList').html(""); $('#nextPage').val(1); }
4 类别或排序规则如何高亮?
//设置选中的类型,高亮显示
$(".category").click(function () {
//移除所有类别元素的高亮样式
$('.category').removeClass('highlight');
$('.category').addClass('text-black-50');
$(this).addClass('highlight');
//高亮之后还有真正的目的。data-category="-1"
//得到你点击高亮的类别的值
var categoryId = $(this).data('category');
//将你得到的这个类别id,赋值给隐藏域,以便我们提交到接口
$("#categoryId").val(categoryId);
//点击类别,发送ajax请求
page1(true);
});
//按热度和评分来排序,选中的高亮显示
$(".order").click(function () {
$('.order').removeClass('highlight');
$('.order').addClass('text-black-50');
$(this).addClass('highlight');
//得到热度或评分 data-order="quantity"
var order = $(this).data("order");
//设置隐藏域的排序规则
$('#order').val(order);
//点击热度或评分,发送ajax请求
page1(true);
})
-
为同一层级的类别设置同一个class=“category”,为排序规则设置同一个class=“order”
-
当点击到某类别或者某排序规则时,为所有的该类添加一个淡化字体的方法text-black-50
.text-black-50 { color: rgba(0, 0, 0, 0.5) !important; }
-
并且随机为点击到的这个类别或者排序规则,增加一个自定义高亮样式highlight即可
.highlight { color: red !important; }
5 如何按照分类、排序,实现查询?
- 同3,后端根据从前端拿到的类别order、排序order需求,去查出需要的数据。(没写完,太困了。。直接看代码吧
前端代码汇总
<#-- ajax请求数据 -->
<script type="text/javascript">
//初始化星形图片目录
$.fn.raty.defaults.path="./resources/raty/lib/images";
//1次是加载页,1次是点按钮时
function page1(isFirst) {
if(isFirst==true){
$('#bookList').html("");
$('#nextPage').val(1);
}
//取得隐藏域的值
var nextPage = $('#nextPage').val();
//从隐藏域中获取类别及排序
var categoryId = $('#categoryId').val();
var order = $('#order').val();
$.ajax({
url:"books",
data:{"nextPage":nextPage,"categoryId":categoryId,"order":order},
type:'get',
dataType:'json',
success:function (data) {
//console.log(data)
//拿到集合
var bookList = data.records;
for (var i = 0; i < bookList.length; i++) {
var book = bookList[i];
/*var html = '<li>'+ book.bookName +'</li>';
//将得到的图书,追加到图书列表的后面
$('#bookList').append(html);*/
//使用模板,将取出的book对象送入模板中赋值
var html = template('bookTemplate', book);
$('#bookList').append(html);
}
//$(".stars").raty();
$(".stars").raty({readOnly:true});
if(data.current<data.pages){
//将隐藏域中的值+1
$('#nextPage').val(parseInt(data.current)+1);
$('#btnMore').show();
$('#divNoMore').hide();
} else {
$('#btnMore').hide();
$('#divNoMore').show();
}
}
})
};
$(function () {
//加载页面时
page1(true);
});
$(function () {
//点击加载更多,即下一页
$('#btnMore').click(function () {
page1()
});
//设置选中的类型,高亮显示
$(".category").click(function () {
//移除所有类别元素的高亮样式
$('.category').removeClass('highlight');
$('.category').addClass('text-black-50');
$(this).addClass('highlight');
//高亮之后还有真正的目的。data-category="-1"
//得到你点击高亮的类别的值
var categoryId = $(this).data('category');
//将你得到的这个类别id,赋值给隐藏域,以便我们提交到接口
$("#categoryId").val(categoryId);
//点击类别,发送ajax请求
page1(true);
});
//按热度和评分来排序,选中的高亮显示
$(".order").click(function () {
$('.order').removeClass('highlight');
$('.order').addClass('text-black-50');
$(this).addClass('highlight');
//得到热度或评分 data-order="quantity"
var order = $(this).data("order");
//设置隐藏域的排序规则
$('#order').val(order);
//点击热度或评分,发送ajax请求
page1(true);
})
});
</script>
<#-- 定义一个js模板 -->
<script type="text/html" id="bookTemplate">
<!-- 一个图书 begin -->
<a href="/book/{{bookId}}" style="color: inherit">
<div class="row mt-2 book">
<div class="col-4 mb-2 pr-2">
<img class="img-fluid" src="./resources/images/{{cover}}">
</div>
<div class="col-8 mb-2 pl-0">
<h5 class="text-truncate">{{bookName}}</h5>
<div class="mb-2 bg-light small p-2 w-100 text-truncate">{{author}}</div>
<div class="mb-2 w-100">{{subTitle}}</div>
<p>
<#-- 第1个span是5个星 -->
<span class="stars" data-score="{{evaluationScore}}" title="gorgeous">
<#--<img alt="1" src="./resources/raty/lib/images/star-on.png" title="gorgeous">
<img alt="2" src="./resources/raty/lib/images/star-on.png" title="gorgeous">
<img alt="3" src="./resources/raty/lib/images/star-on.png" title="gorgeous">
<img alt="4" src="./resources/raty/lib/images/star-on.png" title="gorgeous">
<img alt="5" src="./resources/raty/lib/images/star-on.png" title="gorgeous">
<input name="score" type="hidden" value="{{evaluationScore}}" readonly="">-->
</span>
<#-- 第2个span是评分 -->
<span class="mt-2 ml-2">{{evaluationScore}}</span>
<#-- 第3个span是多少人评论 -->
<span class="mt-2 ml-2">{{evaluationQuantity}}人已评</span>
</p>
</div>
</div>
</a>
</script>