Vue--》从零开始打造交互体验一流的电商平台(一)

今天开始使用 vue3 + ts 搭建一个电商项目平台,因为文章会将项目的每处代码的书写都会讲解到,所以本项目会分成好几篇文章进行讲解,我会在最后一篇文章中会将项目代码开源到我的github上,大家可以自行去进行下载运行,希望本文章对有帮助的朋友们能多多关注本专栏,学习更多前端vue知识,然后开篇先简单介绍一下本项目用到的技术栈都有哪几个方面(阅读本文章能够学习到的技术):

vite:快速轻量且功能丰富的前端构建工具,帮助开发人员更高效构建现代Web应用程序。

pnpm:高性能、轻量级npm替代品,帮助开发人员更加高效地处理应用程序的依赖关系。

vue3:vue最新版本的用于构建用户界面的渐进式JavaScript框架。

typescript:javascript的超集,提供了静态类型检查,使得代码更加健壮。

vue-router:Vue.js官方提供的路由管理器与Vue.js紧密耦合,非常方便与Vue.js一同使用。

pinia:vue3构建的Vuex替代品,具有响应式能力,提供非常简单的 API,进行状态管理。

element-plus:基于Vue.js 3.0的UI组件库,用于构建高品质的响应式Web应用程序。

axios:基于Promise的HTTP客户端,可以在浏览器和node.js中使用。

@vueuse/core:针对vue3功能性的API库,提供了许多实用的功能。

当然还有许多其他的需要安装的第三方库,这里就不再一一介绍了,在项目中用到的地方自行会进行讲解,大家自行学习即可,现在就让我们走进vue3+ts的实战项目吧。

目录

初始化项目

包管理工具

src别名配置

重置默认样式

配置elementPlus

自定义全局样式

axios基础配置

API接口统一管理

全局组件封装

路由配置管理

store仓库配置

git管理配置


初始化项目

找到自己想要创建项目的文件夹,在地址栏输入cmd,从而进入当前文件路径,在当前路径下执行如下命令,使用vite构建工具进行创建vue3项目,具体的操作这里就不再赘述,不了解 vite 构建工具的朋友可以先去看 vite脚手架的搭建与使用 ,因为我这里使用 vite3 版本,其安装命令如下:

我这里就使用 pnpm 进行安装项目了,没有安装过pnpm的朋友,cmd进行全局安装即可,命令为:npm i -g pnpm 。

pnpm create vite

安装过程与我上面分享的文章基本一致,cd到项目路径安装下依赖,最后的结果如下表明创建项目成功:

然后将项目文件拖到编辑器中,打开终端执行 pnpm run dev 打开项目,结果如下:

包管理工具

团队开发项目的时候,需要统一包管理器工具,因为不同包管理器工具下载同一个依赖,可能版本不一样,导致项目出现bug问题,因此包管理器工具需要统一管理! 只需在 package.json 中加入一行代码来限制,如下含义:只允许使用 pnpm 来进行安装

"scripts": {
    // ... 其他命令
    "preinstall": "npx only-allow pnpm"
 }

直接将上面的代码复制如下,preinstall 是包安装工具的 钩子函数,在上例中作为 install 之前的拦截判断,也就是在 install 之前触发:

配置完成之后,当你使用的不是pnpm命令之后,控制台直接报错警告:

src别名配置

在开发项目的时候文件与文件关系可能很复杂,因此我们需要给src文件夹配置一个别名!在创建的项目中找到 vite.config.ts 配置文件,配置如下命令:

// vite.config.ts
import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
export default defineConfig({
    plugins: [vue()],
    resolve: {
        alias: {
            "@": path.resolve(__dirname, 'src') // 相对路径别名配置,使用 @ 代替 src
        }
    }
})

如果红色语法提示请安装 @type/node 其是TypeScript 的一个文件包,用于描述 Node.js 核心模块和常用的第三方库的类型信息,需要终端执行如下命令才能解决下图的警告:

pnpm i @types/node --save-dev

找到 tsconfig.json 配置文件,找到配置项 compilerOptions 添加配置,这一步的作用是让 IDE 可以对路径进行智能提示:

// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".", // 解析非相对模块的基地址,默认是当前目录
    "paths": { //路径映射,相对于baseUrl
      "@/*": ["src/*"] 
    }
  }
}

验证我们是否配置成功?我们可以在main.js入口文件处进行校验,如果有提示说明配置成功!

重置默认样式

在项目中我们都会用到一些标签,但是这些标签可能本身自带一些默认样式,这些默认样式可能会影响我们的排版布局,如果每次引用就去清除一遍默认样式有点太过繁琐,因此这里需要我们清除一下默认样式。执行如下命令安装第三方包: 

pnpm install reset.css --save

安装完成之后,我们在入口文件处进行引入即可,如下:

配置elementPlus

因为本项目需要采用 element-plus 组件库进行创建项目,其官方地址为:element-plus ,所以接下来需要对组件库进行一个安装配置,具体的实现过程如下,终端执行如下安装命令: 

pnpm install element-plus

这里我们采用自动按需导入的方式,如下需要安装两个插件:

pnpm install unplugin-auto-import unplugin-vue-components -D 

因为我们可以还需要用到elementplus中的图标,所以这里也采用自动导入的方式:

pnpm install unplugin-icons -D

因为本次使用的是vite + ts的模板,所以我们需要对下面文件进行如下操作修改:

// vite.config.ts
import {defineConfig} from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'
// 配置按需导入
import Icons from 'unplugin-icons/vite'
import IconsResolver from 'unplugin-icons/resolver'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'

const pathSrc = path.resolve(__dirname, 'src')

export default defineConfig({
    plugins: [vue(),
        AutoImport({
            // 自动导入 Element Plus 相关函数,如:ElMessage, ElMessageBox... (带样式)
            resolvers: [
              ElementPlusResolver(),
              // 自动导入图标组件
              IconsResolver({}),
            ],
        }),
        Components({
            resolvers: [
              // 自动注册图标组件
              IconsResolver({
                enabledCollections: ['ep'],
              }),
              // 自动导入 Element Plus 组件
              ElementPlusResolver(),
            ],
        }),
        Icons({
            autoInstall: true,
        }),
    ],
    resolve: {
        alias: {
            "@": pathSrc // 相对路径别名配置,使用 @ 代替 src
        }
    }
})

接下来我们直接在项目中引入一个button组件,尝试一下,如下说明我们自动按需引入成功!

接下来我们需要对elementPlus进行一个主题色的配置,这里我们采用sass样式系统,sass是一种预编译的css,作用类似于less,这里我们在vue项目中采用该预处理器进行处理样式,终端执行如下命令安装相应的插件: 

pnpm install sass -D

接下来在src目录下新建styles文件夹用于存放全局样式组件,该文件夹下新建element.scss文件,设置定制化样式,如下:

@forward 'element-plus/theme-chalk/src/common/var.scss' with (
  $colors: (
    'primary': (
      // 主色
      'base': #f94417,
    ),
    'success': (
      // 成功色
      'base': #f72f18,
    ),
    'warning': (
      // 警告色
      'base': #fd5e1d,
    ),
    'danger': (
      // 危险色
      'base': #e26237,
    ),
    'error': (
      // 错误色
      'base': #cf4444,
    ),
  )
)

然后我们需要在vite.config.ts文件夹下修改下面两处的内容:

回到页面可以看到我们的主题色已经生效了:

因为elementPlus默认是英文的,接下来我们还需要对其设置一下国际化配置,打开main.ys入口文件,进行如下配置:

import { createApp } from 'vue'
import 'reset.css'
import App from './App.vue'
// 配置国际化
import ElementPlus from 'element-plus'
import zhCn from 'element-plus/es/locale/lang/zh-cn'

createApp(App)
    .use(ElementPlus, { locale: zhCn })
    .mount('#app')

接下来我们引入一个分页器,看看是否变成中文了,如下看来是没毛病了!

自定义全局样式

在项目里一些组件共享的色值会以scss变量的方式统一放到一个名为var.scss的文件中,正常组件中使用,需要先导入scss文件,再使用内部的变量,比较繁琐,自动导入可以免去手动导入的步骤,直接使用内部的变量,如下:

我们在公共样式文件夹styles中新增一个var.scss文件,里面存放着全局公共样式:

然后我们在vite.config.ts中进行引入该文件夹:

可以看到我们的样式已经生效了!

axios基础配置

axios是一个基于promise的http客户端,用于浏览器和node.js环境中发起http请求。它提供了简单易用的api,可以用于执行各种类型的http请求,包括get、post、put、delete等。接下来对其进行简单的配置讲解:

终端执行如下命令进行安装axios:

pnpm install axios

然后我们在src文件夹下新建utils工具文件夹,在该文件夹下新建http.ts文件对axios进行二次封装

目的

使用请求拦截器,可以在请求拦截器中处理一些业务(开始进度条、请求头携带公共参数)

使用响应拦截器,可以在响应拦截器中处理一些业务(进度条结束、简化服务器返回的数据、处理http网络错误)

// axios基础封装
import axios from 'axios'

const http = axios.create({
    baseURL: '服务器接口根地址',
    timeout: 5000,
})

// 请求拦截器
http.interceptors.request.use(config => {
    // 请求拦截器
    return config
}, error => {
    return Promise.reject(error)
})

// 响应拦截器
http.interceptors.response.use(res => {
    return res.data
},  error => {
        //处理网络错误
        let msg = ''
        const status = error.response.status
        switch (status) {
            case 401:
                msg = 'token过期'
                break
            case 403:
                msg = '无权访问'
                break
            case 404:
                msg = '请求地址错误'
                break
            case 500:
                msg = '服务器出现问题'
                break
            default:
                msg = '网络出现问题'
                break
        }
        ElMessage({
            type: 'error',
            message: msg,
        })
        return Promise.reject(error)
    }
)

export default http

因为我们是自动按需导入,所以不需要像以前那样用到elementPlus组件还需要导入,这里直接使用相关api即可,不过可能ts文件会检索 ElMessage 不存在,会报错,这里我们需要在tsconfig.json中的include字段中添加auto-imports.d.ts就可以了:

"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "auto-imports.d.ts",],

接下来开始对我们封装的axios进行相关测试,我们在入口文件main.ts进行接口测试:

打开控制台可以看到我们的接口数据已经请求成功了!

这里我们把接口地址故意写错试试,可以看到如下的效果,还不错!

API接口统一管理

在开发项目的时候,接口可能很多需要统一管理。在src目录下去创建api文件夹去统一管理项目的接口:

统一管理我们项目用户的相关接口

// 统一管理我们项目用户的相关接口
import http from '@/utils/http'
import type { loginForm, loginResponseData, userResponseData } from './type'
// 统一管理接口
enum API {
  LOGIN_URL = '/user/login',
  USERINFO_URL = '/user/info',
}
// 暴露请求函数
// 登录接口的方法
export const reqLogin = (data: loginForm) =>
  http.post<any, loginResponseData>(API.LOGIN_URL, data)

// 获取用户信息接口方法
export const reqUserInfo = () =>
  http.get<any, userResponseData>(API.USERINFO_URL)

登录接口需要携带参数ts类型

// 登录接口需要携带参数ts类型
export interface loginForm {
  username: string
  password: string
}
interface dataType {
  token: string
}
// 登录接口返回数据类型
export interface loginResponseData {
  code: number
  data: dataType
}
interface userInfo {
  userId: number
  avatar: string
  username: string
  password: string
  desc: string
  roles: string[]
  buttons: string[]
  routes: string[]
  token: string
}
// 定义服务器返回用户信息相关数据类型
interface user {
  checkUser: userInfo
}
export interface userResponseData {
  code: number
  data: user
}

当然后期我们还需要其他的接口,这里仅仅作为一个展示,接下来进行接口测试:

全局组件封装

在vue3项目,有很多组件需要在多个地方进行使用,所以我们一般都将其封装成全局组件,然而单纯的封装成全局组件的话,每次使用还需要额外在每个项目中进行引入,就很烦,这里我们先将所有的全局进行全局注册,这样后面使用的话直接使用我们设置的组件名称即可,就不需要一次次再单独的进行引入了,如下:我们封装一个Loading加载组件为全局组件:

封装成全局组件之后,我们还需要在入口文件main.js进行一个引入注册:

上面index.js代码如下,方便大家复制直接使用即可:

import { defineAsyncComponent } from "vue";
// 获取要注册的全局组件
const components = import.meta.glob("./global/*.vue");

// 对外暴露插件
export default function install(app: any) {
  for (const [key, value] of Object.entries(components)) {
    const name = key.slice(key.lastIndexOf("/") + 1, key.lastIndexOf("."));
    app.component(name, defineAsyncComponent(value as any));
  }
}

然后Loading组件的加载的话,大家可以仿照 网站 里面的案例进行使用,还是有免费的找找就行: 

然后这里我们将本次使用的Loading加载组件代码也分享出来,供大家使用:

<template>
    <div class="load">
        <div class="loading">
        <div class="vsg">
            <svg viewBox="0 0 50 50">
            <circle class="ring" cx="25" cy="25" r="20"></circle>
            <circle class="ball" cx="25" cy="5" r="3.5"></circle>
            </svg>
        </div>
        <div class="text">
            Loading
        </div>
        </div>
    </div>
</template>
  
<style lang="scss" scoped>
.load {
    width: 100%;
    height: 100%;
    position: absolute;
    z-index: 3;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: rgb(0, 0, 0);
    .loading {
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
        .vsg {
            display: flex;
            justify-content: center;
            align-items: center;
            @keyframes spin {
                to {
                    transform: rotate(360deg);
                }
            }
            svg {
                width: 3.75em;
                animation: 1.5s spin ease infinite;
            }
            .ring {
                fill: none;
                stroke: hsla(106, 97%, 59%, 0.3);
                stroke-width: 2;
            }
            .ball {
                fill: #00ff85;
                stroke: none;
            }
        }
        .text {
            text-align: center;
            font-size: 16px;
            background: linear-gradient(to right, #00ff85, #5090ff);
            background-clip: text;
            -o-background-clip: text;
            -ms-background-clip: text;
            -moz-background-clip: text;
            -webkit-background-clip: text;
            color: transparent;
        }
    }
}
</style>

接下来我们在App.vue组件进行引入loading组件,如下:

回到浏览器可以看到我们的loading组件已经加载出来了,后期可以根据情况使用异步加载的组件或者使用v-if来进行操作,博主这里不再赘述:

路由配置管理

我们在开始搭建后台项目之前,都要仔细考虑一下路由应该如何配置,以下是本项目配置路由的详细步骤,如果想更加深入了解vue3路由知识,推荐参考我之前的文章:Vue 3 路由进阶——从基础到高级的完整指南:

安装配置路由的第三方包:

pnpm install vue-router

安装完路由包之后,接下来我们要先创建路由组件,因为项目仅仅是一个后台所以我们只需要在src目录下新进views文件,再创建3个路由组件即可:

创建完路由组件之后,接下来开始进行相关router配置:

// 通过vue-router插件实现模板路由配置
import { createRouter, createWebHistory } from 'vue-router'
import { constantRoute } from './routes'
 
// 创建路由器
const router = createRouter({
  // 路由模式
  history: createWebHistory(),
  routes: constantRoute,
  // 滚动行为
  scrollBehavior() {
    return {
      left: 0,
      top: 0,
    }
  },
})
export default router

这里我单独将routes的属性对象抽离出一个js文件出来 ,便于后期的维护,代码如下:

// 对外暴露路由(常量路由)
export const constantRoute = [
  {
    path: '/login',
    name: 'login', // 命名路由
    component: () => import('@/views/login/index.vue'),
    meta: {
      title: '登录页面',
    },
  },
  {
    path: '/',
    name: 'home',
    component: () => import('@/views/home/index.vue'),
    meta: {
      title: '后台页面',
    },
  },
  {
    path: '/404',
    name: '404',
    component: () => import('@/views/404/index.vue'),
    meta: {
      title: '404界面',
    },
  },
  {
    path: '/:pathMatch(.*)*',
    name: 'any',
    redirect: '/404',
  },
]

接下来在入口文件 main.ts 处进行路由router的挂载:

如果想把写好的路由进行展示的话,需要通过 router-view 作为路由出口,路由匹配到的组件将进行响应的渲染,这里在App根组件上进行展示:

最终呈现的效果如下所示:

store仓库配置

接下来我们需要对我们项目进行一个仓库管理,这里用到了pinia状态管理工具,不了解pinia的朋友,推荐看一下我之前讲解的文章:探索Pinia:Vue状态管理的未来 ,本项目就不再着重讲解其具体知识了。具体讲解如下:

终端执行如下命令安装pinia仓库:

pnpm install pinia

在src目录下新建store文件夹,文件夹下新建 index.ts 文件,暴露如下代码:

// 设置pinia仓库
import { createPinia } from 'pinia'
const pinia = createPinia()
// 对外暴露:入口文件需要安装仓库
export default pinia

在main.ts入口文件出进行pinia的挂载:

import { createApp } from 'vue'
import 'reset.css'
import App from './App.vue'
// 配置国际化
import ElementPlus from 'element-plus'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
// 引入自定义插件对象:注册整个项目的全局组件
import globalComponents from '@/components'
// 导入路由配置
import router from '@/router'
// 导入仓库
import pinia from '@/store'

createApp(App)
    .use(ElementPlus, { locale: zhCn }) // 配置中文国际化
    .use(globalComponents) // 安装全局路由组件
    .use(router) // 安装路由
    .use(pinia) // 安装仓库
    .mount('#app')

接下来在store中新建文件夹modules用于存储仓库文件,在该文件夹创建一个login.js文件,用来存储登录相关数据,这里采用组合式API的写法,如下案例:

import { defineStore } from "pinia";
import { ref } from "vue"

export const useMemberStore = defineStore("login", () => {
    const profile = ref();
    const setProfile = (val: number) => {
        profile.value = val;
    }
    const clearProfile = () => {
        profile.value = undefined
    }
    return { profile, setProfile, clearProfile }
})

git管理配置

接下来我们需要对我们上面撰写的项目初始化模板进行一个git上传,进行版本管理操作,这里我们使用可视化工具 github desktop 工具进行操作,不了解这个工具的参考:文章 ,里面详细记录了这个工具的操作,然后我们先创建存储库:

点击新建存储库之后,这里我们需要给仓库中输入一些相应的信息,这里我将之前写的一个项目作为本地路径上传上去,然后点击新建存储库即可: 

然后这里我们点击右上角的发布存储库按钮,将本地创建的存储库推送到远程仓库上: 

点击之后会出现弹框,这里我们需要取消勾选,让仓库成为公共仓库,任何人都能访问到,然后点击发布即可: 

打开github之后,就可以看到我们的创建的仓库已经出现了: 

然后我们把之前写的一个电商项目里面的文件copy一下放到仓库当中去,如下github desktop出现了我们文件的差异提示,每个更改的文件以及里面具体的内容都能看到, 如下: 

刷新浏览器之后,可以看到我们的项目已经全部推送到远程仓库上去了,很方便不需要再像git命令行那样一个一个的命令去敲: 

后期我们在本地进行什么样的修改,github desktop工具都能识别到我们哪些地方进行了修改,如下我在本地代码文件中,main.ts文件下面输入两行空行,工具都识别到我的更改,是不是很方便! 

注意:如果已经学习过我上一个项目的朋友可能已经了解过项目开始前的一些基础配置,觉得我再在新的项目再讲一遍有点啰嗦,但是我仍然坚持不厌其烦的去再讲一遍,一方面是培养自己的习惯另一方面是想不断加深读者对项目开始前基础配置的熟练程度,希望大家能够在小事中获得经验。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Node.js工程师养成计划】之express中间件与接口规范

一、Express中间件的概念与基本应用 const express require(express)// 加一个注释&#xff0c;用以说明&#xff0c;本项目代码可以任意定制更改 const app express()const PORT process.env.PORT || 3000// // 挂载路由 // app.use(/api, router)// // 挂载统一处理服务端…

【倪亲斫经典水墨云纹仲尼式】倪诗韵亲斫古琴

【倪亲斫经典水墨云纹仲尼式】倪诗韵亲斫古琴 松透润&#xff0c;适合大曲文曲潇湘欸乃平沙&#xff0c;余韵悠长&#xff0c;手感极其舒适&#xff0c;久弹不疲。

[Linux][网络][TCP][三][超时重传][快速重传][SACK][D-SACK][滑动窗口]详细讲解

目录 1.超时重传1.什么是超时重传&#xff1f;2.超时时间是如何确定的&#xff1f; 2.快速重传3.SACK4.D-SACK1.ACK丢失2.网络延迟 5.滑动窗口0.问题抛出1.发送方的滑动窗口2.如何表示发送方的四个部分&#xff1f;3.接收方的滑动窗口4.滑动窗口的完善理解 1.超时重传 1.什么是…

C++手写协程项目(协程实现线程结构体、线程调度器定义,线程挂起函数、线程切换函数、线程恢复函数、线程结束函数、线程结束判断函数,模块测试)

协程结构体定义 之前我们使用linux下协程函数实现了线程切换&#xff0c;使用的是ucontext_t结构体&#xff0c;和基于这个结构体的四个函数。现在我们要用这些工具来实现我们自己的一个线程结构体&#xff0c;并实现线程调度和线程切换、挂起。 首先我们来实现以下线程结构体…

Splay 树简介

【Splay 树简介】 ● Treap 树解决平衡的办法是给每个结点加上一个随机的优先级&#xff0c;实现概率上的平衡。Splay 树直接用旋转调整树的形态&#xff0c;通过旋转改善树的平衡性。计算量小&#xff0c;效果好。 ● Splay 树的旋转主要分为“单旋”和“双旋”。 所谓“单旋”…

基于52单片机的AS608指纹密码锁电路原理图+源程序+PCB实物制作

目录 1、前言 2、实物图 3、PCB图 4、原理图 5、程序 资料下载地址&#xff1a;基于52单片机的AS608指纹密码锁电路原理图源程序PCB实物制作 1、前言 这是一个基于AS608STC89C52单片机的指纹识别和键盘密码锁。 里面包括程序&#xff0c;原理图&#xff0c;pcb图和实…

OpenNJet:云原生技术中的创新者与实践者

目录 引言OpenNJet介绍OpenNJet优势1. 性能无损动态配置2. 灵活的CoPilot框架3. 支持HTTP/34. 支持国密5. 企业级应用6. 高效安全 OpenNJet 编译与安装环境准备编译环境配置配置yum源yum 安装软件包创建符号连接修改 ld.so.conf 配置 编译代码 部署 WEB SERVER配置OpenNJet部署…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-13-按键实验

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

FTP协议与工作原理

一、FTP协议 FTP&#xff08;FileTransferProtocol&#xff09;文件传输协议&#xff1a;用于Internet上的控制文件的双向传输&#xff0c;是一个应用程序&#xff08;Application&#xff09;。基于不同的操作系统有不同的FTP应用程序&#xff0c;而所有这些应用程序都遵守同…

计算机网络【应用层】邮件和DNS

文章目录 电子邮件DNSDNS提供的服务&#xff1a;域名分级域名解析流程DNS资源记录DNS服务器类型 电子邮件 使用SMTP协议发送邮件之前&#xff0c;需要将二进制多媒体数据编码为ASCII码SMTP一般不使用中间邮件服务器发送邮件&#xff0c;如果收件服务器没开机&#xff0c;那么会…

解决jar包中没有主清单目录的问题

文章目录 解决jar包中没有主清单目录的问题问题描述环境描述方法一 | 阿里巴巴构造器的通用解决方案方式二 | 指定MANIFEST.MF路径 解决jar包中没有主清单目录的问题 问题描述 很简单可能很多人都遇到过&#xff0c;maven项目打成jar包后执行报错&#xff1a;jar包中没有主清单…

在模方中已经选好水岸线了,但是点处理瓦块的时候还是提示水岸线没选

答&#xff1a;能部分位置不闭合&#xff0c;双击右键闭合一下&#xff0c;可以强行闭合缺口。 模方是一款针对实景三维模型的冗余碎片、水面残缺、道路不平、标牌破损、纹理拉伸模糊等共性问题研发的实景三维模型修复编辑软件。模方4.1新增自动单体化建模功能&#xff0c;支持…

高情商回复(不是)

背景介绍 在抖音上有这样的视频&#xff0c;视频就是一张图&#xff0c;图上问了一个问题&#xff1a;饭局上&#xff0c;你去帮领导盛饭&#xff0c;领导接过后说&#xff1a;‘盛这么多&#xff0c;喂猪呢&#xff1f;’咋回&#xff1f; 底下有一个搞笑评论&#xff1a;猪可…

迅雷永久破解

链接&#xff1a;https://pan.baidu.com/s/1ZGb1ljTPPG3NFsI8ghhWbA?pwdok7s 下载后解压 以管理员身份运行绿化.bat&#xff0c;会自动生成快捷方式&#xff0c;如果没有可以在program中运行Thunder.exe

UDP如何端口映射?

UDP端口映射是一种网络技术&#xff0c;通过它可以实现在异地组网的情况下&#xff0c;不暴露在公网上&#xff0c;通过私有通道传输数据&#xff0c;并对数据进行安全加密&#xff0c;以保障数据的安全性。这项技术在如今日益复杂和危险的网络环境中显得尤为重要。 UDP&#x…

Rust 适合哪些场景?

目录 二、Rust 适合哪些场景&#xff1f; 三、Rust 社区的发展趋势如何&#xff1f; 四、Rust 快速搭建一个WebServer服务器 一、Rust是什么&#xff1f; Rust是一门赋予每个人构建可靠且高效软件能力的语言。 Rust 程序设计语言 一门帮助每个人构建可靠且高效软件的语言。…

tomcat-以服务的方式重启tomcat

背景 双击tomcat的bin目录下面的startup.bat&#xff0c;会留下一个cmd的窗口&#xff0c;很不优雅 使用service服务的方式启动&#xff0c;并且设置为自动启动 找到tomcat的bin目录输入cmd&#xff0c;按Enter&#xff0c;进入命令行界面。执行“service.bat install” 。&…

详解嵌入式MCU运行时分配的stack和heap

目录 概述 1 认识stack和heap 1.1 栈区&#xff08;stack&#xff09; 1.2 堆区&#xff08;heap&#xff09; 2 stack和heap的区别 2.1 管理方式的不同 2.2 空间大小不同 2.3 产生碎片不同 2.4 增长方式不同 2.5 分配方式不同 2.6 分配效率不同 3 确定stack和heap…

架构师:搭建Spring Security、OAuth2和JWT 的安全认证框架

1、简述 Spring Security 是 Spring 生态系统中的一个强大的安全框架,用于实现身份验证和授权。结合 OAuth2 和 JWT 技术,可以构建一个安全可靠的认证体系,本文将介绍如何在 Spring Boot 中配置并使用这三种技术实现安全认证,并分析它们的优点。 2、Spring Security Spri…

Linux基础04-Linux中目录和文件都能操作的命令

前面两节我们分别学习了目录操作命令和文件操作命令&#xff0c;那么有没有一些既可以操作目录&#xff0c;又可以操作文件的命令呢&#xff1f; 这样我们就不需要记住两套命令了。 其实还真有&#xff0c;今天这一章就带大家学习Linux中目录和文件都能操作的命令 最近无意间获…