09-搜索前端开发-搜索页面
09-搜索前端开发-搜索页面
3 搜索前端开发
3.1 搜索页面
3.1.1 需求分析
上图是课程搜索前端的界面,用户通过前端向服务端发起搜索请求,搜索功能包括:
1、界面默认查询所有课程,并分页显示
2、通过一级分类和二分类搜索课程,选择一级分类后将显示下属的二级分类
3、通过关键字搜索课程
4、通过课程等级搜索课程
3.1.2 页面布局
nuxt.js将/layout/default.vue作为所有页面的默认布局,通常布局包括:页头、内容区、页尾
default.vue内容如下:
<template>
<div>
<Header />
<nuxt/>
<Footer />
</div>
</template>
<script>
import Footer from '../components/Footer.vue'
import Header from '../components/Header.vue'
export default {
components: {
Header,
Footer
}
}
</script>
<style>
</style>
3.1.3 Nginx代理配置
搜索页面中以/static开头的静态资源通过nginx解析,如下:
/static/plugins:指向门户目录下的plugins目录。
/static/css:指向门户目录下的的css目录
修改Nginx中www.xuecheng.com虚拟主机的配置:
location / {
alias E:/java_www/xcEduUI05/;
index index.html index.htm;
}
location /static/img/ {
alias E:/java_www/xcEduUI05/img/;
}
location /static/css/ {
alias E:/java_www/xcEduUI05/css/;
}
location /static/js/ {
alias E:/java_www/xcEduUI05/js/;
}
location /static/plugins/ {
alias E:/java_www/xcEduUI05/plugins/;
add_header Access-Control‐Allow‐Origin http://ucenter.xuecheng.com;
#add_header Access‐Control‐Allow‐Credentials true;
#add_header Access‐Control‐Allow‐Methods GET;
}
配置搜索Url,下图是Nginx搜索转发流程图
用户请求/course/search时Nginx将请求转发到nuxt.js服务,nginx在转发时根据每台nuxt服务的负载情况进行转
发,实现负载均衡。
本教程开发环境Nuxt.js服务和www.xuecheng.com虚拟机主在同一台计算机,使用同一个nginx,配置如下:
#前端门户课程搜索
location ^~ /course/search {
proxy_pass http://dynamic_portal_server_pool;
}
#后端搜索服务
location /openapi/search/ {
proxy_pass http://search_server_pool/search/;
}
#分类信息
location /static/category/ {
proxy_pass http://static_server_pool;
}
dynamic_portal_server_pool配置如下 :
#前端动态门户
upstream dynamic_portal_server_pool{
server 127.0.0.1:10000 weight=10;
}
#后台搜索(公开api)
upstream search_server_pool{
server 127.0.0.1:40100 weight=10;
}
其它配置:
#开发环境webpack定时加载此文件
location ^~ /__webpack_hmr {
proxy_pass http://dynamic_portal_server_pool/__webpack_hmr;
}
#开发环境nuxt访问_nuxt
location ^~ /_nuxt/ {
proxy_pass http://dynamic_portal_server_pool/_nuxt/;
}
在静态虚拟主机中添加:
#学成网静态资源
server {
listen 91;
server_name localhost;
#分类信息
location /static/category/ {
alias F:/develop/xuecheng/static/category/;
}
...
nginx的配置文件全部代码如下:
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
#cms页面预览
upstream cms_server_pool{
server 127.0.0.1:31001 weight=10;
}
#静态资源服务
upstream static_server_pool{
server 127.0.0.1:91 weight=10;
}
#前端动态门户
upstream dynamic_portal_server_pool{
server 127.0.0.1:10000 weight=10;
}
#后台搜索(公开api)
upstream search_server_pool{
server 127.0.0.1:40100 weight=10;
}
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
#门户的顶级域名,门户的主站
server {
listen 80;
server_name www.xuecheng.com;
ssi on;
ssi_silent_errors on;
location / {
alias E:/java_www/xcEduUI05/;
index index.html index.htm;
}
location /static/img/ {
alias E:/java_www/xcEduUI05/img/;
}
location /static/css/ {
alias E:/java_www/xcEduUI05/css/;
}
location /static/js/ {
alias E:/java_www/xcEduUI05/js/;
}
location /static/plugins/ {
alias E:/java_www/xcEduUI05/plugins/;
add_header Access-Control‐Allow‐Origin http://ucenter.xuecheng.com;
#add_header Access‐Control‐Allow‐Credentials true;
#add_header Access‐Control‐Allow‐Methods GET;
}
#页面预览
location /cms/preview/ {
proxy_pass http://cms_server_pool/cms/preview/;
}
location /static/company/ {
proxy_pass http://static_server_pool;
}
location /static/teacher/ {
proxy_pass http://static_server_pool;
}
location /static/stat/ {
proxy_pass http://static_server_pool;
}
location /course/detail/ {
proxy_pass http://static_server_pool;
}
#前端门户课程搜索
location ^~ /course/search {
proxy_pass http://dynamic_portal_server_pool;
}
#后端搜索服务
location /openapi/search/ {
proxy_pass http://search_server_pool/search/;
}
#分类信息
location /static/category/ {
proxy_pass http://static_server_pool;
}
#开发环境webpack定时加载此文件
location ^~ /__webpack_hmr {
proxy_pass http://dynamic_portal_server_pool/__webpack_hmr;
}
#开发环境nuxt访问_nuxt
location ^~ /_nuxt/ {
proxy_pass http://dynamic_portal_server_pool/_nuxt/;
}
}
#学成网静态资源
server {
listen 91;
server_name localhost;
#公司信息
location /static/company/ {
alias E:/java_www/xcEduUI05/static/company/;
}
#老师信息
location /static/teacher/ {
alias E:/java_www/xcEduUI05/static/teacher/;
}
#统计信息
location /static/stat/ {
alias E:/java_www/xcEduUI05/static/stat/;
}
location /course/detail/ {
alias E:/java_www/xcEduUI05/course/detail/;
}
location /static/category/ {
alias E:/java_www/xcEduUI05/static/category/;
}
}
}
3.1.4 搜索页面
创建搜索页面如下:
将index_1.vue文件代码复制到index.vue中。
页面文件参考:“资料”–》“search”–》index_1.vue,重要代码如下:
nuxt.js支持定义header,本页面我们在header中引入css样式并定义头部信息。
<template>
<div>
<div class="learing-list">
<div class="list-box">
<ul>
<li>关键字ss:</li>
<ol>
<li>{{keyword}}
<nuxt-link v-if="keyword" class="title-link" :to="'/course/search?keyword=&mt='+mt+'&st=' + st+'&grade='+grade">
Χ
</nuxt-link>
</li>
</ol>
</ul>
<ul>
<li>一级分类:</li>
<li v-if="mt!=''"><nuxt-link class="title-link" :to="'/course/search?keyword='+keyword+'&grade='+grade">全部</nuxt-link></li>
<li class="all" v-else>全部</li>
<ol>
<li v-for="category_v in first_category">
<nuxt-link class="title-link all" :to="'/course/search?keyword='+keyword+'&mt=' + category_v.id" v-if="category_v.id == mt">{{category_v.name}}</nuxt-link>
<nuxt-link class="title-link" :to="'/course/search?keyword='+keyword+'&mt=' + category_v.id" v-else>{{category_v.name}}</nuxt-link>
</li>
</ol>
<!--<ol>
<li>数据分析</li>
<li>机器学习工程</li>
<li>前端开发工程</li>
</ol>-->
</ul>
<ul>
<li>二级分类:</li>
<li v-if="st!=''"><nuxt-link class="title-link" :to="'/course/search?keyword='+keyword+'&mt='+mt+'&grade='+grade">全部</nuxt-link></li>
<li class="all" v-else>全部</li>
<ol v-if="second_category.length>0">
<li v-for="category_v in second_category">
<nuxt-link class="title-link all" :to="'/course/search?keyword='+keyword+'&mt='+mt+'&st=' + category_v.id" v-if="category_v.id == st">{{category_v.name}}</nuxt-link>
<nuxt-link class="title-link" :to="'/course/search?keyword='+keyword+'&mt='+mt+'&st=' + category_v.id" v-else>{{category_v.name}}</nuxt-link>
</li>
<!-- <li>大数据</li>
<li>云计算</li>-->
</ol>
<!--<a href="#" class="more">更多 ∨</a>-->
</ul>
<ul>
<li>难度等级:</li>
<li v-if="grade!=''">
<nuxt-link class="title-link" :to="'/course/search?keyword='+keyword+'&mt=' + mt+'&st='+st+'&grade='">全部
</nuxt-link>
</li>
<li class="all" v-else>全部</li>
<ol>
<li v-if="grade=='200001'" class="all">初级</li>
<li v-else><nuxt-link class="title-link" :to="'/course/search?keyword='+keyword+'&mt=' + mt+'&st='+st+'&grade=200001'">初级</nuxt-link></li>
<li v-if="grade=='200002'" class="all">中级</li>
<li v-else><nuxt-link class="title-link" :to="'/course/search?keyword='+keyword+'&mt=' + mt+'&st='+st+'&grade=200002'">中级</nuxt-link></li>
<li v-if="grade=='200003'" class="all">高级</li>
<li v-else><nuxt-link class="title-link" :to="'/course/search?keyword='+keyword+'&mt=' + mt+'&st='+st+'&grade=200003'">高级</nuxt-link></li>
</ol>
</ul>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-9 list-row-left">
<div class="list-cont-left">
<div class="tit">
<ul class="nav nav-tabs ">
<!--<li class="active"><a href="#">推荐</a></li>
<li><a href="#">最新</a></li>
<li><a href="#">热评</a></li>-->
<!-- <div class="page navbar-right">
<a href="#" class="prev">
< </a>
<span class="">1/28</span>
<a href="#" class="next"> ></a>
</div>-->
</ul>
</div>
<div class="tab-content">
<div class="content-list">
<!--<div class="recom-item">
<a href="/course/detail?id=1010" target="_blank">
<p><img src="/img/widget-demo1.png" width="100%" alt=""><span class="lab">HOT</span></p>
<ul>
<li>Think PHP 5.0 博客系统实战项目演练 </li>
<li><span>高级</span> <em> · </em> 1125人在学习</li>
</ul>
</a>
</div>-->
<div class="recom-item" v-for="(course, index) in courselist">
<a :href="'/course/detail/'+course.id+'.html'" target="_blank">
<!--<a href="/course/detail/test.html" target="_blank">-->
<div v-if="course.pic">
<p><img :src="imgUrl+'/'+course.pic" width="100%" alt=""></p>
</div>
<div v-else>
<p><img src="/img/widget-demo1.png" width="100%" alt=""></p>
</div>
<ul >
<li class="course_title"><span v-html="course.name"></span></li>
<li style="float: left"><span v-if="course.charge == '203001'">免费</span><span v-if="course.charge == '203002'">¥{{course.price | money}}</span>
<!-- <em> · </em>--> <!--<em>1125人在学习</em>--></li>
</ul>
<!--</a>-->
</a>
</div>
<li class="clearfix"></li>
</div>
<div class="clearfix"></div>
</div>
</div>
<div style="text-align: center">
<el-pagination
background
layout="prev, pager, next"
@current-change="handleCurrentChange"
:total="total"
:page-size="page_size"
prev-text="上一页"
next-text="下一页">
</el-pagination>
</div>
</div>
<div class="col-md-3 list-row-rit">
<div class="list-cont-right">
<!--精品推荐-->
<!--#include virtual="/include/BestTop.html"-->
<!--精品推荐结束-->
<!--猜你喜欢开始-->
<div class="right-box">
<div class="tit">猜你喜欢</div>
<div class="contList">
<div class="contList-titB">通过对ThinkPHP框架基础,带领大家由浅入深轻松掌握ThinkPHP的理论基础,更加全面的掌握ThinkPHP框架运行机制……</div>
<div class="contList-item">
<p>Think PHP 5.0 博客系统实战项目演练</p>
<li><span>高级</span> <em> · </em> 1125人在学习</li>
</div>
<div class="contList-item">
<p>Think PHP 5.0 博客系统实战项目演练</p>
<li><span>高级</span> <em> · </em> 1125人在学习</li>
</div>
<div class="contList-item">
<p>Think PHP 5.0 博客系统实战项目演练</p>
<li><span>高级</span> <em> · </em> 1125人在学习</li>
</div>
<div class="contList-item">
<p>Think PHP 5.0 博客系统实战项目演练</p>
<li><span>高级</span> <em> · </em> 1125人在学习</li>
</div>
</div>
</div>
<!--猜你喜欢结束-->
</div>
</div>
</div>
</div>
</div>
</template>
<script>
//配置文件
let config = require('~/config/sysConfig')
import querystring from 'querystring'
import * as courseApi from '~/api/course'
export default {
head() {
return {
title: '传智播客-一样的教育,不一样的品质',
meta: [
{charset: 'utf-8'},
{name: 'description', content: '传智播客专注IT培训,Java培训,Android培训,安卓培训,PHP培训,C++培训,网页设计培训,平面设计培训,UI设计培训,移动开发培训,网络营销培训,web前端培训,云计算大数据培训,全栈工程师培训,产品经理培训。'},
{name: 'keywords', content: this.keywords}
],
link: [
{rel: 'stylesheet', href: '/static/plugins/normalize-css/normalize.css'},
{rel: 'stylesheet', href: '/static/plugins/bootstrap/dist/css/bootstrap.css'},
{rel: 'stylesheet', href: '/static/css/page-learing-list.css'}
]
}
},
async asyncData({ store, route }) {//服务端调用方法
return {
courselist: {},
first_category:{},
second_category:{},
mt:'',
st:'',
grade:'',
keyword:'',
page:1,
total:0,
imgUrl:config.imgUrl
}
},
data(){
return {
courselist: {},
first_category:{},
second_category:{},
mt:'',
st:'',
grade:'',
keyword:'',
imgUrl:config.imgUrl,
total:0,//总记录数
page:1,//页码
page_size:12//每页显示个数
}
},
watch:{//路由发生变化立即搜索search表示search方法
'$route':'search'
},
methods:{
//分页触发
handleCurrentChange(page) {
},
search(){
//刷新当前页面
window.location.reload();
}
},
mounted(){
}
}
</script>
<style>
a {
color: #000;
}
.el-icon-arrow-left:before {
content: "<";
}
.el-icon-d-arrow-left:before {
content: "...";
}
.el-icon-arrow-right:before {
content: ">";
}
.el-icon-d-arrow-right:before {
content: "...";
}
.el-icon-more:before {
content: "...";
}
.el-pagination.is-background .btn-next, .el-pagination.is-background .btn-prev, .el-pagination.is-background .el-pager li {
background-color: #fff;
}
.course_title{
height: 20px;
width: 160px;
overflow:hidden;
}
.eslight{
color: #990000;
}
</style>
3.1.5 测试
重启Nginx,
请求:http://www.xuecheng.com/course/search,页面效果如下:
当用户访问http://www.xuecheng.com/course/search,则ngnix执行以下代码:
#前端门户课程搜索
location ^~ /course/search {
proxy_pass http://dynamic_portal_server_pool;
}
这样到http://dynamic_portal_server_pool/course/search,然后ngnix执行以下代码:
#前端动态门户
upstream dynamic_portal_server_pool{
server 127.0.0.1:10000 weight=10;
}
这样到http:// 127.0.0.1:10000/course/search
所以需要启动xc-ui-pc-portal这个项目
右击查看源代码如下:
我们发现title和description都有,因为我们使用了服务端渲染的技术,包括css都渲染出来