vue引入iconfont/引入svg原理

news2024/11/24 16:02:29

前言

本文撰写的初衷是为了向组内成员推行使用svg sprites的方式管理项目的图标,由于实际工作中很多项目仍然采用font class的方式,这样不自觉带来一个痛点.

当项目一期开发完毕后,过段时间进入到项目二期。新增的开发需求不可避免的会增加新的图标,而font class需要全量打包图标的字体文件.

哪怕新需求只添加了一个图标,而前端同学却要将旧图标和新图标融合后重新打包生成一次字体文件,这样的结果让人无法接受.

svg sprites能完美的解决这一问题.整体思路是先将项目中每一个图标都生成一个svg文件与之对应,那么有多少个svg文件就相当于对应了多少个图标.

以后如果想新增一个图标,那么只需要添加一个新svg文件即可.那些已经存在的图标和svg文件则不需要再参与进来.

本文接下来将以vue3为基础框架,iconfont为图标库,一步步实践图标引入,使用以及管理的整个流程.另外在文章的后半部分,还会介绍一下多主题变色模式下svg图标的相应处理.

生成SVG

svg sprites简介

svg sprites这项技术很早就出来了,具体详情可以点击查看张鑫旭在2014年写的文章 未来必热:SVG Sprites技术介绍.

我们这里做一下简单介绍就进入实践阶段.svg sprites主要基于两个标签元素:.

对元素进行分组,它不会显示在界面上,相当于定义一个模板.元素用于引用并渲染图标.

例如存在以下某个svg图标(代码如下),它是一个爱心的形状.

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="24px" height="24px" viewBox="0 0 24 24">
        <path fill="#E86C60" d="M17,0c-1.9,0-3.7,0.8-5,2.1C10.7,0.8,8.9,0,7,0C3.1,0,0,3.1,0,7c0,6.4,10.9,15.4,11.4,15.8 c0.2,0.2,0.4,0.2,0.6,0.2s0.4-0.1,0.6-0.2C13.1,22.4,24,13.4,24,7C24,3.1,20.9,0,17,0z"></path>
</svg>

现在使用symbol标签将上面的path内容包裹一层,代码如下:

<svg>
    <symbol viewBox="0 0 24 24" id="heart">
        <path fill="#E86C60" d="M17,0c-1.9,0-3.7,0.8-5,2.1C10.7,0.8,8.9,0,7,0C3.1,0,0,3.1,0,7c0,6.4,10.9,15.4,11.4,15.8 c0.2,0.2,0.4,0.2,0.6,0.2s0.4-0.1,0.6-0.2C13.1,22.4,24,13.4,24,7C24,3.1,20.9,0,17,0z"></path>
    </symbol>
</svg>

接下来把symbol包裹后的代码放入页面中(代码如下),再添加一个display: none隐藏起来.这就相当于在页面上注册了一个id名为heart的图标.

此时页面的其他部分就可以引用这个图标,引用方式是在svg标签里面放入一个use标签,use标签的xlink:href填上要引用的图标id,界面就会渲染出爱心的形状.

<body>
    <svg style="display: none;">
        <symbol viewBox="0 0 24 24" id="heart">
            <path fill="#E86C60" d="M17,0c-1.9,0-3.7,0.8-5,2.1C10.7,0.8,8.9,0,7,0C3.1,0,0,3.1,0,7c0,6.4,10.9,15.4,11.4,15.8 c0.2,0.2,0.4,0.2,0.6,0.2s0.4-0.1,0.6-0.2C13.1,22.4,24,13.4,24,7C24,3.1,20.9,0,17,0z"></path>
        </symbol>
    </svg>

    <svg>
        <use xlink:href="#heart"/> <!-- 使用图标 -->
    </svg>
</body>

获取项目图标

前端同学拿到设计图之后,通常会整体浏览一遍整个项目需要用到的所有图标.

iconfont是阿里巴巴体验团队倾力打造的矢量图标库,里边包含海量的图标可供前端工程师选择和使用.

浏览器点击打开 iconfont官网 ,选择好自己的项目中要用到的图标,鼠标移动到图标上点击添加入库.

图标收集完后点击头部右侧导航栏的购物车,出现弹出框,点击添加至项目.所有图标确定添加到项目后,页面会自动跳转到导航栏资源管理--我的项目下的页面(如下图).
在这里插入图片描述

我们的目标是为了生成图标对应的svg文件,这里要做一下设置.打开上图中的项目设置选项,弹框打开后如下图.
在这里插入图片描述

弹框字体格式的那一栏,只保留SVG勾选项,其他都取消,设置好后点击保存按钮.

页面此时会刷新一遍,然后点击页面上的下载至本地的按钮,将所有图标的svg文件下载下来并解压,解压后的文件结构如下图.

在这里插入图片描述

观察上图中的文件结构,我们发现所有svg图标的代码全部都写在iconfont.svg这一个文件,这并不符合预期.我们希望的结果是一个图标对应一个svg文件,而不是像现在一样全部揉进了一个文件内.

虽然iconfont目前没有提供文件分离的机制,但是我们可以借助其他平台帮我们将融合的svg文件分离成单个文件. iconmoon 网站便具备这个功能,它也是一家和iconfont类似的图标库网站.

浏览器点击打开 iconmoon官网 ,选择顶部导航栏右侧的IcoMoon App进入图标选择页面,点击页面头部导航栏左侧的Imports Icons,将从iconfont下载的iconfont.svg文件导入,结果如下图.
在这里插入图片描述

iconfont那一栏可以看到我们导进去的图标展现到了页面上,接下来使用鼠标单击导进去的图标将其标记为选中,再点击页面左下角的Generate SVG & More按钮(如下图).

按钮点击后页面跳转,此时依旧点击左下角的Download按钮(如下图)下载图标.
在这里插入图片描述

下载完成后解压目录,解压后的目录下出现了SVG文件夹,打开该文件夹会发现所有图标都被分离成了单个文件(如下图).
在这里插入图片描述

项目设置

svg文件顺利获取到了,现在在vue3项目目录结构src -> assets文件夹下新建文件夹fonts和子文件夹fonts/svg,将上面生成的所有svg单文件扔到fonts/svg下面.

文件的设置完成,现在开始项目的配置,让vue3能顺利的管理和使用图标.

  • 第一步在项目根目录下打开命令行运行npm i svg-sprite-loader -D.我们之所以要安装依赖svg-sprite-loader,因为它能将svg文件的代码自动塞到一个个symbol标签中.
  • 第二步项目根目录下新建文件vue.config.js,熟悉vue的同学应该知道vue.config.js用来配置构建环境.

vue.config.js详细配置参数可点击查询 vue-cli官网 ,我们这里只需要知道如何配置svg-sprite-loader就可以.

众所周知,vue-cli的构建环境基于webpack,我们通过在vue.config.js文件中添加各类配置参数,vue-cli最终会将这些参数合并到webpack的配置里.

如此一来我们通过vue.config.js就能达到配置开发环境的目的,而不用直接去操作webpack的配置文件.

当前已经安装了依赖svg-sprite-loader,现在要把这个loader载入到webpack的配置中,通过在vue.config.js填写下面代码便可实现.

const resolve = require("path").resolve;

module.exports = {
   chainWebpack(config){
        //引入图标
        config.module.rule("svg").exclude.add(resolve("./src/assets/fonts/svg"));
        config.module.rule("icon").test(/\.svg$/)
        .include.add(resolve("./src/assets/fonts/svg")).end()
        .use("svg-sprite-loader")
        .loader("svg-sprite-loader")
        .options({
            symbolId:'icon-[name]'
        });
   }
}

系统学习过webpack配置的同学很容易能看出来上面代码的含义,上方代码首先将rule中设置的svg规则排除"./src/assets/fonts/svg"目录.

然后新增加一条规则icon"./src/assets/fonts/svg"目录包含了进去,这个目录就是我们存放所有svg文件的文件夹.

代码接下来使用.use.loadersvg-sprite-loader配置到项目环境里,并设置symbolIdicon-[name].

这里的symbolId关乎到标签生成的`id`名称.如果设置`symbolId`为`icon-[name]`,那么最后页面上标签引用图标时就会使用icon-加上文件名.

  • 第三步在assets/fonts下面新建文件index.js(文件结构如下图),并填写下面两行代码.

这两行代码主要使用了webpack中的require.context函数,它可以帮助我们自动引入文件模块.

require.context第一个参数代表目标文件目录,第二个参数是否应用于子文件夹,第三个参数匹配文件格式.

const load = require.context("./svg",false,/\.svg$/);
load.keys().map(load);

require.context执行完毕后返回结果load,返回值load本身就是一个引入模块的函数,另外它还包含一个keys属性,执行load.keys()返回结果如下.

 ["./arrow.svg", "./arrowon.svg", "./downarrow.svg", "./jiantou.svg", "./trash.svg", "./yiwenicon.svg"]

我们从这里可以看出load.keys()会返回fonts/svg文件夹下所有图标的相对路径,再使用loda函数去加载这些路径的文件,这样便实现了动态引入fonts/svg文件夹下的所有以.svg结尾的文件.

那么以后如果出现新增一个图标的需求,先在iconfont网站上下载单个svg文件,下载完成后直接丢到fonts/svg文件夹下就可以完成自动引入了.

在这里插入图片描述

  • 最后一步在项目的入口文件main.js调用第三步新建的index.js,执行所有svg文件的自动引入(代码如下).
import { createApp } from 'vue';
import App from './App.vue'; // 根组件
import "@/assets/fonts/index"; // 执行自动引入
import router from '@/router/index'; // 路由

createApp(App).use(router).mount('#app');

通过以上四步基本完成了项目的配置,整个运行过程可以做一下简单的梳理.

入口文件main.js启动后,执行assets/fonts/index.js启动所有svg文件的自动引入.

svg-sprite-loader一旦监听到项目中引入了以.svg结尾的文件,它就会把这些svg的代码内容全部都封装到一个个``标签里面(如下图),再一起插入到页面文档中.

这将相当于svg-sprite-loader帮助我们将所有的svg图标在页面上注册了,而我们剩下的事情就是在页面上去引用图标就行了.
在这里插入图片描述

图标引用

我们在Home主页下填写如下代码(效果图如下).将#icon-前缀加上fonts/svg下对应的文件名拼接而成的字符串赋予xlink:href属性,那么就会渲染出该文件对应的图标.

<template>
  <div class="home">
    <p class="title">Hello world</p>
    <svg>
        <use xlink:href="#icon-trash"/> <!-- 使用图标 -->
    </svg>
  </div>
</template>

在这里插入图片描述

组件引用

页面上使用svguse标签引用图标的方式不太优雅,我们可以将它改造成组件.

在全局组件文件夹components下新建文件Icon/index.vue.该组件接受两个参数namecolor(代码如下).

参数name对应要渲染的图标名称,color为需要渲染的颜色.这里需要格外注意,svg的颜色修改只能通过fill属性,color属性赋值时不奏效.

<template>
    <svg :style="{fill:color?color:''}">
        <use :xlink:href="'#icon-'+name"/>
    </svg>
</template>

<script>
export default {
 props:{
     name:String, //图标名称
     color:{ // 图标颜色
         type:String,
         deafult:null
     }
 }
}
</script>

现在在Home页面引用Icon组件(代码如下).

渲染的图标名称为trash,颜色为蓝色(效果图如下).

<template>
  <div class="home">
    <p class="title">Hello world</p>
    <Icon name="trash" color="blue"/><!-- 使用图标 -->
  </div>
</template>
<script>
import Icon from "@/components/Icon/index";
export default {
    components:{
        Icon
    }
}
</script>

在这里插入图片描述

多主题支持

通过上文讲解可知,当我们给``标签赋予样式属性fill,最终图标的颜色也会发生改变,这就为我们完成多主题的开发需求提供了可能.

我们接下来搭建一个点击按钮在线切换主题的场景,让svg图标也能随着主题的变换而改变.

配置多主题样式

首选在项目文件夹src/assets下新建文件scss/variable.scss,代码内容如下.

代码定义了三个主题,分别为默认主题主题1主题2.每个主题都定义了自己主题下的图标颜色和背景颜色.

代码下半部分定义了3mixin,分别用来设置fillcolorbackground-color属性.在每一个mixin里面,不同主题设置的颜色采用自己主题下的颜色设置.

// 默认主题
$icon-color:red;
$background-color:#fff;

// 主题1
$icon-color1:gray;
$background-color1:#eee;

// 主题2
$icon-color2:blue;
$background-color2:#999;

// 用于给svg填充颜色
@mixin fill {
    fill:$icon-color; //默认颜色用默认主题
    [data-theme = "theme1"] & { //切换到主题1时的颜色
        fill:$icon-color1;
    }
    [data-theme = "theme2"] & { //切换到主题2时的颜色
        fill:$icon-color2;
    }
}
//设置color属性
@mixin color {
    color:$icon-color; //默认颜色用默认主题
    [data-theme = "theme1"] & { //切换到主题1时的颜色
        color:$icon-color1;
    }
    [data-theme = "theme2"] & { //切换到主题2时的颜色
        color:$icon-color2;
    }
}

//设置背景颜色
@mixin backgroudColor {
    background-color:$background-color; //默认颜色用默认主题
    [data-theme = "theme1"] & { //切换到主题1时的颜色
        background-color:$background-color1;
    }
    [data-theme = "theme2"] & { //切换到主题2时的颜色
        background-color:$background-color2;
    }
}

variable.scss是一份全局多主题配置文件,该文件内不光可以配置各个主题下应该渲染的颜色,还可以配置字体大小,常用宽高等.

配置文件编写完成后,现在要将这份文件引用到项目当中.编辑器打开根目录下vue.config.js项目配置文件,新增代码如下.

const resolve = require("path").resolve;

module.exports = {
   chainWebpack(config){
        //引入图标
        config.module.rule("svg").exclude.add(resolve("./src/assets/fonts/svg"));
        config.module.rule("icon").test(/\.svg$/)
        .include.add(resolve("./src/assets/fonts/svg")).end()
        .use("svg-sprite-loader")
        .loader("svg-sprite-loader")
        .options({
            symbolId:'icon-[name]'
        });
   },
   css: {
    loaderOptions: {
        scss: {
            prependData: `@import "@/assets/scss/variable.scss";`
        },
    }
   } 
}

module.exports新增配置属性css,随后将我们在上面编写多主题配置文件的路径填入到prependData对应的值.

这里为了避免因为sass版本的不同导致文件引入失败,统一一下sasssass-loader的版本.

"sass": "1.26.5",
"sass-loader": "8.0.2",

vue.config.js配置完成后重启应用,variable.scss已经全局注入了应用.接下来我们在页面组件内不需要使用@import导入主题配置文件,variable.scss里面定义的变量和mixin可以直接拿来使用.

Icon改造

为了让图标响应主题的变换,全局的Icon组件做如下代码修改.color属性如果有传值,那么图标就按照传入的颜色渲染.如果没有传color,那么决定图标颜色的因素变成了类名icon.

<template>
    <svg class="icon" :style="{fill:color?color:''}">
        <use :xlink:href="'#icon-'+name"/>
    </svg>
</template>

<script>
export default {
 props:{
     name:String,
     color:{
         type:String,
         deafult:null
     }
 }
}
</script>

<style lang="scss" scoped>
 .icon{
   @include fill;
 }
</style>

类名 icon 里面调用 fill对应的mixin,文件variable.scssfill的定义如下面代码.

它最后返回一个属性 fill:color.默认情况下fill的颜色值为$icon-color.

当页面文档html标签上的属性data-theme值变成theme1时,fill渲染的颜色变成了主题1定义的颜色.同理切换到theme2,fill渲染的颜色变成了主题2定义的颜色.

// 用于给svg填充颜色
@mixin fill {
    fill:$icon-color; //默认颜色用默认主题
    [data-theme = "theme1"] & { //切换到主题1时的颜色
        fill:$icon-color1;
    }
    [data-theme = "theme2"] & { //切换到主题2时的颜色
        fill:$icon-color2;
    }
}

我们观察一下页面最终生成的dom结构就可以理解上面配置的目的,@mixin最终会将每个主题下的样式都生成了一份(如下图),这样一来只要``标签的data-theme等于哪个主题,对应主题的样式表就会生效.
在这里插入图片描述

页面校验

Home页面组件填写如下代码.在原来页面基础上新增了三个按钮默认主题主题1主题2.

点击按钮触发updateTheme函数,函数会修改``标签上data-theme的属性值,从而实现了主题切换的功能(效果图如下).

<template>
  <div class="home">
    <p class="title">Hello world</p>
    <Icon name="trash"/><!-- 使用图标 -->
    <button @click="updateTheme()">默认主题</button>
    <button @click="updateTheme('theme1')">主题1</button>
    <button @click="updateTheme('theme2')">主题2</button>
  </div>
</template>
<script>
import Icon from "@/components/Icon/index";
export default {
    components:{
        Icon
    },
    methods: {
        updateTheme(name){
            if(name == null){ // 采用默认主题
                document.documentElement.removeAttribute("data-theme");
            }else{
                document.documentElement.setAttribute("data-theme",name);
            }
        } 
    },
}
</script>
<style scoped lang="scss">
.home{
    height: 100%;
    @include backgroudColor;
}
.title{
  @include color;
}
</style>

最终效果图:
在这里插入图片描述

尾言

上文介绍的多主题实现方案操作起来非常简单,但不适合用于大型复杂的项目.

试想一下,如果一个大型项目包含十几种主题,而每一类主题下的css代码十分庞大,一次性将所有主题下的样式代码全部注入到应用里是不合适的.

最佳实践应该是用户点击切换某一类主题时,就按需加载那一类主题的样式,再注入到应用中渲染,这样可以极大的提升整体性能.最佳实践方式可以参考社区内关于多主题切换的文章.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/90891.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis数据结构及命令详解

个人博客地址&#xff1a; http://xiaohe-blog.top/ 文章目录0. 简述1. 通用命令1.1 keys1.2 del1.3 type1.4 exists1.5 expire1.6 ttl2. string 类型2.1 set2.2 get2.3 mset2.4 mget2.5 setnx2.6 setex2.4 incr2.5 incrby2.6 incrbyfloat3. hash 类型3.1 hset3.2 hget3.3 hmse…

互联网时代,云计算的6大特征

1 云计算的定义 云计算是目前业内的热点概念&#xff0c;它以开放的标准和服务为基础&#xff0c;以互联网为中心&#xff0c;提供安全、快速、便捷的数据存储和网络计算服务&#xff0c;让互联网这片“云”上的各种计算机共同组成数个庞大的数据中心及计算中心。它可以被看成…

Observability:我们该选 Beats 还是 Elastic Agents 来采集数据?

除了 Logstash 之外&#xff0c;Elastic 提供了两种主要的方式来向 Elasticsearch 发送数据&#xff1a; 我们可以选择直接把数据从 Beats 发送至 Elasticsearch。当然我们也可以通过 Logstash 更进一步处理再发送至 Elasticsearch。 另外一种方式是使用 Elastic Agents 来发送…

[附源码]Nodejs计算机毕业设计基于的二手车交易平台Express(程序+LW)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。欢迎交流 项目运行 环境配置&#xff1a; Node.js Vscode Mysql5.7 HBuilderXNavicat11VueExpress。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分…

[附源码]Python计算机毕业设计Django课室预约系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

Jmeter简单入门

背景 我们项目中一般测试接口都是用vscode中的REST Client插件&#xff08;推荐好用&#xff09;或者的话postman(适合写一些脚本和文件的上传) 但是他们都有一个不太行的功能&#xff0c;那就是多线程并发测试&#xff0c;其他市面上的什么apipost也都是不支持&#xff0c;网…

带你在Ubuntu 18.04上编译Linux内核

【推荐阅读】 一文了解Linux上TCP的几个内核参数调优 一文剖析Linux内核中内存管理 分析linux启动内核源码 一、环境说明 编译环境我选择了Ubuntu 18.04的虚拟机&#xff0c;内核截止2018-10-14最新版为4.18.14&#xff0c;笔者即将编译这个版本。 请确保磁盘空间足够&am…

Phoenix 对 Hbase 中表的映射

目录1&#xff09;表的关系2&#xff09;Hbase中创建表 test3&#xff09;视图映射4&#xff09;表映射数字类型说明1&#xff09;表的关系 默认情况下&#xff0c; HBase 中已存在的表&#xff0c;通过 Phoenix 是不可见的。 如果要在 Phoenix 中操作 HBase 中已存在的表&…

java计算机毕业设计基于安卓Android的车位服务管理APP

项目介绍 网络的广泛应用给生活带来了十分的便利。所以把车位服务管理与现在网络相结合,利用java技术建设车位服务管理APP,实现车位服务管理的信息化。则对于进一步提高车位服务管理发展,丰富车位服务管理经验能起到不少的促进作用。 车位服务管理APP能够通过互联网得到广泛的、…

Python 爬虫库 urllib 使用详解!

一、Python urllib库 Python urllib 库用于操作网页 URL&#xff0c;并对网页的内容进行抓取处理。 Python3 的 urllib。 urllib 包 包含以下几个模块&#xff1a; urllib.request - 打开和读取 URL。 urllib.error - 包含 urllib.request 抛出的异常。 urllib.parse - 解析 …

自学了半个月python,感觉没用,怎么办?

本人从零基础开始学习python&#xff0c;已有两年之久&#xff0c;虽然一路上磕磕绊绊&#xff0c;但学习了一段时间之后&#xff0c;日常很多繁琐的工作&#xff0c;在python的助力下确实得到了很好的解决&#xff0c;工作效率也大大提高。 回到问题上来&#xff0c;自学了半…

Windows11如何通过附近共享发送文件,附近共享传输文件到电脑

Windows11如何通过附近共享发送文件&#xff1f;2018年&#xff0c;微软推出了名为Nearear Share&#xff08;附近共享&#xff09;的新功能。Near share是一种在PC之间传输文件的新方式&#xff0c;类似Airdrop的功能&#xff0c;只需要开启蓝牙和WiFi就能分享照片/影片/文件给…

[附源码]Python计算机毕业设计Django快转二手品牌包在线交易系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

Android OpenGL ES 学习(八) –矩阵变换

OpenGL 学习教程 Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学习(三) – 绘制平面图形 Android OpenGL ES 学习(四) – 正交投影 Android OpenGL ES 学习(五) – 渐变色 Android OpenGL ES 学习(六) – 使用…

UML图讲解(关联关系,单向关联,双向关联,自关联,组合关系,依赖关系,继承关系,实现关系)

UML图讲解 简介&#xff1a;本文讲解UML图的各种情况下的含义。 简介 百度百科&#xff1a; UML-Unified Modeling Language统一建模语言&#xff0c;又称标准建模语言。是用来对软件密集系统进行可视化建模的一种语言。UML的定义包括UML语义和UML表示法两个元素。 UML是在开…

【实时数仓】动态分流的实现源码(反序列化器、配置表、广播流、业务流)

文章目录一 根据MySQL的配置表&#xff0c;动态进行分流1 自定义反序列化器&#xff08;1&#xff09;需求分析&#xff08;2&#xff09;代码实现2 从配置表中读取数据&#xff08;1&#xff09;自定义CDC采集的反序列化器&#xff08;2&#xff09;使用FlinkCDC读取配置表数据…

事务的隔离级别

目录 1.1 数据并发问题 1.2 SQL中的四种隔离级别 1.3 MySQL支持的四种隔离级别 1.4 如何设置事务的隔离级别 MySQL是一个 客户端&#xff0f;服务器 架构的软件&#xff0c;对于同一个服务器来说&#xff0c;可以有若干个客户端与之连接&#xff0c;每 个客户端与服务器连接…

简说四种架构的通用思维

一.自顶向下构建架构 ​1.首先定义问题&#xff0c;而定义问题中最重要的是定义客户的问题&#xff0c;特别主要识别出关键问题&#xff0c;关键问题是对客户有体感&#xff0c;能够解决客户痛点&#xff0c;通过一定的数据化来衡量识别出来&#xff0c;关键问题要优先给出解决…

我从“校园小白”到仿真“职场小达人”的CFD学习史

CFD属于CAE技术中比较难的一款软件&#xff0c;主要原因就是流体的特点决定了&#xff0c;因为相比于固体&#xff0c;流体太容易变形了&#xff0c;分子之间的距离比较大。所以&#xff0c;导致了一系列的问题。常常的结果是&#xff0c;忙了半天或者很长&#xff0c;根本得不…

Spring Security自定义认证逻辑实现图片验证码登录

前言 相信大家在网上冲浪都遇到过登录时输入图片验证码的情况&#xff0c;既然我们已经学习了 Spring Security&#xff0c;也上手实现过几个案例&#xff0c;那不妨来研究一下如何实现这一功能。 首先需要明确的是&#xff0c;登录时输入图片验证码&#xff0c;属于认证功能…