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返回一个新的请求字符串,尽可能避免使用绝对路径,将请求转换为可在内部使用requireimport在避免绝对路径时使用的字符串

@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

工作流程

img

原始内容

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内容交给templateLoader
  • style内容交给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;

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

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

相关文章

论文阅读Rolling-Unet,卷积结合MLP的图像分割模型

这篇论文提出了一种新的医学图像分割网络Rolling-Unet&#xff0c;目的是在不用Transformer的前提下&#xff0c;能同时有效提取局部特征和长距离依赖性,从而在性能和计算成本之间找到良好的平衡点。 论文地址&#xff1a;https://ojs.aaai.org/index.php/AAAI/article/view/2…

618购物狂欢节有哪些数码好物值得抢购?年终必备神器清单大揭秘!

一年一度的“618年中大促”即将拉开帷幕&#xff0c;大家是否已经挑选好了心仪的宝贝呢&#xff1f;那些平时心仪已久的商品&#xff0c;是否总期待着在价格最优惠时收入囊中&#xff1f;毫无疑问&#xff0c;618就是这样一个绝佳的时机&#xff0c;因为各大电商平台都会纷纷推…

Lecture2——最优化问题建模

一&#xff0c;建模 1&#xff0c;重要性 实际上&#xff0c;我们并没有得到一个数学公式——通常问题是由某个领域的专家口头描述的。能够将问题转换成数学公式非常重要。建模并不是一件容易的事&#xff1a;有时&#xff0c;我们不仅想找到一个公式&#xff0c;还想找到一个…

群晖NAS安装配置Joplin Server用来存储同步Joplin笔记内容

一、Joplin Server简介 1.1、Joplin Server介绍 Joplin支持多种方式进行同步用户的笔记数据&#xff08;如&#xff1a;Joplin自己提供的收费的云服务Joplin Cloud&#xff0c;还有第三方的云盘如Dropbox、OneDrive&#xff0c;还有自建的云盘Nextcloud、或者通过WebDAV协议来…

长沙干洗服务,打造您的专属衣橱

长沙干洗服务&#xff0c;用心呵护您的每一件衣物&#xff01;致力于为您打造专属的衣橱&#xff0c;让您的每一件衣物都焕发出独特的魅力。 我们深知每一件衣物都承载着您的故事和情感&#xff0c;因此我们会以更加细心的态度对待每一件衣物。无论是您心爱的牛仔裤&#xff0c…

sizeof和strlen

1.sizeof和strlen的对比 1.1sizeof sizeof是计算变量所占内存空间大小的&#xff0c;单位是&#xff1a;字节 如果操作数是类型的话&#xff0c;计算的是使用类型创建的变量所占内存空间的大小。 sizeof只关注占用内存空间的大小&#xff0c;不在乎内存中存放的是什么数据 …

QML Canvas 代码演示

一、文字阴影 / 发光 Canvas{id: root; width: 400; height: 400onPaint: //所有的绘制都在onPaint中{var ctx getContext("2d") //获取上下文// 绘制带阴影的文本ctx.fillStyle "#333" //设置填充颜色ctx.fillRect(0, 0, root.width, root.height…

Stability AI发布新版文生图模型:依然开源

Stability AI最近发布了Stable Diffusion 3 Medium&#xff08;简称SD3 Medium&#xff09;&#xff0c;这是其最新的文生图模型&#xff0c;被官方称为“迄今为止最先进的开源模型”。SD3 Medium的性能甚至超过了Midjourney 6&#xff0c;特别是在生成手部和脸部图像方面表现出…

一杯咖啡的艺术 | 如何利用数字孪生技术做出完美的意式浓缩咖啡?

若您对数据分析以及人工智能感兴趣&#xff0c;欢迎与我们一起站在全球视野关注人工智能的发展&#xff0c;与Forrester 、德勤、麦肯锡等全球知名企业共探AI如何加速制造进程&#xff0c; 共同参与6月20日由Altair主办的面向工程师的全球线上人工智能会议“AI for Engineers”…

可以自定义的文字识别OCR

可以自定义的文字识别OCR 什么是OCR文档自学习自定义模板单证票据信息抽取操作体验 这里提到的可以自定义的文字识别OCR &#xff0c;其实就是OCR文档自学习。 什么是OCR文档自学习 什么是OCR文档自学习呢&#xff1f;OCR文档自学习&#xff0c;是面向“无算法基础”的企业与个…

C#——字典diction详情

字典 字典: 包含一个key(键)和这个key所以对应的value&#xff08;值&#xff09;&#xff0c;字典是是无序的&#xff0c;key是唯一的&#xff0c;可以根据key获取值。 定义字典: new Diction<key的类型&#xff0c;value的类型>() 方法 添加 var dic new Dictionar…

OZON芒果店长erp,OZON平台支持什么ERP

在跨境电商的浪潮中&#xff0c;OZON平台凭借其独特的优势&#xff0c;吸引了众多卖家入驻。然而&#xff0c;随着业务规模的不断扩大&#xff0c;如何高效管理商品、处理订单、优化仓储物流等成为了卖家们亟需解决的问题。此时&#xff0c;一款强大的ERP&#xff08;企业资源规…

线性代数|机器学习-P13计算特征值和奇异值

文章目录 1. 特征值1.1 特征值求解思路1.1 相似矩阵构造 1. 特征值 1.1 特征值求解思路 我们想要计算一个矩阵的特征值&#xff0c;一般是用如下公式&#xff1a; ∣ ∣ A − λ I ∣ ∣ 0 → λ 1 , λ 2 , ⋯ , λ n \begin{equation} ||A-\lambda I||0\rightarrow \lamb…

汇聚荣科技有限公司实力强吗?

汇聚荣科技有限公司实力强吗?在当今快速发展的科技行业中&#xff0c;公司的实力往往决定了其市场竞争力和发展前景。对于汇聚荣科技有限公司而言&#xff0c;其是否具备强大的实力&#xff0c;不仅关系到自身的发展&#xff0c;也影响着投资者和合作伙伴的选择。因此&#xf…

植物大战僵尸杂交版2.1版本重磅发布!更新内容介绍讲解

植物大战僵尸杂交版2.1版&#xff0c;简直是游戏迷们的福音&#xff01;这个版本不仅更新了大量的新植物和僵尸角色&#xff0c;还加入了更多的游戏模式和挑战关卡&#xff0c;让玩家们可以更加畅快地玩耍。 植物大战僵尸杂交版V2.1 :苹果安卓 PC防闪退工具修改工具高清工具通关…

16个不为人知的资源网站,强烈建议收藏!

整理了16个不为人知的资源网站&#xff0c;涵盖了课程学习、办公技能、娱乐休闲、小说音乐等多种资源&#xff0c;强烈建议收藏&#xff01; #学习网站 1、中国大学MOOC icourse163.org/ 这是一个汇集了国内顶尖大学免费课程资源的平台&#xff0c;众多985工程院校如北京大…

将HTML转化为PDF,一键操作轻松实现高效文件转换,轻松应对多种需求场景

在信息时代的浪潮中&#xff0c;文件格式的转换已经成为我们日常工作、学习和生活中不可或缺的一部分。无论是网页内容的保存、报告的整理还是简历的发送&#xff0c;我们经常需要将HTML文档转换为PDF格式&#xff0c;以确保文件内容的完整性和可读性。然而&#xff0c;传统的转…

3dmax在设计3D模型时闪退解决方法---模大狮模型网

3ds Max 在设计 3D 模型时闪退可能由多种原因造成&#xff0c;以下是一些常见的解决方法&#xff1a; 更新显卡驱动程序&#xff1a; 一个过时或不稳定的显卡驱动程序可能导致 3ds Max 闪退。请确保你的显卡驱动程序是最新版本&#xff0c;并且与 3ds Max 兼容。 关闭不必要的…

基于MCGS的双容水箱液位控制系统设计【MCGS+MATLAB+研华工控机】

摘 要 液位控制技术在众多工业领域中扮演着至关重要的角色。无论是化工、制药、食品加工还是水处理行业&#xff0c;对液位进行精确控制都是保证生产流程稳定、产品质量可靠的关键环节。因此基于实验平台设计了液位自动控制系统。首先&#xff0c;根据实际液位的控制需求&…

【SpringCloud学习笔记】RabbitMQ(上)

1. RabbitMQ简介 官网地址&#xff1a;https://www.rabbitmq.com/ 2. 安装方式 安装前置准备&#xff1a; 此处基于Linux平台 Docker进行安装&#xff0c;前置准备如下&#xff1a; Linux云服务器 / 虚拟机Docker环境 安装命令&#xff1a; docker run \-e RABBITMQ_DEFAU…