整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          CSS3 @font-face

          CSS3 @font-face

          font-face是CSS3中的一個模塊,他主要是把自己定義的Web字體嵌入到你的網頁中,隨著@font-face模塊的出現,我們在Web的開發中使用字體不怕只能使用Web安全字體,你們當中或許有許多人會不自然的問,這樣的東西IE能支持嗎?當我告訴大家@font-face這個功能早在IE4就支持了你肯定會感到驚訝。我的Blog就使用了許多這樣的自定義Web字體,比如說首頁的Logo,Tags以及頁面中的手寫英文體,很多朋友問我如何使用,能讓自己的頁面也支持這樣的自定義字體,一句話這些都是@font-face實現的,為了能讓更多的朋友知道如何使用他,今天我主要把自己的一點學習過程貼上來和大家分享。

          首先我們一起來看看@font-face的語法規則:

          @font-face {
           font-family: <YourWebFontName>;
           src: <source> [<format>][,<source> [<format>]]*;
           [font-weight: <weight>];
           [font-style: <style>];
           }
          

          取值說明

          1. YourWebFontName:此值指的就是你自定義的字體名稱,最好是使用你下載的默認字體,他將被引用到你的Web元素中的font-family。如“font-family:"YourWebFontName";”
          2. source:此值指的是你自定義的字體的存放路徑,可以是相對路徑也可以是絕路徑;
          3. format:此值指的是你自定義的字體的格式,主要用來幫助瀏覽器識別,其值主要有以下幾種類型:truetype,opentype,truetype-aat,embedded-opentype,avg等;
          4. weight和style:這兩個值大家一定很熟悉,weight定義字體是否為粗體,style主要定義字體樣式,如斜體。

          兼容瀏覽器

          說到瀏覽器對@font-face的兼容問題,這里涉及到一個字體format的問題,因為不同的瀏覽器對字體格式支持是不一致的,這樣大家有必要了解一下,各種版本的瀏覽器支持什么樣的字體,前面也簡單帶到了有關字體的幾種格式,下面我就分別說一下這個問題,讓大家心里有一個概念:

          一、TureTpe(.ttf)格式:

          .ttf字體是Windows和Mac的最常見的字體,是一種RAW格式,因此他不為網站優化,支持這種字體的瀏覽器有【IE9+,Firefox3.5+,Chrome4+,Safari3+,Opera10+,iOS Mobile Safari4.2+】;

          二、OpenType(.otf)格式:

          .otf字體被認為是一種原始的字體格式,其內置在TureType的基礎上,所以也提供了更多的功能,支持這種字體的瀏覽器有【Firefox3.5+,Chrome4.0+,Safari3.1+,Opera10.0+,iOS Mobile Safari4.2+】;

          三、Web Open Font Format(.woff)格式:

          .woff字體是Web字體中最佳格式,他是一個開放的TrueType/OpenType的壓縮版本,同時也支持元數據包的分離,支持這種字體的瀏覽器有【IE9+,Firefox3.5+,Chrome6+,Safari3.6+,Opera11.1+】;

          四、Embedded Open Type(.eot)格式:

          .eot字體是IE專用字體,可以從TrueType創建此格式字體,支持這種字體的瀏覽器有【IE4+】;

          五、SVG(.svg)格式:

          .svg字體是基于SVG字體渲染的一種格式,支持這種字體的瀏覽器有【Chrome4+,Safari3.1+,Opera10.0+,iOS Mobile Safari3.2+】。

          這就意味著在@font-face中我們至少需要.woff,.eot兩種格式字體,甚至還需要.svg等字體達到更多種瀏覽版本的支持。

          為了使@font-face達到更多的瀏覽器支持,Paul Irish寫了一個獨特的@font-face語法叫Bulletproof @font-face:

           @font-face {
          	font-family: 'YourWebFontName';
          	src: url('YourWebFontName.eot?') format('eot');/*IE*/
          	src:url('YourWebFontName.woff') format('woff'), url('YourWebFontName.ttf') format('truetype');/*non-IE*/
           }
          

          但為了讓各多的瀏覽器支持,你也可以寫成:

           @font-face {
          	font-family: 'YourWebFontName';
          	src: url('YourWebFontName.eot'); /* IE9 Compat Modes */
          	src: url('YourWebFontName.eot?#iefix') format('embedded-opentype'), /* IE6-IE8 */
           url('YourWebFontName.woff') format('woff'), /* Modern Browsers */
           url('YourWebFontName.ttf') format('truetype'), /* Safari, Android, iOS */
           url('YourWebFontName.svg#YourWebFontName') format('svg'); /* Legacy iOS */
           }
          

          說了這么多空洞的理論知識,大家一定有點心癢癢了,那么我們先來看看W3CPLUS首頁中導航部分的蘭色字體是如何實現的,假如我們有一個這樣的DOM標簽,需要應用自定義字體:

          HTML Code:

          <h2 class="neuesDemo">Neues Bauen Demo</h2>
          

          通過@font-face來定義自己的Web Font:

          @font-face {
           font-family: 'NeuesBauenDemo';
           src: url('../fonts/neues_bauen_demo-webfont.eot');
           src: url('../fonts/neues_bauen_demo-webfont.eot?#iefix') format('embedded-opentype'),
           url('../fonts/neues_bauen_demo-webfont.woff') format('woff'),
           url('../fonts/neues_bauen_demo-webfont.ttf') format('truetype'),
           url('../fonts/neues_bauen_demo-webfont.svg#NeuesBauenDemo') format('svg');
           font-weight: normal;
           font-style: normal;
          }
          

          我在這里采用的是相對路徑,當然大家也可以使用絕路徑。到這里我們就需要把定義好的字體應用到我們實際頁面中去:

          h2.neuesDemo {
           font-family: 'NeuesBauenDemo'
          }
          

          效果:

          看到上面的效果,我想大家會感到@font-face很神奇,同時也想爭著做做看,可是一動手才發現,特殊字體我要怎樣才能得到,那些.eot,.woff,.ttf,.svg這些字體格式又怎么獲取呢?有些朋友可能就不知道如何運手了,那么我們就帶著這些問題來一個全程完成的實例吧:

          一、獲取特殊字體:

          我們拿下面這種single Malta字體來說吧:

          要得到single Malta字體,不外乎兩種途徑,其一找到付費網站購買字體,其二就是到免費網站DownLoad字體。當然要給錢的這種傻事我想大家都不會做的,那我們就得到免費的地方下載,在哪有呢?我平時都是到Google Web Fonts和Dafont.com尋找自己需要的字體,當然網上也還有別的下載字體的地方,這個Demo使用的是Dafont.com的Single Malta字體,這樣就可以到這里下載Single Malta:

          Single Malta下載下來后,需要把它解壓縮出來:

          二、獲取@font-face所需字體格式:

          特殊字體已經在你的電腦中了,現在我們需要想辦法獲得@font-face所需的.eot,.woff,.ttf,.svg字體格式。要獲取這些字體格式,我們同樣是需要第三方工具或者軟件來實現,下面我給大家推薦一款我常用的一個工具fontsquirrel,別的先不多說,首跟我點這里進入到下面這個界面吧。

          如果你進入頁面沒有看到上圖,你可以直接點擊導航:

          如果你看到了上面的界面,那就好辦了,我們來看如何應用這個工具生成@font-face需要的各種字體,先把我們剛才下載的字體上傳上去:

          上傳后按下圖所示操作:

          現在從Font Squirrel下載下來的文件已經保存在你本地的電腦上了,接著只要對他進行解壓縮,你就能看到文件列表如下所示:

          大家可以看到,解壓縮出來的文件格式,里面除了@font-face所需要的字體格式外,還帶有一個DEMO文件,如果你不清楚的也可以參考下載下來的DEMO文件,我在這里不對DEMO說明問題,我主要是給大家介紹如何把下載下來的文件有價值的運用到我們的項目中。

          例如在自己的本地創建了一個fontface項目:

          為了讓項目結構更清晰,我們在項目中單獨創建一個fonts目錄,用來放置解壓縮出來@font-face所需的字體格式:

          現在@font-face所需字體已經加載到本地項目,現在本地項目中的style.css中附上我們需要的@font-face樣式

          @font-face {
           font-family: 'SingleMaltaRegular';
           src: url('../fonts/singlemalta-webfont.eot');
           src: url('../fonts/singlemalta-webfont.eot?#iefix') format('embedded-opentype'),
           url('../fonts/singlemalta-webfont.woff') format('woff'),
           url('../fonts/singlemalta-webfont.ttf') format('truetype'),
           url('../fonts/singlemalta-webfont.svg#SingleMaltaRegular') format('svg');
           font-weight: normal;
           font-style: normal;
          }
          

          到這里為止,我們已經通過@font-face自定義好所需的SingleMalta字體,離最后效果只差一步了,就是把自己定義的字體應用到你的Web中的DOM元素上:

          h2.singleMalta {
           font-family: 'SingleMaltaRegular'
          }
          

          效果:

          看到上面的效果,那大家就知道我們實現成功了。那么關于@font-face幫你打造特殊效果的字體,到這里基本上就完成了,我在這里需要提醒使用者:

          1、如果你的項目中是英文網站,而且項目中的Logo,Tags等應用到較多的這種特殊字體效果,我建議你不要使用圖片效果,而使用@font-face,但是你是中文網站,我覺得還是使用圖片比較合適,因為加載英文字體和圖片沒有多大區別,但是你加載中文字體,那就不一樣了,因為中文字體太大了,這樣會影響到項目的某些性能的優化;

          2、致命的錯誤,你在@font-face中定義時,文件路徑沒有載對;

          3、你只定義了@font-face,但并沒有應用到你的項目中的DOM元素上;

          以上幾點都是在平時制作中常出現的問題,希望大家能小意一些,另外我們沒有辦法在購買所有字體,就算你實力雄厚,那也沒有辦法在一臺服務器主機上放置你所有項目需要的字體。因此我給大家提供幾個免費字體下載的網址:Webfonts,Typekit,Kernest,Google Web Fonts,Kernest,Dafont,Niec Web Type,不然你點這里將有更多的免費字體。前面幾個鏈接是幫助你獲取一些優美的怪異的特殊字體,但下面這個工具作用更是無窮的大,他能幫你生成@font-face所需要的各種字體,這工具就是Font Squirrel。

          最后在提醒一下,使用@font-face別的可以忘了,但Font Squirrel千萬不能忘,因為他能幫你生成@font-face所需的各種字體格式。

          到此關于@font-face就介紹完了,不知道大家喜歡不喜歡,如果喜歡的話趕快動手實踐一下,有Blog的可以馬上運用上去,也可以炫一下。

          學習從來不是一個人的事情,要有個相互監督的伙伴,想要學習或交流前端問題的小伙伴可以私信“學習”小明加群獲取2019web前端最新入門資料,一起學習,一起成長!

          -2 SPU和SKU詳解

          ??商城系統中的商品信息肯定避免不了SPU和SKU這兩個概念,本節就給大家詳細介紹下這塊的內容

          1、掌握SKU和SPU關系

          SPU=Standard Product Unit (標準化產品單元)

          SPU是商品信息聚合的最小單位,是一組可復用、易檢索的標準化信息的集合,該集合描述了一個產品的特性。通俗點講,屬性值、特性相同的商品就可以稱為一個SPU。

          SKU=stock keeping unit(庫存量單位)

          SKU即庫存進出計量的單位, 可以是以件、盒、托盤等為單位。

          SKU是物理上不可分割的最小存貨單元。在使用時要根據不同業態,不同管理模式來處理。在服裝、鞋類商品中使用最多最普遍。

          舉個例子:

          購買手機的時候,你可以選擇華為Mate40系列手機,Mate40系列手機的生產制造商是華為,品牌是華為,手機分類也是華為,不過Mate40系列手機有多款,比如 Mate40 、Mate40 Pro 、 Mate40 Pro +,每款手機的架構也不一樣,顏色也不一定一樣,那么這個例子中哪些是Spu哪些是Sku呢?

          Spu:

          手機系列:Mate40系列
          廠家:華為
          品牌:華為
          分類:手機

          Sku:

          價格
          顏色
          網絡格式

          2、表結構設計

          2.1 Spu和Sku

          spu:

          CREATE TABLE `spu` (
            `id` varchar(60) NOT NULL COMMENT '主鍵',
            `name` varchar(100) DEFAULT NULL COMMENT 'SPU名',
            `intro` varchar(200) DEFAULT NULL COMMENT '簡介',
            `brand_id` int(11) DEFAULT NULL COMMENT '品牌ID',
            `category_one_id` int(20) DEFAULT NULL COMMENT '一級分類',
            `category_two_id` int(10) DEFAULT NULL COMMENT '二級分類',
            `category_three_id` int(10) DEFAULT NULL COMMENT '三級分類',
            `images` varchar(1000) DEFAULT NULL COMMENT '圖片列表',
            `after_sales_service` varchar(50) DEFAULT NULL COMMENT '售后服務',
            `content` longtext COMMENT '介紹',
            `attribute_list` varchar(3000) DEFAULT NULL COMMENT '規格列表',
            `is_marketable` int(1) DEFAULT '0' COMMENT '是否上架,0已下架,1已上架',
            `is_delete` int(1) DEFAULT '0' COMMENT '是否刪除,0:未刪除,1:已刪除',
            `status` int(1) DEFAULT '0' COMMENT '審核狀態,0:未審核,1:已審核,2:審核不通過',
            PRIMARY KEY (`id`)
          ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

          sku:

          CREATE TABLE `sku` (
            `id` varchar(60) NOT NULL COMMENT '商品id',
            `name` varchar(200) NOT NULL COMMENT 'SKU名稱',
            `price` int(20) NOT NULL DEFAULT '1' COMMENT '價格(分)',
            `num` int(10) DEFAULT '100' COMMENT '庫存數量',
            `image` varchar(200) DEFAULT NULL COMMENT '商品圖片',
            `images` varchar(2000) DEFAULT NULL COMMENT '商品圖片列表',
            `create_time` datetime DEFAULT NULL COMMENT '創建時間',
            `update_time` datetime DEFAULT NULL COMMENT '更新時間',
            `spu_id` varchar(60) DEFAULT NULL COMMENT 'SPUID',
            `category_id` int(10) DEFAULT NULL COMMENT '類目ID',
            `category_name` varchar(200) DEFAULT NULL COMMENT '類目名稱',
            `brand_id` int(11) DEFAULT NULL COMMENT '品牌id',
            `brand_name` varchar(100) DEFAULT NULL COMMENT '品牌名稱',
            `sku_attribute` varchar(200) DEFAULT NULL COMMENT '規格',
            `status` int(1) DEFAULT '1' COMMENT '商品狀態 1-正常,2-下架,3-刪除',
            PRIMARY KEY (`id`),
            KEY `cid` (`category_id`),
            KEY `status` (`status`),
            KEY `updated` (`update_time`)
          ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品表';

          2.2 商品發布流程分析

          商品發布流程如下:

          1)分類選擇

          發布商品前,需要先選擇發布商品所屬分類,分類嚴格定義為3級分類。

          分類表:

          CREATE TABLE `category` (
            `id` int(20) NOT NULL AUTO_INCREMENT COMMENT '分類ID',
            `name` varchar(50) DEFAULT NULL COMMENT '分類名稱',
            `sort` int(11) DEFAULT NULL COMMENT '排序',
            `parent_id` int(20) DEFAULT NULL COMMENT '上級ID',
            PRIMARY KEY (`id`),
            KEY `parent_id` (`parent_id`)
          ) ENGINE=InnoDB AUTO_INCREMENT=11182 DEFAULT CHARSET=utf8 COMMENT='商品類目';

          2)選擇品牌

          分類選擇完成后,需要加載品牌,品牌加載并非一次性加載完成,而是根據選擇的分類進行加載。

          分類品牌關系表:

          CREATE TABLE `category_brand` (
            `category_id` int(11) NOT NULL COMMENT '分類ID',
            `brand_id` int(11) NOT NULL COMMENT '品牌ID',
            PRIMARY KEY (`brand_id`,`category_id`)
          ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

          品牌表:

          CREATE TABLE `brand` (
            `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '品牌id',
            `name` varchar(100) NOT NULL COMMENT '品牌名稱',
            `image` varchar(1000) DEFAULT '' COMMENT '品牌圖片地址',
            `initial` varchar(1) DEFAULT '' COMMENT '品牌的首字母',
            `sort` int(11) DEFAULT NULL COMMENT '排序',
            PRIMARY KEY (`id`)
          ) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 COMMENT='品牌表';

          3)屬性加載

          當選擇分類后,加載分類對應的屬性。

          分類屬性表:

          CREATE TABLE `category_attr` (
            `category_id` int(11) NOT NULL,
            `attr_id` int(11) NOT NULL COMMENT '屬性分類表',
            PRIMARY KEY (`category_id`,`attr_id`)
          ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

          屬性表:

          CREATE TABLE `sku_attribute` (
            `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
            `name` varchar(50) DEFAULT NULL COMMENT '屬性名稱',
            `options` varchar(2000) DEFAULT NULL COMMENT '屬性選項',
            `sort` int(11) DEFAULT NULL COMMENT '排序',
            PRIMARY KEY (`id`)
          ) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8;

          3、 商品發布加載功能

          對應的Bean我們已經提前寫好,如下

          package com.bobo.vip.mall.goods.model;
          
          import com.baomidou.mybatisplus.annotation.IdType;
          import com.baomidou.mybatisplus.annotation.TableId;
          import com.baomidou.mybatisplus.annotation.TableName;
          import lombok.AllArgsConstructor;
          import lombok.Data;
          import lombok.NoArgsConstructor;
          
          import java.io.Serializable;
          
          /*****
           * @Author: 波波
           * @Description: 云商城
           ****/
          @Data
          @AllArgsConstructor
          @NoArgsConstructor
          //MyBatisPlus表映射注解
          @TableName(value="category")
          public class Category implements Serializable {
          
              @TableId(type=IdType.AUTO)
              private Integer id;
              private String name;
              private Integer sort;
              private Integer parentId;
          }
          package com.bobo.vip.mall.goods.model;
          
          import com.baomidou.mybatisplus.annotation.TableField;
          import com.baomidou.mybatisplus.annotation.TableName;
          import lombok.AllArgsConstructor;
          import lombok.Data;
          import lombok.NoArgsConstructor;
          
          /*****
           * @Author: 波波
           * @Description: 云商城
           ****/
          @Data
          @AllArgsConstructor
          @NoArgsConstructor
          //MyBatisPlus表映射注解
          @TableName(value="category_attr")
          public class CategoryAttr {
          
              @TableField
              private Integer categoryId;
          
              @TableField
              private Integer attrId;
          
          }
          /*****
           * @Author: 波波
           * @Description: 云商城
           ****/
          @Data
          @AllArgsConstructor
          @NoArgsConstructor
          //MyBatisPlus表映射注解
          @TableName(value="category_brand")
          public class CategoryBrand {
          
              @TableField
              private Integer categoryId;
          
              @TableField
              private Integer brandId;
          }
          /*****
           * @Author: 波波
           * @Description: 云商城
           ****/
          @Data
          @NoArgsConstructor
          @AllArgsConstructor
          public class Product {
              // Spu
              private Spu spu;
              // Sku
              private List<Sku> skus;
          }
          
          1234567891011121314
          @Data
          @AllArgsConstructor
          @NoArgsConstructor
          //MyBatisPlus表映射注解
          @TableName(value="sku")
          public class Sku {
          
              @TableId(type=IdType.ASSIGN_ID)
              private String id;
              private String name;
              private Integer price;
              private Integer num;
              private String image;
              private String images;
              private Date createTime;
              private Date updateTime;
              private String spuId;
              private Integer categoryId;
              private String categoryName;
              private Integer brandId;
              private String brandName;
              private String skuAttribute;
              private Integer status;
          }
          /*****
           * @Author: 波波
           * @Description: 云商城
           ****/
          @Data
          @AllArgsConstructor
          @NoArgsConstructor
          //MyBatisPlus表映射注解
          @TableName(value="sku_attribute")
          public class SkuAttribute implements Serializable {
          
              @TableId(type=IdType.AUTO)
              private Integer id;
              private String name;
              private String options;
              private Integer sort;
          
              //對應分類
              @TableField(exist=false)
              private List<Category> categories;
          
          }
          12345678910111213141516171819202122
          @Data
          @AllArgsConstructor
          @NoArgsConstructor
          //MyBatisPlus表映射注解
          @TableName(value="spu")
          public class Spu {
          
              @TableId(type=IdType.ASSIGN_ID)
              private String id;
              private String name;
              private String intro;
              private Integer brandId;
              private Integer categoryOneId;
              private Integer categoryTwoId;
              private Integer categoryThreeId;
              private String images;
              private String afterSalesService;
              private String content;
              private String attributeList;
              private Integer isMarketable;
              private Integer isDelete;
              private Integer status;
          }

          3.1 分類加載

          分類功能需要實現按照父ID查詢,最開始初始化加載的是頂級父類,parent_id=0,后面每次點擊的時候都根據傳入的id查詢子分類。

          1)Mapper

          創建com.bobo.vip.mall.goods.mapper.CategoryMapper,代碼如下:

          public interface CategoryMapper extends BaseMapper<Category> {
          }
          12

          2)Service

          接口:com.bobo.vip.mall.goods.service.CategoryService代碼如下:

          public interface CategoryService extends IService<Category> {
          
              /**
               * 根據父ID查詢子分類
               * @param pid
               * @return
               */
              List<Category> queryByParentId(Integer pid);
          }
          123456789

          實現類:com.bobo.vip.mall.goods.service.impl.CategoryServiceImpl代碼如下:

          @Service
          public class CategoryServiceImpl extends ServiceImpl<CategoryMapper,Category> implements CategoryService {
          
              @Autowired
              private CategoryMapper categoryMapper;
          
              /***
               * 根據父ID查詢子分類
               * @param pid
               * @return
               */
              @Override
              public List<Category> queryByParentId(Integer pid) {
                  //條件封裝
                  QueryWrapper<Category> queryWrapper=new QueryWrapper<Category>();
                  queryWrapper.eq("parent_id",pid);
                  return categoryMapper.selectList(queryWrapper);
              }
          }
          12345678910111213141516171819

          3)Controller

          創建com.bobo.vip.mall.goods.controller.CategoryController代碼如下;

          @RestController
          @RequestMapping(value="/category")
          @CrossOrigin
          public class CategoryController {
          
              @Autowired
              private CategoryService categoryService;
          
              /****
               * 根據父ID查詢子分類
               */
              @GetMapping(value="/parent/{pid}")
              public RespResult<List<Category>> list(@PathVariable(value="pid")Integer pid){
                  List<Category> categories=categoryService.queryByParentId(pid);
                  return RespResult.ok(categories);
              }
          }
          1234567891011121314151617

          3.2 品牌加載

          品牌需要根據分類進行加載,當用戶選擇第3級分類的時候,加載品牌,品牌數據需要經過category_brand表關聯查詢。

          我們可以按照如下步驟實現:

          1、查詢category_brand中指定分類對應的品牌ID集合
          2、從brand查出品牌集合

          1)Mapper

          修改com.bobo.vip.mall.goods.mapper.BrandMapper,添加根據分類ID查詢品牌ID集合:

          //根據分類ID查詢品牌集合
          @Select("select brand_id from category_brand where category_id=#{id}")
          List<Integer> queryBrandIds(Integer id);
          123

          2)Service

          接口:com.bobo.vip.mall.goods.service.BrandService中添加根據分類ID查詢品牌集合方法

          //根據分類ID查詢品牌
          List<Brand> queryByCategoryId(Integer id);
          12

          實現類:com.bobo.vip.mall.goods.service.impl.BrandServiceImpl

          /***
           * 根據分類ID查詢品牌
           * @param id
           * @return
           */
          @Override
          public List<Brand> queryByCategoryId(Integer id) {
              //查詢分類ID對應的品牌集合
              List<Integer> brandIds=brandMapper.queryBrandIds(id);
              //根據品牌ID集合查詢品牌信息
              List<Brand> brands=brandMapper.selectBatchIds(brandIds);
              return brands;
          }
          12345678910111213

          3)Controller

          修改com.bobo.vip.mall.goods.controller.BrandController添加根據分類ID查詢品牌集合

          /****
           * 根據分類ID查詢品牌
           */
          @GetMapping(value="/category/{id}")
          public RespResult<List<Brand>> categoryBrands(@PathVariable(value="id")Integer id){
              List<Brand> brands=brandService.queryByCategoryId(id);
              return RespResult.ok(brands);
          }
          12345678

          3.3 屬性加載

          屬性也稱為規格,屬性也需要根據分類查詢,我們可以按照如下思路實現:

          1、先從category_attr根據分類ID查詢出當前分類擁有的屬性ID集合
          2、從sku_attribute中查詢屬性集合

          1)Mapper

          創建com.bobo.vip.mall.goods.mapper.SkuAttributeMapper實現根據分類ID查詢屬性信息。

          /***
           * 根據分類ID查詢屬性集合
           * @param id
           * @return
           */
          @Select("SELECT * FROM sku_attribute WHERE id IN(SELECT attr_id FROM category_attr WHERE category_id=#{id})")
          List<SkuAttribute> queryByCategoryId(Integer id);
          1234567

          2)Service

          接口:com.bobo.vip.mall.goods.service.SkuAttributeService添加根據分類ID查詢屬性集合方法

          //根據分類ID查詢屬性集合
          List<SkuAttribute> queryList(Integer id);
          12

          實現類:com.bobo.vip.mall.goods.service.impl.SkuAttributeServiceImpl添加如下實現方法

          /***
           * 根據分類ID查詢屬性集合
           * @param id
           * @return
           */
          @Override
          public List<SkuAttribute> queryList(Integer id) {
              return skuAttributeMapper.queryByCategoryId(id);
          }
          123456789

          3)Controller

          創建com.bobo.vip.mall.goods.controller.SkuAttributeController,添加如下方法

          /***
           * 根據分類ID查詢
           */
          @GetMapping(value="/category/{id}")
          public RespResult<SkuAttribute> categoryAttributeList(@PathVariable(value="id")Integer id){
              //根據分類ID查詢屬性參數
              List<SkuAttribute> skuAttributes=skuAttributeService.queryList(id);
              return RespResult.ok(skuAttributes);
          }
          123456789

          4、商品發布

          4.1 復合對象分析

          商品發布,如上圖,我們可以發現發布的商品信息包含Sku和Spu,因此我們應該在后端能有一個對象同時能接到Spu和多個Sku,方法有很多種,我們可以直接在Spu中寫一個List<Sku>,但這種方法不推薦,按照對象設計原則,對一個對象進行擴展時,盡量避免對原始對象造成改變,因此我們可以使用復合類,可以創建一個Prodcut類,該類中有Spu也有List<Sku>,代碼如下:

          @Data
          @NoArgsConstructor
          @AllArgsConstructor
          public class Product {
              // Spu
              private Spu spu;
              // Sku
              private List<Sku> skus;
          }
          123456789

          4.2 添加商品

          添加商品的時候,我們需要保存Spu,同時需要添加多個Sku。我們可以在華為商城中看看真實電商中Sku名字特征,每次點擊不同屬性的時候,前部分名字一樣,只是將名字中的規格替換了,也就是說Sku的名字其實是組合成的,一部分是Spu的一部分是Sku的,可以進行組合。

          1)名字分析

          添加商品的時候,會將商品的屬性傳入后臺,格式如下,如果把規格名字添加到名字中,那就是華為商城中的效果了,我們可以這么做,把屬性解析成Map,然后每個屬性值添加到商品名字中即可。

          {"適合人群":"有一定java基礎的人","書籍分類":"軟件編程"}

          2)實現代碼

          Mapper

          com.bobo.vip.mall.goods.mapper.SpuMapper代碼如下:

          public interface SpuMapper extends BaseMapper<Spu> {
          }
          12

          com.bobo.vip.mall.goods.mapper.SkuMapper代碼如下:

          public interface SkuMapper extends BaseMapper<Sku> {
          }
          12

          Service

          com.bobo.vip.mall.goods.service.SpuService中添加產品方法如下

          public interface SpuService extends IService<Spu> {
              //保存商品
              void saveProduct(Product product);
          }
          1234

          com.bobo.vip.mall.goods.service.impl.SpuServiceImpl中添加產品方法如下:

          @Service
          public class SpuServiceImpl extends ServiceImpl<SpuMapper,Spu> implements SpuService {
          
              @Autowired
              private SkuMapper skuMapper;
          
              @Autowired
              private SpuMapper spuMapper;
          
              @Autowired
              private CategoryMapper categoryMapper;
          
              @Autowired
              private BrandMapper brandMapper;
          
              // 保存商品
              @Override
              public void saveProduct(Product product) {
                  //Spu
                  Spu spu=product.getSpu();
                  //上架
                  spu.setIsMarketable(1);
                  //未刪除
                  spu.setIsDelete(0);
                  //狀態
                  spu.setStatus(1);
                  //添加
                  spuMapper.insert(spu);
          
          
                  //查詢三級分類
                  Category category=categoryMapper.selectById(spu.getCategoryThreeId());
                  //查詢品牌
                  Brand brand=brandMapper.selectById(spu.getBrandId());
                  //當前時間
                  Date now=new Date();
          
                  //新增Sku集合
                  for (Sku sku : product.getSkus()) {
                      //設置名字
                      String skuName=spu.getName();
                      Map<String,String> attrMap=JSON.parseObject(sku.getSkuAttribute(), Map.class);
                      for (Map.Entry<String, String> entry : attrMap.entrySet()) {
                          skuName+="   "+entry.getValue();
                      }
                      sku.setName(skuName);
                      //設置圖片
                      sku.setImages(spu.getImages());
                      //設置狀態
                      sku.setStatus(1);
                      //設置類目ID
                      sku.setCategoryId(spu.getCategoryThreeId());
                      //設置類目名稱
                      sku.setCategoryName(category.getName());
                      //設置品牌ID
                      sku.setBrandId(brand.getId());
                      //設置品牌名稱
                      sku.setBrandName(brand.getName());
                      //設置Spuid
                      sku.setSpuId(spu.getId());
                      //時間
                      sku.setCreateTime(now);
                      sku.setUpdateTime(now);
                      //增加
                      skuMapper.insert(sku);
                  }
              }
          }
          1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768

          Controller

          創建com.bobo.vip.mall.goods.controller.SpuController,添加產品代碼如下:

          @Autowired
          private SpuService spuService;
          
          /***
           * 保存
           */
          @PostMapping(value="/save")
          public RespResult save(@RequestBody Product product){
              //保存
              spuService.saveProduct(product);
              return RespResult.ok();
          }

          4.3 產品修改

          產品修改其實和產品添加幾乎一致,只需要做小改動即可,實現步驟如下:

          1、如果Spu的id值不為空,說明是修改操作
          2、如果是修改操作,先刪除之前對應的Sku集合
          3、其他流程和添加商品一致

          修改com.bobo.vip.mall.goods.service.impl.SpuServiceImplsave方法,代碼如下:

          在這里插入圖片描述

          源碼如下:

          @Override
          public void saveProduct(Product product) {
              //Spu
              Spu spu=product.getSpu();
          
              //如果ID為空,則增加
              if(StringUtils.isEmpty(spu.getId())){
                  //上架
                  spu.setIsMarketable(1);
                  //未刪除
                  spu.setIsDelete(0);
                  //狀態
                  spu.setStatus(1);
                  //添加
                  spuMapper.insert(spu);
              }else{
                  //ID 不為空,則修改
                  spuMapper.updateById(spu);
                  //刪除之前的Sku記錄
                  skuMapper.delete(new QueryWrapper<Sku>().eq("spu_id",spu.getId()));
              }
          
              //查詢三級分類
              Category category=categoryMapper.selectById(spu.getCategoryThreeId());
              //查詢品牌
              Brand brand=brandMapper.selectById(spu.getBrandId());
              //當前時間
              Date now=new Date();
          
              //新增Sku集合
              for (Sku sku : product.getSkus()) {
                  //設置名字
                  String skuName=spu.getName();
                  Map<String,String> attrMap=JSON.parseObject(sku.getSkuAttribute(), Map.class);
                  for (Map.Entry<String, String> entry : attrMap.entrySet()) {
                      skuName+="   "+entry.getValue();
                  }
                  sku.setName(skuName);
                  //設置圖片
                  sku.setImages(spu.getImages());
                  //設置狀態
                  sku.setStatus(1);
                  //設置類目ID
                  sku.setCategoryId(spu.getCategoryThreeId());
                  //設置類目名稱
                  sku.setCategoryName(category.getName());
                  //設置品牌ID
                  sku.setBrandId(brand.getId());
                  //設置品牌名稱
                  sku.setBrandName(brand.getName());
                  //設置Spuid
                  sku.setSpuId(spu.getId());
                  //時間
                  sku.setCreateTime(now);
                  sku.setUpdateTime(now);
                  //增加
                  skuMapper.insert(sku);
              }
          }
          1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859

          5 MyBatis Plus代碼生成

          我們可以發現個問題,剛才寫的很多增刪改查代碼都比較簡單,比較枯燥,重復寫一些類的創建、單表增刪改查非常類,而創建對象和單標操作的代碼,在開發中幾乎占用了開發時間的80%,如果能夠用工具生成就可以大大節省我們開發成本了。

          5.1 MyBatis Plus介紹

          AutoGenerator 是 MyBatis-Plus 的代碼生成器,通過 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各個模塊的代碼,極大的提升了開發效率。

          學習網址 https://baomidou.com/guide/generator.html

          5.2 MyBatisPlus代碼生成配置

          1)引入依賴

          <dependency>
              <groupId>com.baomidou</groupId>
              <artifactId>mybatis-plus-generator</artifactId>
              <version>3.4.0</version>
          </dependency>
          
          <dependency>
              <groupId>org.apache.velocity</groupId>
              <artifactId>velocity-engine-core</artifactId>
              <version>2.2</version>
          </dependency>
          1234567891011

          2)代碼生成

          public static void main(String[] args) {
              // 代碼生成器
              AutoGenerator mpg=new AutoGenerator();
          
              // 全局配置
              GlobalConfig gc=new GlobalConfig();
              String projectPath=System.getProperty("user.dir");
              gc.setOutputDir(projectPath + "/src/main/java");    // 文件輸出路徑
              gc.setAuthor("bobo");   //作者
              gc.setOpen(false);   //生成之后是否打開目錄
              gc.setIdType(IdType.NONE);  //主鍵策略
              gc.setServiceName("%sService"); //名字設置 %s是占位符,可以理解成類的名字
              mpg.setGlobalConfig(gc);
          
              // 數據源配置
              DataSourceConfig dsc=new DataSourceConfig();
              dsc.setUrl("jdbc:mysql://192.168.100.140:3306/shop_goods?useUnicode=true&useSSL=false&characterEncoding=utf8");
              dsc.setDriverName("com.mysql.jdbc.Driver");
              dsc.setUsername("root");
              dsc.setPassword("123456");
              mpg.setDataSource(dsc);
          
              // 包配置
              PackageConfig pc=new PackageConfig();
              pc.setModuleName("mall-goods");
              pc.setParent("com.bobo.code");
              mpg.setPackageInfo(pc);
          
              // 策略配置
              StrategyConfig strategy=new StrategyConfig();
              strategy.setNaming(NamingStrategy.underline_to_camel);  //駝峰命名
              strategy.setColumnNaming(NamingStrategy.underline_to_camel);    //駝峰命名
              strategy.setEntityLombokModel(true);    //是否使用Lombok
              strategy.setRestControllerStyle(true);  //是否生成RestController
              // 寫于父類中的公共字段
              strategy.setSuperEntityColumns("id");   //公共字段定義
              strategy.setControllerMappingHyphenStyle(true); //駝峰轉連字符
              strategy.setTablePrefix(pc.getModuleName() + "_");  //表前綴
              mpg.setStrategy(strategy);
              mpg.execute();
          }

          效果

          有紅色的提示是因為沒有引入依賴,我們可以把生成的相關內容拷貝到合適的項目位置即可。

          Vue.js 3.x+Express全棧開發:從0到1打造商城項目》

          1

          本書內容

          《Vue.js 3.x+Express全棧開發 : 從0到1打造商城項目》是一本詳盡的全棧開發教程,旨在通過Vue.js和Express框架引導讀者從零開始構建一個完整的電商項目。內容覆蓋電商項目的基本結構,以及Vue.js和Express的核心概念與架構;深入講解Vue.js開發生態中的關鍵模塊,包括網絡請求、UI組件、路由管理和狀態管理等;探討Express框架的常用組件,如處理加密數據的中間件和與MySQL數據庫交互的插件;最后指導讀者打造一個完整的電商項目。在用戶端,實現注冊登錄、商品瀏覽、購物車等功能;在服務端,完成用戶驗證、商品維護、訂單處理等任務;在后臺管理端,進行商品信息、訂單數據等的管理與統計分析。通過閱讀《Vue.js 3.x+Express全棧開發 : 從0到1打造商城項目》,讀者能夠掌握Vue.js和Express全棧開發技術,并獨立完成電商項目的搭建與開發。

          《Vue.js 3.x+Express全棧開發 : 從0到1打造商城項目》還提供了完整的項目源碼、代碼導讀手冊以及長達30小時的教學視頻,可大幅提升學習效率。

          2

          本書作者

          張益琿,美國亞利桑那州立大學計算機工程技術碩士,架構師,從業近10年,多年大前端開發經驗,曾就職于知名上市公司,主導開發過多款商業級應用程序,對移動跨平臺開發、前端開發,以及Vue.js 、React、Flutter、小程序與iOS開發都擁有豐富經驗。開源中國特邀技術專家,發表相關技術博文400余篇,訪問量超過100萬次。出版技術圖書《循序漸進Vue.js 3.x前端開發實戰》《微信小程序與云開發從入門到實踐》《Swift 5從零到精通iOS開發訓練營》等多部。

          3

          本書讀者

          《Vue.js 3.x+Express全棧開發 : 從0到1打造商城項目》采用實際商業項目作為教學案例,融入了多種前端框架和新技術,非常適合缺乏項目經驗的學生和對全棧開發感興趣的開發者閱讀,也適合作為培訓機構和大中專院校相關專業的實踐課教學用書

          4

          本書目錄

          第1章 項目概覽與環境準備 1

          1.1 項目概覽 1

          1.1.1 電商項目的功能構成 2

          1.1.2 前端框架Vue.js及其周邊工具 3

          1.1.3 熟悉Node.js與Express 4

          1.1.4 從JavaScript到TypeScript 5

          1.2 腳手架工具的應用 6

          1.2.1 安裝Node.js環境 6

          1.2.2 使用Vue.js腳手架工具Vite 7

          1.2.3 使用Express項目生成工具 9

          1.2.4 使用Visual Studio Code編程工具 11

          1.3 HelloWorld工程解析 13

          1.3.1 Vue.js工程解析 13

          1.3.2 Express工程解析 16

          1.4 小結與上機練習 22

          第2章 前端基礎模塊及應用 24

          2.1 axios與vue-axios網絡請求模塊的應用 25

          2.1.1 嘗試發起一個HTTP請求 25

          2.1.2 axios網絡模塊的更多用法 27

          2.2 Element Plus頁面UI組件模塊的應用 30

          2.2.1 加載Element Plus模塊 30

          2.2.2 基礎UI組件 32

          2.2.3 典型的表單類組件 34

          2.2.4 典型的數據展示類組件 37

          2.2.5 常用的導航組件 40

          2.2.6 常用的用戶反饋類組件 43

          2.3 Vue Router路由模塊的應用 46

          2.3.1 Vue Router模塊的使用 46

          2.3.2 動態路由與參數匹配 48

          2.3.3 路由的嵌套和命名 51

          2.3.4 路由中的導航守衛 54

          2.4 Pinia狀態管理模塊的應用 56

          2.4.1 嘗試使用Pinia 56

          2.4.2 Pinia中的幾個核心概念 59

          2.5 小結與上機練習 60

          第3章 后端服務基礎模塊及應用 69

          3.1 文件上傳服務 70

          3.1.1 圖片上傳服務示例 70

          3.1.2 Multer中間件的更多用法 74

          3.2 在Express中使用MySQL數據庫 76

          3.2.1 MySQL數據庫的安裝和簡單使用 76

          3.2.2 在Express中調用MySQL的相關功能 79

          3.3 使用JSON Web Token實現身份授權和驗證 82

          3.3.1 JSON Web Token簡介 82

          3.3.2 在Express中使用JWT 83

          3.4 使用bcrypt加密模塊實現商城安全 86

          3.5 小結與上機練習 89

          第4章 開發用戶登錄和注冊模塊 96

          4.1 實現服務端的登錄和注冊模塊 96

          4.1.1 用戶數據表的定義 97

          4.1.2 封裝數據庫工具類與實現登錄和注冊接口 98

          4.2 實現用戶端的登錄和注冊功能 107

          4.2.1 搭建用戶端工程 108

          4.2.2 開發用戶端登錄和注冊頁面 110

          4.2.3 開發用戶端賬戶數據邏輯 113

          4.2.4 開發用戶端登錄和注冊接口邏輯 115

          4.3 實現后臺管理端的登錄和注冊功能 119

          4.4 小結與上機練習 121

          第5章 開發營銷推廣模塊 124

          5.1 實現服務端的運營推廣模塊 124

          5.1.1 定義運營位表結構和接口文檔 125

          5.1.2 實現運營位圖片上傳接口 131

          5.1.3 實現用戶鑒權中間件 133

          5.1.4 實現運營位業務接口 136

          5.2 實現后臺管理端的運營位管理模塊 138

          5.2.1 搭建后臺管理系統首頁 138

          5.2.2 實現創建運營位組件 141

          5.2.3 實現運營位管理模塊 146

          5.3 實現用戶端的運營位模塊 149

          5.4 小結與上機練習 152

          第6章 開發商品列表與詳情模塊 154

          6.1 開發服務端的商品相關模塊 154

          6.1.1 商品類別表的定義與接口實現 155

          6.1.2 商品表與相關接口的實現 158

          6.2 實現后臺管理端的商品管理模塊 167

          6.2.1 實現類別管理功能 167

          6.2.2 實現商品編輯模塊 172

          6.2.3 實現商品管理模塊 180

          6.3 實現用戶端的商品模塊 183

          6.3.1 實現用戶端首頁商品推薦模塊 184

          6.3.2 實現用戶端的商品詳情頁 189

          6.4 小結與上機練習 193

          第7章 開發購物車與訂單模塊 194

          7.1 實現服務端的購物車與訂單模塊 194

          7.1.1 購物車表的定義與功能接口的實現 195

          7.1.2 訂單表的定義與接口分析 200

          7.1.3 實現訂單模塊后端接口 202

          7.2 實現用戶端的購物車與訂單模塊 207

          7.2.1 實現購物車功能 207

          7.2.2 實現訂單模塊 212

          7.3 實現后臺管理端的訂單管理模塊 217

          7.4 小結與上機練習 218

          第8章 開發搜索與評價模塊 222

          8.1 實現服務端的搜索與評價模塊 222

          8.1.1 實現商品搜索接口 223

          8.1.2 評價數據結構與接口定義 224

          8.1.3 實現評價相關接口 226

          8.2 實現用戶端的搜索與評價模塊 229

          8.2.1 實現搜索功能 230

          8.2.2 實現創建商品評價功能 233

          8.2.3 實現商品評價展示功能 237

          8.3 實現后臺管理端的評價模塊 239

          8.4 小結與上機練習 242

          第9章 數據統計模塊與項目總結 243

          9.1 實現電商后臺數據統計模塊 243

          9.1.1 數據統計功能的后端接口定義 244

          9.1.2 數據統計功能的后端服務接口實現 245

          9.1.3 后臺管理端的數據圖表繪制 250

          9.2 項目總結 254

          9.3 小結與上機練習 256


          5

          編輯推薦

          《Vue.js 3.x+Express全棧開發:從0到1打造商城項目》是一本實戰型教程,專注于使用最新的Vue.js 3.x和Express框架來構建一個完整的電子商務平臺。以下是您可能需要這本書的原因:

          1全面而深入:《Vue.js 3.x+Express全棧開發:從0到1打造商城項目》首先介紹了Vue和Express的基本概念與框架結構,如Vue的組件化開發、數據綁定以及Express的路由處理和中間件使用等,為您打下堅實的基礎。

          2生態資源介紹:書中詳細講述了Vue和Express生態系統中的核心插件,讓您對UI搭建、網絡請求、路由管理、數據存儲與安全等方面有全面的了解。

          實戰項目經驗:通過引導您搭建一個完整的電商項目,包括前端用戶功能和后端API服務,幫助您獲得寶貴的實戰經驗。

          3功能完整:從用戶注冊登錄到商品展示、購物車以及后臺的商品和訂單管理,這本書將指導您一步步實現一個功能完備的電商平臺。

          4學習資源豐富:《Vue.js 3.x+Express全棧開發:從0到1打造商城項目》提供了完整的項目源代碼、導讀手冊和配套視頻教程,極大地便利了您的學習和實踐,并加速理解過程。

          5適用讀者廣泛:無論是正在尋求項目經驗的開發人員,還是希望通過實踐學習的在校學生,抑或是用作高校和培訓機構的實踐課教材,《Vue.js 3.x+Express全棧開發:從0到1打造商城項目》都是一個極佳的選擇。

          6這本書將幫助您掌握使用Vue和Express進行全棧開發的能力,更重要的是,在您完成閱讀和實踐后,能夠獨立負責電商項目的搭建和開發。

          把握機遇,深化知識,提升技能。相信《Vue.js 3.x+Express全棧開發:從0到1打造商城項目》將是您技術成長道路上的一塊墊腳石。

          本文摘自《Vue.js 3.x+Express全棧開發:從0到1打造商城項目》,獲出版社和作者授權發布。


          主站蜘蛛池模板: 亚洲熟妇AV一区二区三区浪潮| 亚欧成人中文字幕一区 | 中文字幕一区二区人妻性色| 精品无码人妻一区二区三区| 国产精品久久无码一区二区三区网 | 无码乱人伦一区二区亚洲| 国产一区二区三区高清视频 | 日本美女一区二区三区| 国精产品一区二区三区糖心| 亚洲电影国产一区| 无码人妻AⅤ一区二区三区| 日韩高清国产一区在线 | 福利一区二区三区视频午夜观看| 国产成人午夜精品一区二区三区| 久久国产精品一区| 久久久久人妻精品一区二区三区| 久久精品无码一区二区WWW| 一区二区中文字幕| 国产精品一区在线播放| 女女同性一区二区三区四区| 波多野结衣的AV一区二区三区| 精品乱子伦一区二区三区| 久久国产精品免费一区二区三区| 亚洲一区二区三区在线 | 乱中年女人伦av一区二区| 麻豆AV天堂一区二区香蕉| 一区五十路在线中出| 香蕉一区二区三区观| 亚洲AV无码国产精品永久一区| 国产另类ts人妖一区二区三区 | 天堂成人一区二区三区| 亚洲av鲁丝一区二区三区| 国产精品熟女视频一区二区| 亚洲制服中文字幕第一区| 亚洲A∨精品一区二区三区| 日韩精品中文字幕无码一区| 日本精品啪啪一区二区三区| 亚洲狠狠狠一区二区三区| 任你躁国产自任一区二区三区 | 中文字幕不卡一区| 国产福利一区二区精品秒拍|