乐优商城第六天

0.学习目标

  • 使用资料搭建后台系统
  • 会使用nginx进行反向代理
  • 实现商品分类查询功能
  • 掌握cors解决跨域
  • 实现品牌查询功能

1.搭建后台管理前端

1.1.导入已有资源

后台项目相对复杂,为了有利于教学,我们不再从0搭建项目,而是直接使用课前资料中给大家准备好的源码:
在这里插入图片描述

我们解压缩,放到工作目录中:
在这里插入图片描述

然后在Intellij idea中导入新的工程:
在这里插入图片描述
选中我们的工程:
在这里插入图片描述

这正是一个用vue-cli构建的webpack工程,是不是与昨天的一样:
在这里插入图片描述

1.2.安装依赖

你应该注意到,这里并没有node_modules文件夹,方便给大家下发,已经把依赖都删除了。不过package.json中依然定义了我们所需的一切依赖:
在这里插入图片描述
我们只需要打开终端,进入项目目录,输入:npm install命令,即可安装这些依赖。
在这里插入图片描述
大概需要几分钟。

如果安装过程出现以下问题
在这里插入图片描述
建议删除node_modules目录,重新安装。

1.3.运行一下看看

输入命令:npm run dev
在这里插入图片描述
发现默认的端口是9001。访问:http://localhost:9001

会自动进行跳转:
在这里插入图片描述

2.Vuetify框架

2.1.为什么要学习UI框架

Vue虽然会帮我们进行视图的渲染,但样式还是由我们自己来完成。这显然不是我们的强项,因此后端开发人员一般都喜欢使用一些现成的UI组件,拿来即用,常见的例如:

  • BootStrap
  • LayUI
  • EasyUI
  • ZUI

然而这些UI组件的基因天生与Vue不合,因为他们更多的是利用DOM操作,借助于jQuery实现,而不是MVVM的思想。

而目前与Vue吻合的UI框架也非常的多,国内比较知名的如:

  • element-ui:饿了么出品
  • i-view:某公司出品

然而我们都不用,我们今天推荐的是一款国外的框架:Vuetify

官方网站:https://vuetifyjs.com/zh-Hans/
在这里插入图片描述

2.2.为什么是Vuetify

有中国的为什么还要用外国的?原因如下:

  • Vuetify几乎不需要任何CSS代码,而element-ui许多布局样式需要我们来编写
  • Vuetify从底层构建起来的语义化组件。简单易学,容易记住。
  • Vuetify基于Material Design(谷歌推出的多平台设计规范),更加美观,动画效果酷炫,且风格统一

这是官网的说明:
在这里插入图片描述
缺陷:

  • 目前官网虽然有中文文档,但因为翻译问题,几乎不太能看。

2.3.怎么用?

基于官方网站的文档进行学习:
在这里插入图片描述

我们重点关注UI components即可,里面有大量的UI组件,我们要用的时候再查看,不用现在学习,先看下有什么:
在这里插入图片描述
在这里插入图片描述
以后用到什么组件,就来查询即可。

3.项目结构

开始编码前,我们先了解下项目的结构。

3.1.目录结构

首先是目录结构图:
在这里插入图片描述

3.2.调用关系

我们最主要理清index.html、main.js、App.vue之间的关系:
在这里插入图片描述

理一下:

  • index.html:html模板文件。定义了空的div,其id为app
  • main.js:实例化vue对象,并且绑定通过id选择器,绑定到index.html的div中,因此main.js的内容都将在index.html的div中显示。main.js中使用了App组件,即App.vue,也就是说index.html中最终展现的是App.vue中的内容。index.html引用它之后,就拥有了vue的内容(包括组件、样式等),所以,main.js也是webpack打包的入口
  • index.js:定义请求路径和组件的映射关系。相当于之前的<vue-router>
  • App.vue中也没有内容,而是定义了vue-router的锚点:<router-view>,我们之前讲过,vue-router路由后的组件将会在锚点展示。
  • 最终结论:一切路由后的内容都将通过App.vue在index.html中显示。
  • 访问流程:用户在浏览器输入路径,例如:http://localhost:9001/#/item/brand --> index.js(/item/brand路径对应pages/item/Brand.vue组件) --> 该组件显示在App.vue的锚点位置 --> main.js使用了App.vue组件,并把该组件渲染在index.html文件中(id为“app”的div中)

3.3.页面布局

接下来我们一起看下页面布局。

Layout组件是我们的整个页面的布局组件:
在这里插入图片描述
一个典型的三块布局。包含左,上,中三部分:
在这里插入图片描述

里面使用了Vuetify中的2个组件和一个布局元素:

  • v-navigation-drawer :导航抽屉,主要用于容纳应用程序中的页面的导航链接。
    在这里插入图片描述
  • v-toolbar:工具栏通常是网站导航的主要途径。可以与导航抽屉一起很好地工作,动态选择是否打开导航抽屉,实现可伸缩的侧边栏。
    在这里插入图片描述
  • v-content:并不是一个组件,而是标记页面布局的元素。可以根据您指定的app组件的结构动态调整大小,使得您可以创建高度可定制的组件。

那么问题来了:v-content中的内容来自哪里?
在这里插入图片描述

  • Layout映射的路径是/
  • 除了Login以为的所有组件,都是定义在Layout的children属性,并且路径都是/的下面
  • 因此当路由到子组件时,会在Layout中定义的锚点中显示。
  • 并且Layout中的其它部分不会变化,这就实现了布局的共享。

4.使用域名访问本地项目

4.1.统一环境

我们现在访问页面使用的是:http://localhost:9001

有没有什么问题?

实际开发中,会有不同的环境:

  • 开发环境:自己的电脑
  • 测试环境:提供给测试人员使用的环境
  • 预发布环境:数据是和生成环境的数据一致,运行最新的项目代码进去测试
  • 生产环境:项目最终发布上线的环境

如果不同环境使用不同的ip去访问,可能会出现一些问题。为了保证所有环境的一致,我们会在各种环境下都使用域名来访问。

我们将使用以下域名:

但是最终,我们希望这些域名指向的还是我们本机的某个端口。

那么,当我们在浏览器输入一个域名时,浏览器是如何找到对应服务的ip和端口的呢?

4.2.域名解析

一个域名一定会被解析为一个或多个ip。这一般会包含两步:

  • 本地域名解析

    浏览器会首先在本机的hosts文件中查找域名映射的IP地址,如果查找到就返回IP ,没找到则进行域名服务器解析,一般本地解析都会失败,因为默认这个文件是空的。

    • Windows下的hosts文件地址:C:/Windows/System32/drivers/etc/hosts
    • Linux下的hosts文件所在路径: /etc/hosts

    样式:

    # My hosts
    127.0.0.1 localhost
    0.0.0.0 account.jetbrains.com
    127.0.0.1 www.xmind.net
    
  • 域名服务器解析

    本地解析失败,才会进行域名服务器解析,域名服务器就是网络中的一台计算机,里面记录了所有注册备案的域名和ip映射关系,一般只要域名是正确的,并且备案通过,一定能找到。

4.3.解决域名解析问题

我们不可能去购买一个域名,因此我们可以伪造本地的hosts文件,实现对域名的解析。修改本地的host为:

127.0.0.1 api.leyou.com
127.0.0.1 manage.leyou.com

这样就实现了域名的关系映射了。

每次在C盘寻找hosts文件并修改是非常麻烦的,给大家推荐一个快捷修改host的工具,在课前资料中可以找到:
在这里插入图片描述
解压,运行exe文件,效果:
在这里插入图片描述
我们添加了两个映射关系(中间用空格隔开):

现在,ping一下域名试试是否畅通:
在这里插入图片描述
OK!

通过域名访问:
在这里插入图片描述
原因:我们配置了项目访问的路径,虽然manage.leyou.com映射的ip也是127.0.0.1,但是webpack会验证host是否符合配置。
在这里插入图片描述
在webpack.dev.conf.js中取消host验证:
在这里插入图片描述
重新执行npm run dev,刷新浏览器:
在这里插入图片描述
OK!

4.4.nginx解决端口问题

域名问题解决了,但是现在要访问后台页面,还得自己加上端口:http://manage.taotao.com:9001

这就不够优雅了。我们希望的是直接域名访问:http://manage.taotao.com。这种情况下端口默认是80,如何才能把请求转移到9001端口呢?

这里就要用到反向代理工具:Nginx

4.4.1.什么是Nginx

在这里插入图片描述
nginx可以作为web服务器,但更多的时候,我们把它作为网关,因为它具备网关必备的功能:

  • 反向代理
  • 负载均衡
  • 动态路由
  • 请求过滤

4.4.2.nginx作为web服务器

Web服务器分2类:

  • web应用服务器,如:
    • tomcat
    • resin
    • jetty
  • web服务器,如:
    • Apache 服务器
    • Nginx
    • IIS

区分:web服务器不能解析jsp等页面,只能处理js、css、html等静态资源。
并发:web服务器的并发能力远高于web应用服务器。

4.4.3.nginx作为反向代理

什么是反向代理?

  • 代理:通过客户机的配置,实现让一台服务器(代理服务器)代理客户机,客户的所有请求都交给代理服务器处理。
  • 反向代理:用一台服务器,代理真实服务器,用户访问时,不再是访问真实服务器,而是代理服务器。

nginx可以当做反向代理服务器来使用:

  • 我们需要提前在nginx中配置好反向代理的规则,不同的请求,交给不同的真实服务器处理
  • 当请求到达nginx,nginx会根据已经定义的规则进行请求的转发,从而实现路由功能

利用反向代理,就可以解决我们前面所说的端口问题,如图
在这里插入图片描述

4.4.4.安装和使用

安装

安装非常简单,把课前资料提供的nginx直接解压即可,绿色免安装,舒服!
在这里插入图片描述
我们在本地安装一台nginx:
在这里插入图片描述
解压后,目录结构:
在这里插入图片描述

  1. conf:配置目录
  2. contrib:第三方依赖
  3. html:默认的静态资源目录,类似于tomcat的webapps
  4. logs:日志目录
  5. nginx.exe:启动程序。可双击运行,但不建议这么做。

反向代理配置

示例:
在这里插入图片描述
nginx中的每个server就是一个反向代理配置,可以有多个server

完整配置:

#user  nobody;
worker_processes  1;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;
    sendfile        on;
   
    keepalive_timeout  65;

    gzip  on;
	server {
        listen       80;
        server_name  manage.leyou.com;

        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        location / {
			proxy_pass http://127.0.0.1:9001;
			proxy_connect_timeout 600;
			proxy_read_timeout 600;
        }
    }
	server {
        listen       80;
        server_name  api.leyou.com;

        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        location / {
			proxy_pass http://127.0.0.1:10010;
			proxy_connect_timeout 600;
			proxy_read_timeout 600;
        }
    }
}

使用

nginx可以通过命令行来启动,操作命令:

  • 启动:start nginx.exe
  • 停止:nginx.exe -s stop
  • 重新加载:nginx.exe -s reload

启动过程会闪烁一下,启动成功后,任务管理器中会有两个nginx进程:
在这里插入图片描述

4.5.测试

启动nginx,然后用域名访问后台管理系统:
在这里插入图片描述
现在实现了域名访问网站了,中间的流程是怎样的呢?
在这里插入图片描述

  1. 浏览器准备发起请求,访问http://mamage.leyou.com,但需要进行域名解析

  2. 优先进行本地域名解析,因为我们修改了hosts,所以解析成功,得到地址:127.0.0.1

  3. 请求被发往解析得到的ip,并且默认使用80端口:http://127.0.0.1:80

    本机的nginx一直监听80端口,因此捕获这个请求

  4. nginx中配置了反向代理规则,将manage.leyou.com代理到127.0.0.1:9001,因此请求被转发

  5. 后台系统的webpack server监听的端口是9001,得到请求并处理,完成后将响应返回到nginx

  6. nginx将得到的结果返回到浏览器

5.实现商品分类查询

商城的核心自然是商品,而商品多了以后,肯定要进行分类,并且不同的商品会有不同的品牌信息,其关系如图所示:
在这里插入图片描述

  • 一个商品分类下有很多商品
  • 一个商品分类下有很多品牌
  • 而一个品牌,可能属于不同的分类
  • 一个品牌下也会有很多商品

因此,我们需要依次去完成:商品分类、品牌、商品的开发。

5.1.导入数据

首先导入课前资料提供的sql:
在这里插入图片描述
我们先看商品分类表:
在这里插入图片描述

CREATE TABLE `tb_category` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '类目id',
  `name` varchar(20) NOT NULL COMMENT '类目名称',
  `parent_id` bigint(20) NOT NULL COMMENT '父类目id,顶级类目填0',
  `is_parent` tinyint(1) NOT NULL COMMENT '是否为父节点,0为否,1为是',
  `sort` int(4) NOT NULL COMMENT '排序指数,越小越靠前',
  PRIMARY KEY (`id`),
  KEY `key_parent_id` (`parent_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1424 DEFAULT CHARSET=utf8 COMMENT='商品类目表,类目和商品(spu)是一对多关系,类目与品牌是多对多关系';

因为商品分类会有层级关系,因此这里我们加入了parent_id字段,对本表中的其它分类进行自关联。

5.2.页面实现

5.2.1.页面分析

首先我们看下要实现的效果:
在这里插入图片描述
商品分类之间是会有层级关系的,采用树结构去展示是最直观的方式。

一起来看页面,对应的是/pages/item/Category.vue:
在这里插入图片描述
页面模板:

<template>
  <v-card>
      <v-flex xs12 sm10>
        <v-tree url="/item/category/list"
                :treeData="treeData"
                :isEdit="isEdit"
                @handleAdd="handleAdd"
                @handleEdit="handleEdit"
                @handleDelete="handleDelete"
                @handleClick="handleClick"
        />
      </v-flex>
  </v-card>
</template>
  • v-card:卡片,是vuetify中提供的组件,提供一个悬浮效果的面板,一般用来展示一组数据。

在这里插入图片描述

  • v-flex:布局容器,用来控制响应式布局。与BootStrap的栅格系统类似,整个屏幕被分为12格。我们可以控制所占的格数来控制宽度:
    在这里插入图片描述
    本例中,我们用sm10控制在小屏幕及以上时,显示宽度为10格

  • v-tree:树组件。Vuetify并没有提供树组件,这个是我们自己编写的自定义组件:
    在这里插入图片描述
    里面涉及一些vue的高级用法,大家暂时不要关注其源码,会用即可。

5.2.2.树组件的用法

也可参考课前资料中的:《自定义Vue组件的用法.md

这里我贴出树组件的用法指南。

属性列表:

属性名称 说明 数据类型 默认值
url 用来加载数据的地址,即延迟加载 String -
isEdit 是否开启树的编辑功能 boolean false
treeData 整颗树数据,这样就不用远程加载了 Array -

这里推荐使用url进行延迟加载,每当点击父节点时,就会发起请求,根据父节点id查询子节点信息

当有treeData属性时,就不会触发url加载

远程请求返回的结果格式:

[
    {
    
        "id": 74,
        "name": "手机",
        "parentId": 0,
        "isParent": true,
        "sort": 2
	},
     {
    
        "id": 75,
        "name": "家用电器",
        "parentId": 0,
        "isParent": true,
        "sort": 3
	}
]

事件:

事件名称 说明 回调参数
handleAdd 新增节点时触发,isEdit为true时有效 新增节点node对象,包含属性:name、parentId和sort
handleEdit 当某个节点被编辑后触发,isEdit为true时有效 被编辑节点的id和name
handleDelete 当删除节点时触发,isEdit为true时有效 被删除节点的id
handleClick 点击某节点时触发 被点击节点的node对象,包含完整的node信息

完整node的信息

回调函数中返回完整的node节点会包含以下数据:

{
   
    "id": 76, // 节点id
    "name": "手机", // 节点名称
    "parentId": 75, // 父节点id
    "isParent": false, // 是否是父节点
    "sort": 1, // 顺序
    "path": ["手机", "手机通讯", "手机"] 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值