Vue项目整合与优化
前几篇文章,我们讲述了 Vue 项目构建的整体流程,从无到有的实现了单页和多页应用的功能配置,但在实现的过程中不乏一些可以整合的功能点及可行性的优化方案,就像大楼造完需要进行最后的项目验收改进一样,有待我们进一步的去完善。
使用 alias 简化路径
使用 webpack 构建过 Vue 项目的读者应该知道 alias
的作用,我们可以使用它将复杂的文件路径定义成一个变量来访问。在不使用 alias 的项目中,我们引入文件的时候通常会去计算被引入文件对于引入它的文件的相对路径,比如像这样:
import HelloWorld from '../../../../HelloWorld.vue'
一旦相对层次结构较深,我们就很难去定位所引入文件的具体位置,其实这并不是我们应该操心的地方,完全可以交给 webpack 来进行处理。在原生的 webpack 配置中我们可以定义 alias 来解决这一问题:
const path = require('path');// 解析路径的函数
const resolve = dir => {return path.join(__dirname, dir); // 将当前目录与给定目录连接
}module.exports = {// 其他配置...resolve: {alias: {'@': resolve('src'), // 将 '@' 映射到 'src' 目录_lib: resolve('src/common'), // 将 '_lib' 映射到 'src/common' 目录_com: resolve('src/components'), // 将 '_com' 映射到 'src/components' 目录_img: resolve('src/images'), // 将 '_img' 映射到 'src/images' 目录_ser: resolve('src/services'), // 将 '_ser' 映射到 'src/services' 目录}},// 其他配置...
}
上方我们在 webpack resolve(解析)对象下配置 alias 对象的值,将常用的一些路径赋值给了我们自定义的变量,这样在配置了别名之后,可以在代码中使用这些别名来导入模块。:
import HelloWorld from '_com/HelloWorld.vue'
alias
对象:定义了一系列别名,这样在你的 JavaScript 或 Vue 文件中,你可以用简短的别名来引用相关目录,而不必使用相对路径
而在 CLI 3.x 中我们无法直接操作 webpack 的配置文件,我们需要通过 chainWebpack (在“Webpack在Vue CLI中的应用”中有较详细的解释)来进行间接修改,代码如下:
/* vue.config.js */
module.exports = {...chainWebpack: config => {config.resolve.alias.set('@', resolve('src')).set('_lib', resolve('src/common')).set('_com', resolve('src/components')).set('_img', resolve('src/images')).set('_ser', resolve('src/services'))},...
}
如果使用 VSCode,可以在 jsconfig.json
或 tsconfig.json
中定义路径,以便编辑器能够识别这些别名:
{"compilerOptions": {"baseUrl": ".","paths": {"@/*": ["src/*"],"_lib/*": ["src/common/*"],"_com/*": ["src/components/*"],"_img/*": ["src/images/*"],"_ser/*": ["src/services/*"]}}
这样我们修改 webpack alias 来简化路径的优化就实现了。但是需要注意的是对于在样式及 html 模板中引用路径的简写时,前面需要加上 ~
符,否则路径解析会失败,如:
.img {background: url('~_img/home.png'); /* 使用 ~ 表示从别名中导入 */
}
拓展1
1.resolve
函数的作用
resolve
函数是一个常用的工具函数,通常用于将相对路径转换为绝对路径。这个函数通过 path.join
方法,将当前文件的目录(由 __dirname
提供)与给定的目录名连接,从而生成一个绝对路径。
在上文的代码中:
const path = require('path');const resolve = dir => {return path.join(__dirname, dir); // 将当前目录与给定目录连接
};
dir:
- 这是函数的参数,代表您希望连接的目录名。它可以是一个相对路径,相对于当前文件的目录
结合起来:
假设项目结构如下:
/my-project├── src│ ├── components│ └── services
可以在 config.js
中使用 resolve
函数来设置别名,如下所示:
const path = require('path');const resolve = dir => {return path.join(__dirname, dir);
};module.exports = {chainWebpack: config => {config.resolve.alias.set('@', resolve('src')) // 将 '@' 映射到 'src' 目录.set('_com', resolve('src/components')) // 将 '_com' 映射到 'src/components' 目录.set('_ser', resolve('src/services')); // 将 '_ser' 映射到 'src/services' 目录}
};
一旦设置了别名,就可以在项目中使用这些别名来导入模块,例如:
// 引入组件
import MyComponent from '_com/MyComponent.vue';// 引入服务
import MyService from '_ser/MyService';
2.使用 ~
前缀的原因
当在样式表或 HTML 模板中引入资源时,如果希望使用 Webpack 的模块解析特性,需要在路径前加上 ~
符号。这样做的目的有几个:
-
模块解析:
~
符号告诉 Webpack 从node_modules
或配置的别名目录中解析路径。这使得开发者可以方便地引用模块或资源,而不必使用相对路径。 -
避免路径错误: 当使用相对路径时,可能会因为文件位置的变化导致路径失效。而使用
~
前缀能够确保路径正确,即使文件位置发生变化。
这里简单的举个例子
在 CSS 文件中
.img {background: url('~_img/home.png'); /* 正确:使用 ~ 前缀 */
}
在 HTML 模板中
如果使用 Vue、React 或其他框架的模板文件,也需要使用 ~
符号来引入样式或资源:
<template><div class="img" style="background-image: url('~_img/home.png');"></div>
</template>
在webpack.config.js
中
const path = require('path');module.exports = {resolve: {alias: {'_img': path.resolve(__dirname, 'src/images'), // 示例别名配置}}
};
-
没有
~
的情况: 如果在路径前面不加~
,Webpack 将会尝试从当前文件位置的相对路径进行解析,这可能会导致找不到文件的错误。
整合功能模块
在多页应用的构建中,由于存在多个入口文件,因此会出现重复书写相同入口配置的情况,这样对于后期的修改和维护都不是特别友好,需要修改所有入口文件的相同配置,比如在 index 单页的入口中我们引用了 VConsole 及 performance 的配置,同时在 Vue 实例上还添加了 $openRouter 方法:
import Vue from 'vue'
import App from './index.vue'
import router from './router'
import store from '@/store/'
import { Navigator } from '../../common'// 如果是非线上环境,不加载 VConsole
if (process.env.NODE_ENV !== 'production') {var VConsole = require('vconsole/dist/vconsole.min.js');var vConsole = new VConsole();//启用 Vue.js 的性能监控功能,可以在 Chrome 开发者工具中查看组件渲染的性能分析Vue.config.performance = true;
}//将 Navigator.openRouter 方法挂载到 Vue 原型上
Vue.$openRouter = Vue.prototype.$openRouter = Navigator.openRouter;new Vue({router,store,render: h => h(App)
}).$mount('#app')
而在 page1 和 page2 的入口文件中也同样进行了上述配置,那我们该如何整合这些重复代码,使其能够实现一次修改多处生效的功能呢?最简单的方法便是封装成一个共用方法来进行调用,这里我们可以在 common 文件夹下新建 entryConfig 文件夹用于放置入口文件中公共配置的封装,封装代码如下:
import { Navigator } from '../index'export default (Vue) => {// 如果是非线上环境,不加载 VConsoleif (process.env.NODE_ENV !== 'production') {var VConsole = require('vconsole/dist/vconsole.min.js');var vConsole = new VConsole();Vue.config.performance = true;}Vue.$openRouter = Vue.prototype.$openRouter = Navigator.openRouter;
}
上述代码我们向外暴露了一个函数,在调用它的入口文件中传入 Vue 实例作为参数即可实现内部功能的共用,我们可以将原本的入口文件简化为:
import Vue from 'vue'
import App from './index.vue'
import router from './router'
import store from '@/store/'
import entryConfig from '_lib/entryConfig/'// 调用公共方法加载配置
entryConfig(Vue)new Vue({router,store,render: h => h(App)// 使用 render 函数渲染 App 组件
}).$mount('#app') // 将根实例挂载到 id 为 app 的 DOM 元素上
h
是createElement
的别名。render函数的这个用法是反应式的,并且它的结构相对简洁。
这样我们便完成了入口文件配置的整合,当然你还可以给该函数传入 router 实例及自定义参数用于其他共用配置的封装。
拓展2
1.VConsole的作用
VConsole
是一个轻量级的移动端调试工具,主要用于在移动设备上调试 JavaScript 应用。它提供了一个可视化的控制台,让开发者能够轻松查看日志、网络请求、错误信息和其他调试信息,类似于浏览器开发者工具的控制台功能。
主要特性
-
日志记录: 您可以在 VConsole 中查看
console.log
,console.error
,console.warn
, 和console.info
等输出的日志信息。 -
网络请求监控: VConsole 能够捕获和显示应用发出的网络请求,包括请求的 URL、方法、状态码和响应时间等信息。
-
原生错误捕获: 捕获 JavaScript 运行时错误并在控制台中显示错误信息,方便调试。
-
元素查看: 可以查看和操作 DOM 元素的状态(在某些情况下)。
-
支持自定义功能: 开发者可以扩展 VConsole 的功能,添加自定义的面板和功能。
下面介绍它的基础用法
安装
要在项目中使用 vconsole
,首先需要安装它。可以通过 npm 或 yarn 安装:
npm install vconsole && yarn add vconsole
然后,在应用中引入并实例化它:
import VConsole from 'vconsole';// 仅在开发环境中启用 VConsole
if (process.env.NODE_ENV !== 'production') {const vConsole = new VConsole();
}
简单的 VConsole 使用示例
import VConsole from 'vconsole';if (process.env.NODE_ENV !== 'production') {const vConsole = new VConsole(); // 实例化 VConsole
}// 示例日志
console.log('Hello, VConsole!');
console.error('This is an error message!');
2.render函数的详细介绍
1. render
函数的基本概念
在 Vue.js 中,render
函数是一种编程方式来描述组件如何生成虚拟 DOM。每当 Vue 组件的状态变化时,render
函数会被重新调用,生成新的虚拟 DOM,并与之前的虚拟 DOM 进行比较以实现高效的更新。
2. render
函数的结构
render
函数通常在 Vue 组件的定义中使用,基本的形式如下:
export default {render(createElement) {// 生成虚拟 DOMreturn createElement('div', 'Hello, World!');}
}
- createElement: 是一个函数,用于创建虚拟节点(VNode)。该函数是 Vue 内部实现的一部分。
3. 创建虚拟节点(VNode)
虚拟节点是 Vue 用来描述底层 DOM 的数据结构。通过 createElement
,可以创建不同类型的节点:
3.1. 创建 HTML 元素
render(createElement) {return createElement('h1', 'Hello, World!');
}
3.2. 创建组件
import MyComponent from './MyComponent.vue';render(createElement) {return createElement(MyComponent);
}
3.3. 传递属性
可以传递属性和事件监听器给创建的元素或组件。属性可以通过一个对象传递,包含 attrs
、props
和 on
等字段:
render(createElement) {return createElement('button', {attrs: {type: 'button',},on: {click: this.handleClick}}, 'Click Me');
}
3.4. 嵌套子元素
可以通过传递一个虚拟节点数组来创建嵌套的结构:
render(createElement) {return createElement('div', [createElement('h1', 'Title'),createElement('p', 'This is a paragraph.'),]);
}
4. 与模板语法的比较
虽然模板语法更常用,且更简洁,但 render
函数提供了更大的灵活性。
4.1. 逻辑复杂性
当需要在渲染过程中进行复杂的逻辑判断时,render
函数可以更容易地进行条件判断:
render(createElement) {return this.isLoggedIn? createElement('h1', 'Welcome back!'): createElement('h1', 'Please log in.');
}
4.2. 动态生成结构
在某些情况下,可能需要动态生成组件或元素,render
函数能够更好地处理这种情况:
javascript
render(createElement) {return this.items.map(item => createElement('li', item));
}
5. 支持 JSX
如果项目配置支持 JSX,可以使用 JSX 语法来编写 render
函数,使代码更简洁和可读:
render() {return (<div><h1>Hello, JSX!</h1><MyComponent /></div>);
}
6. 高级用法
6.1. 使用 Slots
如果组件支持插槽,可以在 render
函数中使用 this.$slots
来访问插槽内容:
javascript
render(createElement) {return createElement('div', this.$slots.default);
}
6.2. 具名插槽
具名插槽可以通过传递一个 vnode
数组来实现:
render(createElement) {return createElement('div', [createElement('header', this.$slots.header),createElement('main', this.$slots.default),createElement('footer', this.$slots.footer),]);
}
6.3. 动态组件
可以通过 is
属性来动态渲染不同的组件:
render(createElement) {return createElement('component', {props: { is: this.currentComponent }});
}
7. 性能优化
- 函数式组件: 如果组件不需要维护状态,可以考虑使用函数式组件,这样可以减少开销。函数式组件的
render
函数无需this
,并且可以更高效地渲染。
export default {functional: true,render(createElement, context) {return createElement('div', context.children);}
}
开启 Gzip 压缩
在《webpack 在 CLI 3 中的应用》章节,我们介绍了 CLI 为我们内置的 webpack plugins,使用这些内置插件基本已经能够满足我们大多数项目的构建和优化,当然你仍然可以为项目添加自己想要的插件来实现一些差异化的功能,比如使用 compression-webpack-plugin 来开启 Gzip 压缩。在 vue.config.js 配置文件中,我们通过 configureWebpack 中返回一个对象来实现 plugins 的合并:
/* vue.config.js */
const isPro = process.env.NODE_ENV === 'production'module.exports = {...//使用configureWebpack 直接修改 Webpack 的配置。configureWebpack: config => {if (isPro) {return {plugins: [new CompressionWebpackPlugin({// 定义生成的压缩文件的名称。[path]表示原始文件的路径和 [query]是查询字符串。如果原始文件是 app.js,压缩后文件名将是 app.js.gzfilename: '[path].gz[query]',// 使用 gzip 压缩算法algorithm: 'gzip', // 正则表达式匹配需要被压缩的文件类型test: new RegExp('\\.(js|css)$'),// 只处理大于此大小的文件threshold: 10240,// 最小压缩比达到 0.8 时才会被压缩minRatio: 0.8,})]}}}...
}
上方我们通过在生产环境中增加 Gzip 压缩配置实现了打包后输出增加对应的 .gz 为后缀的文件,而由于我们配置项中配置的是只压缩大小超过 10240B(10kB)的 JS 及 CSS,因此不满足条件的文件不会进行 Gzip 压缩。
Gzip 压缩能在普通压缩的基础上再进行 50% 以上 的压缩,我们可以直接来看下控制台的输出对比图:
很明显,Gzip 压缩后的文件体积得到了很大程度的减小,这对于浏览器资源加载速度的提升起到了非常有效的帮助。但是需要注意的是访问 Gzip 压缩的文件需要服务端进行相应配置,以下是 Nginx Gzip 压缩的流程:
Nginx 开启 Gzip 压缩配置后,其会根据配置情况对指定的类型文件进行压缩,主要针对 JS 与 CSS 。如果文件路径中存在与原文件同名(加了个 .gz),Nginx 会获取 gz 文件,如果找不到,会主动进行 Gzip 压缩。
拓展3
除了本文中介绍的项目优化方法,还有哪些常见的优化手段?如何通过 Vue CLI 3 配置实现?
以下为我总结的一些常见的优化方法以及如何通过 Vue CLI 3 进行配置的示例:
1. 代码分割(Code Splitting)
目的:通过将应用程序的代码分成较小的块(chunk),实现按需加载,从而减少初始加载时间。
实现方法:
- Vue CLI 默认使用 Webpack,支持基于路由的代码分割。通过动态导入组件实现代码分割。
示例:
const Home = () => import('./views/Home.vue');
const About = () => import('./views/About.vue');
2. 懒加载(Lazy Loading)
目的:只在需要时加载某些组件或库,可以减少首次加载的内容
实现方法:
- 使用 Vue Router 的懒加载特性来实现路由组件的懒加载
示例:
javascript
const routes = [{path: '/home',component: () => import('./views/Home.vue')},{path: '/about',component: () => import('./views/About.vue')}
];
3. 生产模式下的性能优化
目的:确保在生产环境中应用最佳性能优化
实现方法:
- 确保在生产环境下构建时启用 Vue 的生产提示
在 vue.config.js
中:
module.exports = {productionSourceMap: false, // 不生成 source mapsconfigureWebpack: {optimization: {splitChunks: {chunks: 'all', // 对所有模块进行代码分割}}}
};
4. 图片优化
目的:减小图片的体积以加快页面加载
实现方法:
- 使用图像压缩工具(如
imagemin
)在构建过程中优化图像
示例:
npm install imagemin-webpack-plugin --save-dev
在 vue.config.js
中:
const ImageminPlugin = require('imagemin-webpack-plugin').default;module.exports = {configureWebpack: {plugins: [new ImageminPlugin({test: /\.(jpe?g|png|gif|svg)$/i,pngquant: {quality: '95-100'}})]}
};
5. 使用 PWA(渐进式 Web 应用)
目的:通过增强用户体验,提供离线支持、快速加载速度等
实现方法:
- 使用 Vue CLI 的 PWA 插件
安装 PWA 插件:
vue add pwa
这将自动配置 vue.config.js
和其他必要的文件
6. HTTP/2 支持
目的:利用 HTTP/2 的多路复用特性,提高文件传输速度
实现方法:
- 确保你的服务器支持 HTTP/2,并配置相应的 SSL/TLS
7. 使用 CDN
目的:将静态资源托管在 CDN 上,加快加载速度
实现方法:
- 在
vue.config.js
中配置公共路径
module.exports = {publicPath: process.env.NODE_ENV === 'production' ? 'https://cdn.example.com/' : '/'
};
8. 监控性能
目的:通过监控应用性能,找出瓶颈并进行优化
实现方法:
- 使用工具如 Google Lighthouse、Webpack Bundle Analyzer 等
安装 webpack-bundle-analyzer
:
npm install --save-dev webpack-bundle-analyzer
在 vue.config.js
中配置:
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;module.exports = {configureWebpack: {plugins: [new BundleAnalyzerPlugin()]}
};
9. 使用 Tree Shaking
目的:去除未使用的代码以减小最终打包体积
实现方法:
- 确保在项目中使用 ES6 的模块导入语法,Webpack 会自动对未使用的代码进行剔除
10. 预加载和预获取
目的:提高资源的获取速度
实现方法:
在 vue.config.js
中配置 html-webpack-plugin
:
const HtmlWebpackPlugin = require('html-webpack-plugin');module.exports = {configureWebpack: {plugins: [new HtmlWebpackPlugin({// 其他选项preload: ['app.js'], // 预加载prefetch: ['vendor.js'] // 预获取})]}
};
相关文章:
Vue项目整合与优化
前几篇文章,我们讲述了 Vue 项目构建的整体流程,从无到有的实现了单页和多页应用的功能配置,但在实现的过程中不乏一些可以整合的功能点及可行性的优化方案,就像大楼造完需要进行最后的项目验收改进一样,有待我们进一步…...
MyBatis 与 MyBatis-Plus 的区别
MyBatis 和 MyBatis-Plus 都是用于简化 Java 应用程序与数据库交互的持久层框架,但它们在功能、易用性和性能优化方面存在显著差异。下面将详细介绍两者之间的区别,并通过具体的代码示例进行对比。 概述 MyBatis:作为一款经典的持久层框架&a…...
如何让大模型不再“已读乱回”——RAG技术助力生成更精确的答案
随着大语言模型(LLM) 的迅猛发展,越来越多的领域开始受益于其强大的自然语言处理能力。从写作到编程,LLM已成为我们日常生活和工作的得力助手。然而,这些看似无所不能的大模型,却有一个致命的弱点ÿ…...
Anaconda环境配置(Windows11+python3.9)
文章目录 一、 下载ANACONDA(1)点击**Free Download**。(2)点击“skip registration”,跳过登录。(3)下载对应操作系统的ANACONDA版本。 二、 安装ANACONDA(1)双击运行安…...
Spring Boot 中的虚拟线程
什么是虚拟线程? 虚拟线程(Virtual Threads)是 Java 19 引入的一项新特性,它属于 Project Loom 项目的一部分。与传统的线程(平台线程)不同,虚拟线程并不是由操作系统直接管理,而是…...
el-table 实现纵向多级表头
为了实现上图效果,最开始打算用el-row、el-col去实现,但发现把表头和数据分成两大列时,数据太多时会导致所在格高度变高。但由于每一格数据肯定不一样,为保持高度样式一致,就需要我们手动去获取最高格的高度之后再设置…...
探秘Kafka源码:关键内容解析
文章目录 一、以kafka-3.0.0为例1.1安装 gradle 二、生产者源码2.1源码主流程图2.2 初始化2.3生产者sender线程初始化2.4 程序入口2.5生产者 main 线程初始化2.6 跳转到 KafkaProducer构造方法 一、以kafka-3.0.0为例 打开 IDEA,点击 File->Open…->源码包解…...
Promise编码小挑战
题目 我们将实现一个 createImage 函数,该函数返回一个 Promise,用于处理图片加载的异步操作。此外,还会实现暂停执行的 wait 函数。 Part 1: createImage 函数 该函数会: 创建一个新的图片元素。将图片的 src 设置为提供的路径…...
PyQt实战——将pcm文本数据转换成.pcm的二进制文件
系类往期文章: PyQt5实战——多脚本集合包,前言与环境配置(一) PyQt5实战——多脚本集合包,UI以及工程布局(二) PyQt5实战——多脚本集合包,程序入口QMainWindow(三&…...
数据结构之线性表
1.什么是线性表 线性表的概念 定义:线性表是由n个数据元素组成的有限序列。每个数据元素(除了第一个和最后一个)都有且仅有一个前驱和一个后继。逻辑结构:线性表的逻辑结构可以用一个序列来表示,例如 L(a1,a2,…,an)。…...
量子行走的干涉性和叠加性
需要注意公式的一些特殊情况,举例,当dj2和dj3 dj2 dj3...
Fabric环境部署-安装Go
安装go语言环境 国内镜像:Go下载 - Go语言中文网 - Golang中文社区 1.选择版本下载后解压:注意go1.11.linux-amd64.tar.gz换成你下的 sudo tar zxvf go1.21.linux-amd64.tar.gz -C /usr/local 2.. 创建Go目录 mkdir $HOME/go 3. 用vi打开~./bashrc&…...
网站设计总结后期维护与更新的重要性
当我们谈论网站设计时,往往会聚焦在初始阶段的创意和实现上。然而,一旦网站建成并上线,后期维护与更新的重要性就显得尤为突出。一个网站的成功不仅取决于其初始设计,更在于持续的维护与更新。 首先,后期维护能够确保网…...
『SQLite』详解运算符
内容摘要:本节讲解运算符,包括:算术运算符、比较运算符、逻辑运算符和位运算符。 什么是运算符? 运算符是一个保留字或字符,主要用于 SQLite 语句的 WHERE 子句中执行操作。它用于指定 SQLite 语句中的条件࿰…...
计算机网络--根据IP地址和路由表计算下一跳
一、必备知识 1.无分类地址IPV4地址网络前缀主机号 2.每个IPV4地址由32位二进制数组成 3. /15这个地址表示网络前缀有15位,那么主机号32-1517位。 4.地址掩码(子网掩码):所对应的网络前缀为1,主机号为0。 5.计算下…...
如何使用 Ansys OptiSlang 同时运行多个参数化设计研究
了解如何通过使用 OptiSLang 同时运行多个参数化设计研究来提高工作效率。 了解参数化设计研究的重要性 参数化设计研究在工程和设计过程中起着至关重要的作用。通过改变输入参数,工程师可以探索不同设计选择的效果,并优化其设计以满足性能、成本或其他…...
《 拼数 》
题目描述 设有 nn 个正整数 a1…ana1…an,将它们联接成一排,相邻数字首尾相接,组成一个最大的整数。 输入格式 第一行有一个整数,表示数字个数 nn。 第二行有 nn 个整数,表示给出的 nn 个整数 aiai。 输出格…...
Memcached CAS 命令
Memcached CAS(Check-And-Set 或 Compare-And-Swap) 命令用于执行一个"检查并设置"的操作 它仅在当前客户端最后一次取值后,该key 对应的值没有被其他客户端修改的情况下, 才能够将值写入。 检查是通过cas_token参数进…...
ElasticSearch基础-文章目录
ElasticSearch学习总结1(环境安装) ElasticSearch学习总结2(基础查询) ElasticSearch学习总结3(.NetCore操作ES) ElasticSearch学习总结4(sql操作ES) ElasticSearch学习总结5&am…...
后台管理系统动态面包屑Breadcrumb组件的实现
在后管理系统开发中,面包屑导航是一个非常常见的功能,通常是根据当前的 url 自动生成面包屑导航菜单,当跳转路由发生变化时,面包屑导航都会随之发生变化,即动态面包屑。 要完成动态面包屑我们需要制作一个动态数组&am…...
java项目之校园管理系统的设计与实现(源码+文档)
风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于springboot的校园管理系统的设计与实现。项目源码以及部署相关请联系风歌,文末附上联系信息 。 项目简介: springboot校园…...
浅谈棋牌游戏开发流程八:运维与数据分析
一、前言:为什么“云端运维”和“数据分析”如此重要? 在前面几篇文章中,我们已经从客户端、后端架构、用户系统、房间匹配与对局流程、数据库设计与优化、支付与充值、安全与反外挂等角度,系统性地搭建了一个棋牌游戏的基本框架…...
uniapp:微信小程序文本长按无法出现复制菜单
一、问题描述 在集成腾讯TUI后,为了能让聊天文本可以复制,对消息组件的样式进行修改,主要是移除下面的user-select属性限制: user-select: none;-webkit-user-select: none;-khtml-user-select: none;-moz-user-select: none;-ms…...
跨物种筛选同源基因
工具:R:biomaRt 原始文件:human、mouse、macaque、marmoset四个物种的gene list,有些是用ensembl ID,有的是用gene name来表示。 目的:找到四个物种的gene list之间的1v1同源基因 1. 找到物种间的1v1同源…...
大模型数据采集和预处理:把所有数据格式,word、excel、ppt、jpg、pdf、表格等转为数据
大模型数据采集和预处理:把所有数据格式,word、excel、ppt、jpg、pdf、表格等转为数据 文本/图片/表格,分别提取处理工具选择不同格式文件,使用不同工具处理1. 确认目标2. 分析过程(目标-手段分析法)3. 实现步骤4. 代码封装效果展…...
k8s修改存储目录-介绍
k8s修改存储目录-介绍 文章目录 k8s修改存储目录-介绍总结:介绍指定 Docker 或 containerd 镜像和容器存储目录Docker 存储目录containerd 存储目录 指定 Kubelet 的存储目录指定 Pod 和容器存储目录 docker 运行时,迁移目录实操:https://blo…...
【电源专题】为什么测试电源的SW波形上冲振荡之前的0V电位要先来个小的下降
在同步电源的开关节点SW波形测试中,你可能会发现周期性的SW波形在上升前的一小段时间时间内会有一个小小的下跌,这个下跌会低于0V。那么这个下跌是怎么来的呢? 如下所示为某降压转换器的SW开关节点波形: 其展开后可以看到在上升之前有20ns左右的时间,SW电压是下跌…...
常见的反规范化技术
在数据库设计中,数据规范化和反规范化是两种重要的策略,它们在一定程度上存在权衡。规范化通过组织表结构,减少数据冗余,提高数据一致性和降低更新异常,使数据存储更加高效、可靠。然而,过度的规范化会导致…...
Linux中隐藏操作身法
从历史记录中删除指定的命令 假设历史记录中已经包含了一些你不希望记录的命令。这种情况下我们怎么办?很简单。通过下面的命令来删除: history | grep "keyword"例如:history | grep set o history 批量第二条和第四条删除: sed…...
Transformer知识梳理
Transformer知识梳理 文章目录 Transformer知识梳理什么是Transformer?语言模型迁移学习 Transformer结构注意力层原始结构 总结 什么是Transformer? 语言模型 Transformer模型本质上都是预训练语言模型,大部分采用自监督学习(S…...
Nexus Message Transaction Services(MTS)
Nexus 系列交换机遇到以下情形时,可以尝试查看是否是 MTS 消息卡在缓冲区过多,因为 MTS 负责处理模块内以及跨模块(包括跨管理引擎)的各服务之间的消息路由和排队。 • CPU 高 • 命令行无响应、响应慢 • 控制平面中断 • 流量问…...
网络编程基础:连接Java的秘密网络
1 网络编程的重要性 网络编程允许Java应用程序与其他计算机或设备进行通信。这包括从简单的数据传输到复杂的分布式系统和Web服务。 2 Java网络编程的核心类 Java提供了多个类来支持网络编程: InetAddress:表示网络上的IP地址。 URL:表示统…...
uniapp中判断设备类型
全局变量: 在 UniApp 中,你可以通过 uni.getDeviceInfo 获取设备信息,并将设备类型全局存放。通常,这些信息可以存放在 app.vue 的全局变量中,以便在整个应用中访问。 以下是如何在 app.vue 中实现这一功能的完整代码…...
数据可视化分析详解
数据可视化分析是一种通过图形、表格、图标和其他视觉元素来呈现数据的方式,使得数据更易于理解和分析。以下是关于数据可视化分析的一些关键点: 一、定义与目的 数据可视化分析是指利用图形化手段,清晰地有效地传达与沟通信息。它将数据以…...
_使用CLion的Vcpkg安装SDL2,添加至CMakelists时报错,编译报错
语言:C20 编译器:gcc 14.2 摘要:初次使用Vcpkg添加SDL2,出现CMakelists找不到错误、编译缺失main错误、运行失败错误。 CMakelists缺失错误: 使用CLion的Vcpkg安装SDL2时,按照指示把对应代码添加至CMakel…...
QT中Qstring和QByteArray有什么区别?
数据存储内容方面 QString: 主要用于存储和处理Unicode编码的文本字符串。它能够很好地处理包含各种语言字符的文本信息,如中文、日文、韩文等多种语言文字。例如,QString str "你好,世界!";可以方便地存储…...
Viggle AI:支持小孩或者卡通人物吗? [Viggle AI实战教程] – 第2篇
历史文章 Suno AI API接入 - 将AI音乐接入到自己的产品中,支持120并发任务 万物皆能舞,AI让你秒变“舞”林高手 – Viggle AI“舞”所不能 Viggle AI:打造爆款 AI 视频,让照片 “踢” 起足球 Viggle AI:开启3D动画…...
庐山派K230学习日记4 PWM控制
1 本节介绍 📝本节您将学习如何通过将K230开发板的GPIO引脚复用为PWM功能并输出PWM信号;实现输出PWM信号及控制板载无源蜂鸣器发出声音。 🏆学习目标 1️⃣如何将GPIO引脚配置为PWM模式,通过40Pin排针中的部分引脚来输出PWM信号…...
Android配件应用默认启动与USB权限申请区别
使用效果: USB配件授权演示 选择USB配件默认打开应用 申请USB配件使用权限...
【车载开发系列】GPIO模式分类
【车载开发系列】GPIO模式分类 这里写目录标题 【车载开发系列】GPIO模式分类一. GPIO概念二. GPIO的模式区分三. GPIO的八大模式1)推挽输出(Output push-pull)2)开漏输出(Output open-drain)3)…...
uniapp--HBuilder开发
提示:本文为学习内容,若有错误,请联系作者,谦虚受教。 文章目录 前言一、下载HBuilder二、添加modbus相关库1.下载nodejs2.下载modbus库3.项目添加modbus库 三、HBuilder相关功能语句1.文件夹说明2.消息信息框3.开关按钮4.选中按钮…...
学习笔记|arduino uno r3|点亮|hello world|Atmega328P|开发板学习:概述
目录 arduino uno r3开发板学习开发板概述重要引脚介绍配置开发环境安装 Arduino IDE 编程环境介绍Arduino 介绍 实操连接选择程序程序代码编译和执行 总结课后练习 arduino uno r3开发板学习 开发板概述 Arduino UNO 是一款基于Atmega328P 的微控制器开发板。它有 14 个数字…...
Go语言的 的注解(Annotations)核心知识
Go语言的注解(Annotations)核心知识 Go语言是一种简洁且高效的编程语言,广泛应用于后端开发、云计算和微服务架构。在探索Go语言的特性时,我们不可忽视一个重要的概念:注解(Annotations)。虽然…...
WinRAR中“自动加密”如何使用?
WinRAR加密大家都不陌生,那么自动加密功能大家熟悉嘛?如何使用自动加密功能?今天介绍详细教程给大家。 打开WinRAR软件之后选择工具栏中的【选项】,点击设置 然后切换到【压缩】选项卡,点击【创建默认配置】ÿ…...
`http_port_t
http_port_t 是 SELinux(Security-Enhanced Linux)中的一种端口类型标签,用于标识哪些端口可以被 HTTP 和 HTTPS 服务使用。SELinux 是一种强制访问控制(MAC)安全模块,它通过定义安全策略来限制进程对系统资…...
C++编程等级认证学习计划
C编程等级认证学习计划 计划目标 在30天内系统学习并掌握C编程等级认证(一至八级)的知识点,为参加认证考试做好充分准备。 前期准备 学习资料收集 准备涵盖C编程一至八级知识点的专业教材,如《C Primer》等。收集相关的在线教…...
c和c++中为什么要防止头文件被重复包含!
在编程中,头文件就像一本工具书,它包含了函数、类、宏、全局变量等的定义和声明,供其他代码文件引用。想象一下,如果你在写一篇文章时,反复引用同一本工具书的内容,会发生什么情况呢? 1. 避免重…...
安的厦小程序开发日志
目录 背景名字由来架构文件目录app.jsonapp.wxsspackage.jsonproject.config.jsindex.wxmlindex.wxssindex.jsindex.jsondetail.wxmldetail.wxssdetail.jsdetail.json参考资料背景 我们正在经历一场价值观的变迁,过去的丈母娘和女朋友总是要求男方要买房,那是因为房子是当下…...
深度评测uni-app x:开启跨平台开发新篇章
文章目录 一、引言1.1 跨平台开发的崛起1.2 uni-app x 初印象 二、uni-app x 核心特性评测2.1 uts 语言:跨平台编程新利器2.2 uvue 渲染引擎:原生渲染新体验2.3 强大的组件和 API 支持2.4 插件生态:拓展无限可能 三、与 uni-app 对比…...
第06章 重定向与管道
一、概述 在企业生产环境中,如何记录一个程序运行的过程记录或者定时任务执行的结果呢?假设定时任务凌晨执行,我们在白天上班时需要查看执行是否成功要怎么办?就可以使用本章介绍的重定向和管道符号。 二、重定向 2.1 文件描述…...