vue-loader
- Vue Loader 是一个 webpack 的 loader,它允许你以一种名为单文件组件 (SFCs)的格式撰写 Vue 组件
起步
安装
npm install vue --save
npm install webpack webpack-cli style-loader css-loader html-webpack-plugin vue-loader vue-template-compiler webpack-dev-server --save-dev
webpack.config.js
webpack.config.js
const { VueLoaderPlugin } = require('vue-loader')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')
module.exports = {mode: 'development',devtool: false,entry: './src/main.js',module: {rules: [{test: /\.vue$/,loader: 'vue-loader'}]},plugins: [new VueLoaderPlugin(),new HtmlWebpackPlugin({template: './src/index.html'}),new webpack.DefinePlugin({__VUE_OPTIONS_API__: true,__VUE_PROD_DEVTOOLS__: true})]
}
main.js
src\main.js
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
App.vue
src\App.vue
<script>
console.log('App');
</script>
index.html
src\index.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>vue-loader</title>
</head>
<body><div id="app"></div>
</body>
</html>
loader实现
文件结构
- vue-loader内部主要有三个部分
vue-loader\index.js实现了一个普通Loader,负责把SFC的不同区块转化为import语句vue-loader\pitcher.js实现pitch Loader,用于拼出完整的行内路径vue-loader\plugin.js负责动态修改webpack配置,注入新的loader到rules规则中
基础知识
LoaderContext
- Loader Context 表示在 loader 内使用 this 可以访问的一些方法或属性
- this.callback可以同步或者异步调用的并返回多个结果的函数
pitching-loader
- pitching-loaderloader 总是 从右到左被调用。在实际(从右到左)执行 loader 之前,会先 从左到右 调用
loader上的pitch方法 - loader 可以通过 request 添加或者禁用内联前缀,这将影响到 pitch 和执行的顺序,请看Rule.enforce
Rule.enforce
- Rule.enforce可以用于指定
loader种类
resource
- Rule.resource会匹配 resource
- Rule.resourceQuery会匹配资源查询
contextify
- contextify返回一个新的请求字符串,尽可能避免使用绝对路径,将请求转换为可在内部使用
require或import在避免绝对路径时使用的字符串
@vue/compiler-sfc
- compiler-sfc用于编译Vue单文件组件的低级实用程序
// main script
import script from '/project/foo.vue?vue&type=script'
// template compiled to render function
import { render } from '/project/foo.vue?vue&type=template&id=xxxxxx'
// css
import '/project/foo.vue?vue&type=style&index=0&id=xxxxxx'
// attach render function to script
script.render = render
// attach additional metadata
script.__file = 'example.vue'
script.__scopeId = 'hash'
export default script
工作流程

原始内容
import App from './App.vue'
第1次转换
-
1.进入vue-loader的normal处理转换代码为
import script from "./App.vue?vue&type=script&id=4d69bc76&lang=js" import {render} from "./App.vue?vue&type=template&id=4d69bc76&scoped=true&lang=js" import "./App.vue?vue&type=style&index=0&id=4d69bc76&scoped=true&lang=css" script.__scopeId = "data-v-4d69bc76" script.render=render export default script
第2次转换
- 2.进入pitcher,不同区块返回不同内容
//script区块
export { default } from "-!../vue-loader/index.js!./App.vue?vue&type=script&id=4d69bc76&lang=js"; export * from "-!../vue-loader/index.js!./App.vue?vue&type=script&id=4d69bc76&lang=js"
//template区块
export * from "-!../vue-loader/templateLoader.js!../vue-loader/index.js!./App.vue?vue&type=template&id=4d69bc76&scoped=true&lang=js"
//style区块
export * from "-!../node_modules/style-loader/dist/cjs.js!../node_modules/css-loader/dist/cjs.js!../vue-loader/stylePostLoader.js!../vue-loader/index.js!./App.vue?vue&type=style&index=0&id=4d69bc76&scoped=true&lang=css"
第3次转换
- 第二次执行
vue-loader,从SFC中提取对应的区块内容,交给后面的loader script内容直接编译返回template内容交给templateLoaderstyle内容交给stylePostLoader
vue-loader\index.js
if (incomingQuery.get('type')) {return select.selectBlock(descriptor, id, loaderContext, incomingQuery);
}
编译script
- 第一次的时候只走
vue-loader,返回临时文件import script from "./App.vue?vue&type=script&id=4d69bc76&lang=js" - 第一次加载临时文件的时候会走
pitcher,pitcher会拼出行内loader和加载模块的完整路径
webpack.config.js
webpack.config.js
+const { VueLoaderPlugin } = require('./vue-loader')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')
+const path = require('path')
module.exports = {mode: 'development',devtool: false,entry: './src/main.js',module: {rules: [{test: /\.vue$/,
+ loader: path.resolve(__dirname, 'vue-loader')}]},plugins: [new VueLoaderPlugin(),new HtmlWebpackPlugin({template: './src/index.html'}),new webpack.DefinePlugin({__VUE_OPTIONS_API__: true,__VUE_PROD_DEVTOOLS__: true})]
}
vue-loader\index.js
vue-loader\index.js
const compiler = require("vue/compiler-sfc");
const hash = require("hash-sum");
const VueLoaderPlugin = require("./plugin");
const select = require("./select");
function loader(source) {const loaderContext = this;const { resourcePath, resourceQuery = '' } = loaderContext;const rawQuery = resourceQuery.slice(1);const incomingQuery = new URLSearchParams(rawQuery);const { descriptor } = compiler.parse(source);const id = hash(resourcePath);if (incomingQuery.get('type')) {return select.selectBlock(descriptor, id, loaderContext, incomingQuery);}const code = [];const { script } = descriptor;if (script) {const query = `?vue&type=script&id=${id}&lang=js`;const scriptRequest = JSON.stringify(loaderContext.utils.contextify(loaderContext.context, resourcePath + query));code.push(`import script from ${scriptRequest}`);}code.push(`export default script`);return code.join('\n');
}
loader.VueLoaderPlugin = VueLoaderPlugin;
module.exports = loader;
plugin.js
vue-loader\plugin.js
class VueLoaderPlugin {apply(compiler) {const rules = compiler.options.module.rules;const pitcher = {loader: require.resolve('./pitcher'),//类似于test,用于判断资源的路径是否适用于此规则resourceQuery: query => {if (!query) {return false;}let parsed = new URLSearchParams(query.slice(1));return parsed.get('vue') !== null;}};//把pitcher添加到rules数组的第一位compiler.options.module.rules = [pitcher, ...rules];}
}
module.exports = VueLoaderPlugin;
pitcher.js
vue-loader\pitcher.js
const pitcher = code => code;
const isNotPitcher = loader => loader.path !== __filename;
const pitch = function () {const context = this;const loaders = context.loaders.filter(isNotPitcher);const query = new URLSearchParams(context.resourceQuery.slice(1));return genProxyModule(loaders, context, query.get('type') !== 'template');
}
function genProxyModule(loaders, context, exportDefault = true) {const request = genRequest(loaders, context);return (exportDefault ? `export { default } from ${request}; ` : ``) + `export * from ${request}`;
}
function genRequest(loaders, context) {const loaderStrings = loaders.map(loader => loader.request);const resource = context.resourcePath + context.resourceQuery;return JSON.stringify(context.utils.contextify(context.context, '-!' + [...loaderStrings, resource].join('!')));
}
pitcher.pitch = pitch;
module.exports = pitcher;
select.js
vue-loader\select.js
const compiler_sfc = require("vue/compiler-sfc");
function selectBlock(descriptor, scopeId, loaderContext, query) {if (query.get('type') === `script`) {const script = compiler_sfc.compileScript(descriptor, { id: scopeId });loaderContext.callback(null, script.content);return;}
}
exports.selectBlock = selectBlock;
编译template
src\App.vue
src\App.vue
<template><h1>hello</h1>
</template>
<script>
console.log('App');
</script>
vue-loader\index.js
vue-loader\index.js
const compiler = require("vue/compiler-sfc");
const hash = require("hash-sum");
const VueLoaderPlugin = require("./plugin");
const select = require("./select");
function loader(source) {const loaderContext = this;const { resourcePath, resourceQuery = '' } = loaderContext;const rawQuery = resourceQuery.slice(1);const incomingQuery = new URLSearchParams(rawQuery);const { descriptor } = compiler.parse(source);const id = hash(resourcePath);if (incomingQuery.get('type')) {return select.selectBlock(descriptor, id, loaderContext, incomingQuery);}const code = [];const { script } = descriptor;if (script) {const query = `?vue&type=script&id=${id}&lang=js`;const scriptRequest = JSON.stringify(loaderContext.utils.contextify(loaderContext.context, resourcePath + query));console.log(scriptRequest);code.push(`import script from ${scriptRequest}`);}
+ if (descriptor.template) {
+ const query = `?vue&type=template&id=${id}&lang=js`;
+ const templateRequest = JSON.stringify(loaderContext.utils.contextify(loaderContext.context, resourcePath + query));
+ code.push(`import {render} from ${templateRequest}`);
+ }
+ code.push(`script.render=render`);code.push(`export default script`);return code.join('\n');
}
loader.VueLoaderPlugin = VueLoaderPlugin;
module.exports = loader;
plugin.js
vue-loader\plugin.js
class VueLoaderPlugin {apply(compiler) {const rules = compiler.options.module.rules;const pitcher = {loader: require.resolve('./pitcher'),resourceQuery: query => {if (!query) {return false;}let parsed = new URLSearchParams(query.slice(1));return parsed.get('vue') !== null;}};
+ const templateCompilerRule = {
+ loader: require.resolve('./templateLoader'),
+ resourceQuery: query => {
+ if (!query) {
+ return false;
+ }
+ const parsed = new URLSearchParams(query.slice(1));
+ return parsed.get('vue') != null && parsed.get('type') === 'template';
+ }
+ };
+ compiler.options.module.rules = [pitcher, templateCompilerRule, ...rules];}
}
module.exports = VueLoaderPlugin;
select.js
vue-loader\select.js
const compiler_sfc = require("vue/compiler-sfc");
function selectBlock(descriptor, scopeId, loaderContext, query) {if (query.get('type') === `script`) {const script = compiler_sfc.compileScript(descriptor, { id: scopeId });loaderContext.callback(null, script.content);return;}
+ if (query.get('type') === `template`) {
+ const template = descriptor.template;
+ loaderContext.callback(null, template.content);
+ return;
+ }
}
exports.selectBlock = selectBlock;
templateLoader.js
vue-loader\templateLoader.js
const compiler_sfc = require("vue/compiler-sfc");
const TemplateLoader = function (source) {const loaderContext = this;const query = new URLSearchParams(loaderContext.resourceQuery.slice(1));const scopeId = query.get('id');const { code } = compiler_sfc.compileTemplate({source,id: scopeId});loaderContext.callback(null, code);
}
module.exports = TemplateLoader;
编译style
webpack.config.js
webpack.config.js
const { VueLoaderPlugin } = require('./vue-loader')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const webpack = require('webpack')
const path = require('path')
module.exports = {mode: 'development',devtool: false,entry: './src/main.js',module: {rules: [{test: /\.vue$/,loader: path.resolve(__dirname, 'vue-loader')},
+ {
+ test: /\.css$/,
+ use: [
+ 'style-loader',
+ 'css-loader'
+ ]
+ }]},plugins: [new VueLoaderPlugin(),new HtmlWebpackPlugin({template: './src/index.html'}),new webpack.DefinePlugin({__VUE_OPTIONS_API__: true,__VUE_PROD_DEVTOOLS__: true})]
}
App.vue
src\App.vue
<template>
+ <h1 class="title">hello</h1>
</template>
<script>
console.log('App');
</script>
+<style>
+.title {
+ color: red;
+}
+</style>
vue-loader\index.js
vue-loader\index.js
const compiler = require("vue/compiler-sfc");
const hash = require("hash-sum");
const VueLoaderPlugin = require("./plugin");
const select = require("./select");
function loader(source) {const loaderContext = this;const { resourcePath, resourceQuery = '' } = loaderContext;const rawQuery = resourceQuery.slice(1);const incomingQuery = new URLSearchParams(rawQuery);const { descriptor } = compiler.parse(source);const id = hash(resourcePath);if (incomingQuery.get('type')) {return select.selectBlock(descriptor, id, loaderContext, incomingQuery);}const code = [];const { script } = descriptor;if (script) {const query = `?vue&type=script&id=${id}&lang=js`;const scriptRequest = JSON.stringify(loaderContext.utils.contextify(loaderContext.context, resourcePath + query));console.log(scriptRequest);code.push(`import script from ${scriptRequest}`);}if (descriptor.template) {const query = `?vue&type=template&id=${id}&lang=js`;const templateRequest = JSON.stringify(loaderContext.utils.contextify(loaderContext.context, resourcePath + query));code.push(`import {render} from ${templateRequest}`);}
+ if (descriptor.styles.length) {
+ descriptor.styles.forEach((style, i) => {
+ const query = `?vue&type=style&index=${i}&id=${id}&lang=css`;
+ const styleRequest = JSON.stringify(loaderContext.utils.contextify(loaderContext.context, resourcePath + query));
+ code.push(`import ${styleRequest}`);
+ })
+ }code.push(`script.render=render`);code.push(`export default script`);return code.join('\n');
}
loader.VueLoaderPlugin = VueLoaderPlugin;
module.exports = loader;
plugin.js
vue-loader\plugin.js
+const langBlockRuleResource = (query, resource) => `${resource}.${query.get('lang')}`;
class VueLoaderPlugin {apply(compiler) {const rules = compiler.options.module.rules;const pitcher = {loader: require.resolve('./pitcher'),resourceQuery: query => {if (!query) {return false;}let parsed = new URLSearchParams(query.slice(1));return parsed.get('vue') !== null;}};
+ const vueRule = rules.find(rule => 'foo.vue'.match(rule.test));
+ const clonedRules = rules.filter(rule => rule !== vueRule)
+ .map(rule => cloneRule(rule, langBlockRuleResource));const templateCompilerRule = {loader: require.resolve('./templateLoader'),resourceQuery: query => {if (!query) {return false;}const parsed = new URLSearchParams(query.slice(1));return parsed.get('vue') != null && parsed.get('type') === 'template';}};
+ compiler.options.module.rules = [pitcher, templateCompilerRule, ...clonedRules, ...rules];}
}
+function cloneRule(rule, ruleResource) {
+ let currentResource;
+ const res = Object.assign(Object.assign({}, rule), {
+ resource: resources => {
+ currentResource = resources;
+ return true;
+ },
+ resourceQuery: query => {
+ if (!query) {
+ return false;
+ }
+ const parsed = new URLSearchParams(query.slice(1));
+ if (parsed.get('vue') === null) {
+ return false;
+ }
+ //取出路径中的lang参数,生成一个虚拟路径,传入规则中判断是否满足
+ //通过这种方式,vue-loader可以为不同的区块匹配rule规则
+ const fakeResourcePath = ruleResource(parsed, currentResource);
+ if (!fakeResourcePath.match(rule.test)) {
+ return false;
+ }
+ return true;
+ }
+ });
+ delete res.test;
+ return res;
+}
module.exports = VueLoaderPlugin;
select.js
vue-loader\select.js
const compiler_sfc = require("vue/compiler-sfc");
function selectBlock(descriptor, scopeId, loaderContext, query) {if (query.get('type') === `script`) {const script = compiler_sfc.compileScript(descriptor, { id: scopeId });loaderContext.callback(null, script.content);return;}if (query.get('type') === `template`) {const template = descriptor.template;loaderContext.callback(null, template.content);return;}
+ if (query.get('type') === `style` && query.get('index') != null) {
+ const style = descriptor.styles[Number(query.get('index'))];
+ loaderContext.callback(null, style.content);
+ return;
+ }
}
exports.selectBlock = selectBlock;
Scoped CSS
- 当
style标签有scoped属性时,它的 CSS 只作用于当前组件中的元素
App.vue
src\App.vue
<template><h1 class="title">hello</h1>
</template>
<script>
console.log('App');
</script>
+<style scoped>
+.title {
+ color: red;
+}
+</style>
vue-loader\index.js
vue-loader\index.js
const compiler = require("vue/compiler-sfc");
const hash = require("hash-sum");
const VueLoaderPlugin = require("./plugin");
const select = require("./select");
function loader(source) {const loaderContext = this;const { resourcePath, resourceQuery = '' } = loaderContext;const rawQuery = resourceQuery.slice(1);const incomingQuery = new URLSearchParams(rawQuery);const { descriptor } = compiler.parse(source);const id = hash(resourcePath);if (incomingQuery.get('type')) {return select.selectBlock(descriptor, id, loaderContext, incomingQuery);}
+ const hasScoped = descriptor.styles.some(s => s.scoped);const code = [];const { script } = descriptor;if (script) {const query = `?vue&type=script&id=${id}&lang=js`;const scriptRequest = JSON.stringify(loaderContext.utils.contextify(loaderContext.context, resourcePath + query));code.push(`import script from ${scriptRequest}`);}if (descriptor.template) {
+ const scopedQuery = hasScoped ? `&scoped=true` : ``;
+ const query = `?vue&type=template&id=${id}${scopedQuery}&lang=js`;const templateRequest = JSON.stringify(loaderContext.utils.contextify(loaderContext.context, resourcePath + query));code.push(`import {render} from ${templateRequest}`);}if (descriptor.styles.length) {descriptor.styles.forEach((style, i) => {
+ const scopedQuery = style.scoped ? `&scoped=true` : ``;
+ const query = `?vue&type=style&index=${i}&id=${id}${scopedQuery}&lang=css`;const styleRequest = JSON.stringify(loaderContext.utils.contextify(loaderContext.context, resourcePath + query));code.push(`import ${styleRequest}`);})}
+ if (hasScoped) {
+ code.push(`script.__scopeId = "data-v-${id}"`);
+ }code.push(`script.render=render`);code.push(`export default script`);return code.join('\n');
}
loader.VueLoaderPlugin = VueLoaderPlugin;
module.exports = loader;
pitcher.js
vue-loader\pitcher.js
+const isCSSLoader = loader => /css-loader/.test(loader.path);
+const stylePostLoaderPath = require.resolve('./stylePostLoader');
const pitcher = code => code;
const isNotPitcher = loader => loader.path !== __filename;
const pitch = function () {const context = this;const loaders = context.loaders.filter(isNotPitcher);const query = new URLSearchParams(context.resourceQuery.slice(1));
+ if (query.get('type') === `style`) {
+ const cssLoaderIndex = loaders.findIndex(isCSSLoader);
+ if (cssLoaderIndex > -1) {
+ const afterLoaders = loaders.slice(0, cssLoaderIndex + 1);
+ const beforeLoaders = loaders.slice(cssLoaderIndex + 1);
+ return genProxyModule([...afterLoaders, stylePostLoaderPath, ...beforeLoaders], context);
+ }
+ }return genProxyModule(loaders, context, query.get('type') !== 'template');
}
function genProxyModule(loaders, context, exportDefault = true) {const request = genRequest(loaders, context);return (exportDefault ? `export { default } from ${request}; ` : ``) + `export * from ${request}`;
}
function genRequest(loaders, context) {
+ const loaderStrings = loaders.map(loader => loader.request || loader);const resource = context.resourcePath + context.resourceQuery;return JSON.stringify(context.utils.contextify(context.context, '-!' + [...loaderStrings, resource].join('!')));
}
pitcher.pitch = pitch;
module.exports = pitcher;
stylePostLoader.js
vue-loader\stylePostLoader.js
const compiler_sfc = require("vue/compiler-sfc");
const StylePostLoader = function (source) {const query = new URLSearchParams(this.resourceQuery.slice(1));const { code } = compiler_sfc.compileStyle({source,id: `data-v-${query.get('id')}`,scoped: !!query.get('scoped')});this.callback(null, code);
};
module.exports = StylePostLoader;
相关文章:
vue-loader
Vue Loader 是一个 webpack 的 loader,它允许你以一种名为单文件组件 (SFCs)的格式撰写 Vue 组件 起步 安装 npm install vue --save npm install webpack webpack-cli style-loader css-loader html-webpack-plugin vue-loader vue-template-compiler webpack…...
IO系列(十) -TCP 滑动窗口原理介绍(上)
一、摘要 之前在上分享网络编程知识文章的时候,有网友写下一条留言:“可以写写一篇关于 TCP 滑动窗口原理的文章吗?”。 当时没有立即回复,经过查询多方资料,发现这个 TCP 真的非常非常的复杂,就像一个清…...
IPython 使用技巧整理
IPython 是一个增强的 Python 交互式 shell,提供了许多实用的功能和特性,使得 Python 编程和数据科学工作变得更加便捷和高效。以下是一些 IPython 的使用技巧整理: 1. 自动补全和查询 Tab 补全:在 IPython 中,你可以…...
Python 引入中文py文件
目录 背景 思路 importlib介绍 使用方法 1.导入内置库 importlib.util 2.创建模块规格对象 spec importlib.util.spec_from_file_location("example_module", "example.py") 3.创建模块对象 module importlib.util.module_from_spec(spec) …...
qt 实现模拟实际物体带速度的移动(水平、垂直、斜角度)——————附带完整代码
文章目录 0 效果1 原理1.1 图片旋转1.2 物体按照现实中的实际距离带真实速度移动 2 完整实现2.1 将车辆按钮封装为一个类:2.2 调用方法 3 完整代码参考 0 效果 实现后的效果如下 可以显示属性(继承自QToolButton): 鼠标悬浮显示文字 按钮…...
驱动开发(三):内核层控制硬件层
驱动开发系列文章: 驱动开发(一):驱动代码的基本框架 驱动开发(二):创建字符设备驱动 驱动开发(三):内核层控制硬件层 ←本文 目录…...
企业邮箱大附件无法上传?无法确认接收状态?这样解决就行
Outlook邮箱作为最常用的邮箱系统,被全世界企业采用作为内部通用沟通方式,但Outlook邮箱却有着明显的使用缺陷,如邮箱大附件上传障碍及附件接收无提示等。 1、企业邮箱大附件无法上传 Outlook企业邮箱大附件的上传上限一般是50M,…...
Kotlin 数据类(Data Class)
Kotlin 数据类(Data Class)是一种特别用于持有数据的类。它们简化了数据类的创建,并提供了一些自动生成的方法。下面详细介绍 Kotlin 数据类的原理和使用方法。 数据类的定义 Kotlin 中的数据类使用 data 关键字定义。例如: da…...
gridview自带编辑功能如何判断用户修改的值的合法性
在使用GridView的编辑功能更新值时,确保输入的值合法性是十分重要的。为了实现这一点,你可以在GridView的RowUpdating事件中加入代码来检查用户输入的值。如果发现输入的值不合法,你可以取消更新操作并向用户显示错误消息。下面是如何实现的步…...
设计模式-结构型-06-桥接模式
1、传统方式解决手机操作问题 现在对不同手机类型的不同品牌实现操作编程(比如:开机、关机、上网,打电话等),如图: UML 类图 问题分析 扩展性问题(类爆炸):如果我们再…...
安泰电压放大器的选型原则是什么
电压放大器是电子电路中常用的一种器件,主要用于放大输入电压信号。在选型电压放大器时,需要考虑以下几个原则。 根据应用需求确定放大倍数。放大倍数是指输出电压与输入电压之间的倍数关系,也称为增益。不同的应用场景对放大倍数的要求不同&…...
方法分享 |公网IP怎么指定非433端口实现https访问
公网IP可以通过指定非443端口实现HTTPS访问。在网络配置中,虽然HTTPS协议默认使用443端口,但没有规定不能在其他端口上实施HTTPS服务。使用非标准端口进行HTTPS通信需要正确配置服务器和SSL证书,并确保客户端能够连接到指定的端口。下面说明如…...
vue实现拖拽元素;vuedraggable拖拽插件
效果图: 中文文档 以下代码可直接复制使用 安装依赖 npm i -S vuedraggable使用 <template><div class"container"><div>使用flex竖轴布局 <br>handle".mover" 可拖拽的class类名 <br>filter".forbid&qu…...
Javascript介绍
Javascript 定义:一门简单的浏览器可解析的语言 作用:与HTML相结合使用,使我们的网页变得更加酷炫 发展史: 1.1992年,Nombase公司开发出来,校验表单,起名c--,后来更名为&#…...
毕业答辩PPT:如何在短时间内高效准备?
提起PPT,大家的第一反应就是痛苦。经常接触PPT的学生党和打工人,光看到这3个字母,就已经开始头痛了: 1、PPT内容框架与文案挑战重重,任务艰巨,耗费大量精力。 2、PPT的排版技能要求高,并非易事…...
树结构与算法-杨辉三角形的两种实现
什么是杨辉三角形 本文旨在讨论普通杨辉三角形的两种实现方式:迭代法和递归法。我们不详细讲解杨辉三角形的数学问题,只研究其代码实现。 杨辉三角形大致如下图: 杨辉三角形的规律 通过对杨辉三角形的图形分析,我们可以看到这几点…...
【机器学习】智能创意工厂:机器学习驱动的AIGC,打造未来内容新生态
🚀时空传送门 🔍机器学习在AIGC中的核心技术📕深度学习🎈生成对抗网络(GANs) 🚀机器学习在AIGC中的具体应用🍀图像生成与编辑⭐文本生成与对话系统🌠音频生成与语音合成 …...
Python - 一个恶意脚本
Python - 恶意脚本 使用此脚本或修改前请注意以下几点: 系统资源:大量模拟键盘和鼠标事件可能会占用大量系统资源,会导致其他应用程序运行缓慢或崩溃。 隐私和安全:如果此脚本在未经用户同意的情况下运行,它可能侵犯…...
SFNC —— 采集控制(四)
系列文章目录 SFNC —— 标准特征命名约定(一) SFNC —— 设备控制(二) SFNC —— 图像格式控制(三) SFNC —— 采集控制(四) 文章目录 系列文章目录5、采集控制(Acquisi…...
AUTOSAR学习
文章目录 前言1. 什么是autosar?1.1 AP(自适应平台autosar)1.2 CP(经典平台autosar)1.3 我的疑问 2. 为什么会有autosar3.autosar的架构3.1 CP的架构3.1.1 应用软件层3.1.2 运行时环境3.1.3 基础软件层 3.2 AP的架构 4. 参考资料 …...
nnUNetV2实战:从零构建医学影像2D分割数据集全流程解析
1. 环境准备与框架安装 第一次接触nnUNetV2时,我被它繁琐的环境依赖搞得焦头烂额。现在回想起来,其实只要掌握几个关键点就能避开大部分坑。建议使用Python 3.9的环境,我实测Python 3.10的兼容性最好。先通过conda创建隔离环境: c…...
Harmonyos应用实例160:数据分析与决策
应用实例十:数据分析与决策 知识点:第二十章《数据的分析》—— 用样本估计总体。 功能:模拟“鱼塘捕鱼”问题。学生先捕捞一部分鱼做标记放回,再随机捕捞抽样,输入抽样中有标记的鱼的数量,应用估算鱼塘总数,体验样本估计总体的统计思想。 @Entry @Component struct …...
LLM之Agent(四十)|AI Agents(九):从单体到多体——构建可协作的智能体网络
1. 从单体到多体:为什么需要智能体协作网络? 想象一下你正在经营一家小型咨询公司。接到客户需求时,你需要同时完成市场调研、数据分析、报告撰写等工作。如果全靠一个人完成,要么质量难以保证,要么效率极其低下。这就…...
新手必看!Qt中误用close()导致的3大内存问题(附正确姿势)
Qt窗口关闭陷阱:从内存泄漏到双重删除的深度避坑指南 刚接触Qt开发的程序员们,常常会被窗口关闭这个看似简单的操作绊倒。你以为调用close()只是让窗口消失?实际上,这背后隐藏着一系列可能引发内存泄漏、程序崩溃的陷阱。本文将带…...
别再手动改配置了!用Nacos动态管理SkyWalking集群,这5个坑我帮你踩过了
从静态配置到动态治理:SkyWalkingNacos配置中心迁移实战避坑指南 在微服务架构盛行的今天,应用性能监控(APM)系统已成为技术团队不可或缺的运维利器。作为Apache顶级项目,SkyWalking凭借其强大的分布式追踪能力和丰富的指标监控功能…...
Qwen3-32B大模型企业级部署案例:基于优化镜像的API服务封装实践
Qwen3-32B大模型企业级部署案例:基于优化镜像的API服务封装实践 1. 企业级部署需求分析 在当今企业智能化转型过程中,大型语言模型的私有化部署需求日益增长。Qwen3-32B作为一款性能优异的中英双语大模型,在企业知识管理、智能客服、内容生…...
Gradle项目Java版本配置全攻略:从传统方法到Toolchain新特性
Gradle项目Java版本配置全攻略:从传统方法到Toolchain新特性 在Java生态中,Gradle作为现代构建工具的代表,其Java版本管理能力直接影响着项目的构建效率和跨环境一致性。随着Gradle 7.0引入的Toolchain特性,开发者现在拥有了更智能…...
天地图JavaScript API实战:多边形面积计算与交互式绘制
1. 天地图JavaScript API基础入门 第一次接触天地图JavaScript API的开发者可能会觉得有点懵,其实它和我们常用的百度地图、高德地图API类似,都是用来在网页上展示地图和实现地理信息功能的工具链。我刚开始用的时候也踩过不少坑,后来发现只要…...
OpenClaw多平台支持:在Linux上对接QwQ-32B模型
OpenClaw多平台支持:在Linux上对接QwQ-32B模型 1. 为什么选择LinuxOpenClawQwQ-32B组合 去年我在尝试自动化办公流程时,偶然发现了OpenClaw这个开源框架。作为一个长期使用Linux系统的开发者,我一直在寻找能够深度集成到本地环境的AI助手方…...
OpenClaw+GLM-4.7-Flash智能家居控制:语音指令转API调用
OpenClawGLM-4.7-Flash智能家居控制:语音指令转API调用 1. 为什么选择这个组合? 去年折腾Home Assistant时,我就被智能家居的"最后一公里"问题困扰——明明设备已经联网,但自然语言交互始终不够流畅。直到发现OpenCla…...
