Vue2源码梳理:源码构建流程与运行时和编译时的版本选择
Vue.js 源码构建
1 )rollup 和 webpack 的对比
- vuejs的源码呢是基于rollup构建的
- 参考: https://github.com/rollup/rollup
- rollup 和 webpack 都是一个构建工具
- webpack 它会更强大一些, 会把像图片, css等静态资源通通编译成javascript
- rollup 更适合一种javscript库的一个编译
- 它只出了js部分,而其他资源它是不管的,所以它更轻量
- 在编译后代码也是更友好的
- 所以 vuejs 就选了rollup做构建
2 )rollup的构建设计
- vuejs 是发布到 npm 上的一个包, 每个包都是需要一个package.json文件来做描述
- 它是对项目的描述文件,它的内容实际上是一个标准的 JSON 对象
- 比如说,常用的属性, name, version, description, main, module, …
- main 是vue的入口,在 import vue 时,通过这个 main 来查找入口, 后缀是.js
- module 和 main 非常类似的,在webpack2以上把 module作为默认入口, 后缀是 .esm.js
- vuejs 源码是基于 rollup 构建的,它的构建相关配置都在 scripts 目录下
- npm 提供了一个叫 npm scripts 的东西
- 之前早期构建, 可能会用到gulp或者grunt
- 它们两个都是一个以任务为基准的
- 也就是说可以定义一系列任务
- npm scripts 就是完成了这部分的功能
- 也就是说它定义了很多脚本, 每个脚本都是一个任务
- 通过 npm run xxx 可以执行不同的任务
- 构建相关的任务,就是这三个
- build 构建web平台相关
- build:ssr 构建服务端渲染相关
- build:weex 构建weex平台相关
- 我们的源码是托管在 src 目录下,通过构建生成的目标代码在 dist 目录下
- 在vue的仓库下,它已经默认帮我们构建出来很多版本的vuejs
- 那为什么我们能构建如此多版本的vuejs呢?
3 )rollup构建vuejs的过程
package.json
{"script": {"build": "node scripts/build.js","build:ssr": "npm run build -- web-runtime-cjs,web-server-renderer","build:weex": "npm run build -- weex"}
}
- 当我们去执行的这个 npm scripts 的时候,比如说,执行 npm run build
- 它实际上就是执行了这样一个脚本
node scripts/build.js
- 我们来看一下 scripts/build.js
scripts/build.js
const fs = require('fs')
const path = require('path')
const zlib = require('zlib')
const rollup = require('rollup')
const terser = require('terser')if (!fs.existsSync('dist')) {fs.mkdirSync('dist')
}let builds = require('./config').getAllBuilds()// filter builds via command line arg
if (process.argv[2]) {const filters = process.argv[2].split(',')builds = builds.filter(b => {return filters.some(f => b.output.file.indexOf(f) > -1 || b._name.indexOf(f) > -1)})
} else {// filter out weex builds by defaultbuilds = builds.filter(b => {return b.output.file.indexOf('weex') === -1})
}build(builds)function build (builds) {let built = 0const total = builds.lengthconst next = () => {buildEntry(builds[built]).then(() => {built++if (built < total) {next()}}).catch(logError)}next()
}function buildEntry (config) {const output = config.outputconst { file, banner } = outputconst isProd = /(min|prod)\.js$/.test(file)return rollup.rollup(config).then(bundle => bundle.generate(output)).then(({ output: [{ code }] }) => {if (isProd) {const minified = (banner ? banner + '\n' : '') + terser.minify(code, {toplevel: true,output: {ascii_only: true},compress: {pure_funcs: ['makeMap']}}).codereturn write(file, minified, true)} else {return write(file, code)}})
}function write (dest, code, zip) {return new Promise((resolve, reject) => {function report (extra) {console.log(blue(path.relative(process.cwd(), dest)) + ' ' + getSize(code) + (extra || ''))resolve()}fs.writeFile(dest, code, err => {if (err) return reject(err)if (zip) {zlib.gzip(code, (err, zipped) => {if (err) return reject(err)report(' (gzipped: ' + getSize(zipped) + ')')})} else {report()}})})
}function getSize (code) {return (code.length / 1024).toFixed(2) + 'kb'
}function logError (e) {console.log(e)
}function blue (str) {return '\x1b[1m\x1b[34m' + str + '\x1b[39m\x1b[22m'
}
- 前面声明读取的模块
let builds = require('./config').getAllBuilds()
是从配置文件中,读取配置- 之后,再通过命令行参数对构建配置做过滤,最终调用 build() 函数 进行真正的构建
- 所以它整个的构建的流程是非常清晰的
- 那我们首先来分析一下这个这就是怎么拿到的
打开 .config 文件
const path = require('path')
const buble = require('rollup-plugin-buble')
const alias = require('rollup-plugin-alias')
const cjs = require('rollup-plugin-commonjs')
const replace = require('rollup-plugin-replace')
const node = require('rollup-plugin-node-resolve')
const flow = require('rollup-plugin-flow-no-whitespace')
const version = process.env.VERSION || require('../package.json').version
const weexVersion = process.env.WEEX_VERSION || require('../packages/weex-vue-framework/package.json').version
const featureFlags = require('./feature-flags')const banner ='/*!\n' +` * Vue.js v${version}\n` +` * (c) 2014-${new Date().getFullYear()} Evan You\n` +' * Released under the MIT License.\n' +' */'const weexFactoryPlugin = {intro () {return 'module.exports = function weexFactory (exports, document) {'},outro () {return '}'}
}const aliases = require('./alias')
const resolve = p => {const base = p.split('/')[0]if (aliases[base]) {return path.resolve(aliases[base], p.slice(base.length + 1))} else {return path.resolve(__dirname, '../', p)}
}const builds = {// Runtime only (CommonJS). Used by bundlers e.g. Webpack & Browserify'web-runtime-cjs-dev': {entry: resolve('web/entry-runtime.js'),dest: resolve('dist/vue.runtime.common.dev.js'),format: 'cjs',env: 'development',banner},'web-runtime-cjs-prod': {entry: resolve('web/entry-runtime.js'),dest: resolve('dist/vue.runtime.common.prod.js'),format: 'cjs',env: 'production',banner},// Runtime+compiler CommonJS build (CommonJS)'web-full-cjs-dev': {entry: resolve('web/entry-runtime-with-compiler.js'),dest: resolve('dist/vue.common.dev.js'),format: 'cjs',env: 'development',alias: { he: './entity-decoder' },banner},'web-full-cjs-prod': {entry: resolve('web/entry-runtime-with-compiler.js'),dest: resolve('dist/vue.common.prod.js'),format: 'cjs',env: 'production',alias: { he: './entity-decoder' },banner},// Runtime only ES modules build (for bundlers)'web-runtime-esm': {entry: resolve('web/entry-runtime.js'),dest: resolve('dist/vue.runtime.esm.js'),format: 'es',banner},// Runtime+compiler ES modules build (for bundlers)'web-full-esm': {entry: resolve('web/entry-runtime-with-compiler.js'),dest: resolve('dist/vue.esm.js'),format: 'es',alias: { he: './entity-decoder' },banner},// Runtime+compiler ES modules build (for direct import in browser)'web-full-esm-browser-dev': {entry: resolve('web/entry-runtime-with-compiler.js'),dest: resolve('dist/vue.esm.browser.js'),format: 'es',transpile: false,env: 'development',alias: { he: './entity-decoder' },banner},// Runtime+compiler ES modules build (for direct import in browser)'web-full-esm-browser-prod': {entry: resolve('web/entry-runtime-with-compiler.js'),dest: resolve('dist/vue.esm.browser.min.js'),format: 'es',transpile: false,env: 'production',alias: { he: './entity-decoder' },banner},// runtime-only build (Browser)'web-runtime-dev': {entry: resolve('web/entry-runtime.js'),dest: resolve('dist/vue.runtime.js'),format: 'umd',env: 'development',banner},// runtime-only production build (Browser)'web-runtime-prod': {entry: resolve('web/entry-runtime.js'),dest: resolve('dist/vue.runtime.min.js'),format: 'umd',env: 'production',banner},// Runtime+compiler development build (Browser)'web-full-dev': {entry: resolve('web/entry-runtime-with-compiler.js'),dest: resolve('dist/vue.js'),format: 'umd',env: 'development',alias: { he: './entity-decoder' },banner},// Runtime+compiler production build (Browser)'web-full-prod': {entry: resolve('web/entry-runtime-with-compiler.js'),dest: resolve('dist/vue.min.js'),format: 'umd',env: 'production',alias: { he: './entity-decoder' },banner},// Web compiler (CommonJS).'web-compiler': {entry: resolve('web/entry-compiler.js'),dest: resolve('packages/vue-template-compiler/build.js'),format: 'cjs',external: Object.keys(require('../packages/vue-template-compiler/package.json').dependencies)},// Web compiler (UMD for in-browser use).'web-compiler-browser': {entry: resolve('web/entry-compiler.js'),dest: resolve('packages/vue-template-compiler/browser.js'),format: 'umd',env: 'development',moduleName: 'VueTemplateCompiler',plugins: [node(), cjs()]},// Web server renderer (CommonJS).'web-server-renderer-dev': {entry: resolve('web/entry-server-renderer.js'),dest: resolve('packages/vue-server-renderer/build.dev.js'),format: 'cjs',env: 'development',external: Object.keys(require('../packages/vue-server-renderer/package.json').dependencies)},'web-server-renderer-prod': {entry: resolve('web/entry-server-renderer.js'),dest: resolve('packages/vue-server-renderer/build.prod.js'),format: 'cjs',env: 'production',external: Object.keys(require('../packages/vue-server-renderer/package.json').dependencies)},'web-server-renderer-basic': {entry: resolve('web/entry-server-basic-renderer.js'),dest: resolve('packages/vue-server-renderer/basic.js'),format: 'umd',env: 'development',moduleName: 'renderVueComponentToString',plugins: [node(), cjs()]},'web-server-renderer-webpack-server-plugin': {entry: resolve('server/webpack-plugin/server.js'),dest: resolve('packages/vue-server-renderer/server-plugin.js'),format: 'cjs',external: Object.keys(require('../packages/vue-server-renderer/package.json').dependencies)},'web-server-renderer-webpack-client-plugin': {entry: resolve('server/webpack-plugin/client.js'),dest: resolve('packages/vue-server-renderer/client-plugin.js'),format: 'cjs',external: Object.keys(require('../packages/vue-server-renderer/package.json').dependencies)},// Weex runtime factory'weex-factory': {weex: true,entry: resolve('weex/entry-runtime-factory.js'),dest: resolve('packages/weex-vue-framework/factory.js'),format: 'cjs',plugins: [weexFactoryPlugin]},// Weex runtime framework (CommonJS).'weex-framework': {weex: true,entry: resolve('weex/entry-framework.js'),dest: resolve('packages/weex-vue-framework/index.js'),format: 'cjs'},// Weex compiler (CommonJS). Used by Weex's Webpack loader.'weex-compiler': {weex: true,entry: resolve('weex/entry-compiler.js'),dest: resolve('packages/weex-template-compiler/build.js'),format: 'cjs',external: Object.keys(require('../packages/weex-template-compiler/package.json').dependencies)}
}function genConfig (name) {const opts = builds[name]const config = {input: opts.entry,external: opts.external,plugins: [flow(),alias(Object.assign({}, aliases, opts.alias))].concat(opts.plugins || []),output: {file: opts.dest,format: opts.format,banner: opts.banner,name: opts.moduleName || 'Vue'},onwarn: (msg, warn) => {if (!/Circular/.test(msg)) {warn(msg)}}}// built-in varsconst vars = {__WEEX__: !!opts.weex,__WEEX_VERSION__: weexVersion,__VERSION__: version}// feature flagsObject.keys(featureFlags).forEach(key => {vars[`process.env.${key}`] = featureFlags[key]})// build-specific envif (opts.env) {vars['process.env.NODE_ENV'] = JSON.stringify(opts.env)}config.plugins.push(replace(vars))if (opts.transpile !== false) {config.plugins.push(buble())}Object.defineProperty(config, '_name', {enumerable: false,value: name})return config
}if (process.env.TARGET) {module.exports = genConfig(process.env.TARGET)
} else {exports.getBuild = genConfigexports.getAllBuilds = () => Object.keys(builds).map(genConfig)
}
- 这个config文件在最后一行暴露了一个方法,叫 getAllBuilds,它是一个函数
- 这个函数做了什么事情呢?
Object.keys(builds).map(genConfig)
- 拿到一个keys的数组,然后我们再通过map方法调用这个 genConfig 函数
- 这个函数做了什么事情呢?
- 我们来看这个 builds 参数
- 上面代码大篇幅定义了 builds 对象
- 里面每个key对应的也都是一个对象
- 通过注释可知,是不同版本的vuejs的编译配置
- 每一个编译配置它都会有一个 entry 顾名思义就是入口
- dest 顾名思义就是目标
- 还有一个format(输出格式) 和 banner(头部注释)
- 这个 entry 它是通过 resolve 这个函数,然后传一个字符串(文件地址)
const aliases = require('./alias') const resolve = p => {const base = p.split('/')[0]if (aliases[base]) {return path.resolve(aliases[base], p.slice(base.length + 1))} else {return path.resolve(__dirname, '../', p)} }
- resolve 函数,它就是接收一个参数。这个字符参数会通过split(‘/’) 拿到第一个值作为base
- 之后判断 aliases 这个 aliases 也是 require 进来的,看下这个 alias 文件
const path = require('path') const resolve = p => path.resolve(__dirname, '../', p)module.exports = {vue: resolve('src/platforms/web/entry-runtime-with-compiler'),compiler: resolve('src/compiler'),core: resolve('src/core'),shared: resolve('src/shared'),web: resolve('src/platforms/web'),weex: resolve('src/platforms/weex'),server: resolve('src/server'),sfc: resolve('src/sfc') }
- 可见,alias 文件提供别名到真实地址文件的映射
- 回到最上面的 resolve 方法内部,最终返回了从参数到真实地址的字符串
- dest 这个key也走的 resolve, 只不过走到了 最终 else 的环节里
- format 是构建出来的文件格式,cjs 对应的就是 xxx.common.js
- cjs 最终生成的js文件是 module.exports = Vue
- es 最终生成的文件是 export default Vue
- umd 最终生成的文件是 符合 umd 规范的 vuejs 文件
- …
- 所以,很显然
- 上面 web 对应的真实的路径是 path.resolve(__dirname, ‘…/src/platforms/web’),这个路径就找到了 Vue.js 源码的 web 目录
- 然后 resolve 函数通过 path.resolve(aliases[base], p.slice(base.length + 1)) 找到了最终路径
- 它就是 Vue.js 源码 web 目录下的 entry-runtime.js。因此,web-runtime-cjs 配置对应的入口文件就找到了
- 它经过 Rollup 的构建打包后,最终会在 dist 目录下生成 vue.runtime.common.js
- banner 是自己设计的头部注释
- 里面可以 写八本,日期,作者,license 等信息
- 再回到我们的config,最终通过
Object.keys(builds).map(genConfig)
- 拿到这个所有keys 的一个数组,然后这个这个数组我们去调用这个 genConfig 函数
- genConfig 就拿到每个key,然后它就会拿到这个对象,再通过 build[name]
- name 是key对应的这个对象,构造出一个新的 config 对象
- 里面有 input, external, plugins, output, …
- 这个最终的 config 对象才是 rollup 打包所需要的配置结构
- 这是个适配器来进行的转换工作
- 返回到
let builds = require('./config').getAllBuilds()
- 这里的 builds 是一个数组
- 之后进行
if (process.argv[2]) {}
的判断- 提取到命令行输出的参数,如 – weex 等
- 如果有参数,则会通过 filter 来过滤一些不需要的流程
- 最终编译的时候,就调用
build(builds)
在里面进行一个个的编译- 里面定义一个 next() 函数,里面调用 buildEntry, 之后递归,里面有个 built 计数器
- 而 buildEntry 传入最终的config, config作为最终rollup的参数进行构建
- 编译完之后得到了 bundle, 通过了 bundle.generate 传入 output
- 之后拿到 code, 判断环境,分别做处理,最终通过 write 方法,得到构建好的文件
- 在生成的过程中,打下一些 log 信息
- 这是整个的构建流程
4 ) Runtime Only VS Runtime + Compiler
- 通常我们利用 vue-cli 去初始化我们的 Vue.js 项目的时候
- 会询问我们用 Runtime Only 版本的还是 Runtime + Compiler 版本
- 下面我们来对比这两个版本
4.1 ) Runtime Only
- 我们在使用 Runtime Only 版本的 Vue.js 的时候,通常需要借助如 webpack 的 vue-loader 工具把 .vue 文件编译成 JavaScript
- 在浏览器里,是不认识 .vue文件的,所以需要一个编译的过程,在编译阶段,会把 template 模板编译成 render 函数
- 最终编译后的,就是一个 render 函数的版本,所以vue是不带编译的,也就是运行时不带编译
- 所以它只包含运行时的 Vue.js 代码,因此代码体积也会更轻量
4.2 )Runtime + Compiler
-
我们如果没有对代码做预编译,但又使用了 Vue 的 template 属性并传入一个字符串,则需要在客户端编译模板,如下所示:
// 需要编译器的版本 new Vue({template: '<div>{{ hi }}</div>' })
-
这种一定要选择 Runtime + Compiler 版本
// 这种情况不需要 new Vue({render (h) {return h('div', this.hi)} })
-
这种就不需要
-
而 .vue文件 是在编译过程中,通过 vue-loader 处理的
-
所以我们写的 .vue 文件在运行的时候已经编译成 js 函数了,并且模板部分已经编译成 render 函数了
-
在 Vue.js 2.0 中,最终渲染都是通过 render 函数,如果写 template 属性,则需要编译成 render 函数
-
那么这个编译过程会发生运行时,需要带有编译器的版本
-
很显然,这个编译过程对性能会有一定损耗,所以通常开发阶段更推荐使用 Runtime-Only 的 Vue.js
- 一种是运行时的性能优化,一种是编译出来的体积会更轻量
5 )总结
- 我们可了解到 Vue.js 的构建打包过程,也知道了不同作用和功能的 Vue.js 它们对应的入口以及最终编译生成的 JS 文件
- 在实际开发过程中我们会用 Runtime Only 版本开发比较多
- 但为了分析 Vue 的编译过程,我们重点分析的源码是
相关文章:
Vue2源码梳理:源码构建流程与运行时和编译时的版本选择
Vue.js 源码构建 1 )rollup 和 webpack 的对比 vuejs的源码呢是基于rollup构建的 参考: https://github.com/rollup/rollup rollup 和 webpack 都是一个构建工具 webpack 它会更强大一些, 会把像图片, css等静态资源通通编译成javascriptrollup 更适合一种javscri…...
透视数据:数据可视化工具的多重场景应用
数据可视化工具已经成为了许多领域中的重要利器,它们在各种场景下发挥着重要作用。下面我就以可视化从业者的角度简单谈谈数据可视化工具在不同场景下的应用: 企业数据分析与决策支持 在企业层面,数据可视化工具被广泛应用于数据分析和决策…...
系列十四(面试)、谈谈你对StackOverflowError的理解?
一、StackOverflowError 1.1、概述 StackOverflowError是栈内存溢出的意思。栈中主要存储的是8种基本数据类型 引用类型 实例方法,栈的空间也是有限的,当存储进栈中的容量大于栈的最大容量时,就会报StackOverflowError的错误。 1.2、案例 …...
【WebRTC---源码篇】(二十五)音视频同步
RTC音视频同步场景: 音视频不在同一个时间点开始采集,如在视频先采集,音频后采集的情况下。我们不能贸然的认为音频起点来对齐视频起点,这种情况下,如何对音视频进行处理,就涉及到了音视频同步的知识。 解决思路: 通过现有条件,我们拥有RTP和SR,那么是不是可以用这两…...
鸿蒙开发之统一样式, @Styles 复用样式
只能使用通用样式 Entry Component struct Test {// 样式 就近原则 即{}之内的优先级更高 Styles customStyles(){.width(200).height(60).backgroundColor(Color.Red)}build() {Row() {Column({ space: 5 }) {Text("自定义样式").fontSize(30).textAlign(TextAlign…...
解决java内存问题
遇到 Java 控制台程序中的 Exception in thread “main” java.lang.OutOfMemoryError: Java heap space 错误通常意味着程序在其分配的堆内存空间中耗尽了内存。这个问题通常可以通过以下方法解决: 增加堆内存大小 可以通过调整 JVM(Java虚拟机&#x…...
分享5款为你生活带来便捷的小工具
生活需要一些小巧而贴心的工具,它们能够在细节处为我们带来便捷。这五款工具简洁而实用,看看它们是否适合融入你的生活。 1.图片压缩——TinyPNG TinyPNG是一款图片压缩工具,可以智能地减少WebP、PNG和JPEG图片的文件大小。TinyPNG通…...
【Java JVM】JVM 分析工具
在 $JAVA_HOME/bin 的目录下, 存在着许多小工具, 除了编译和运行 Java 程序外, 打包, 部署, 签名, 调试, 监控, 运维等各种场景都可能会用到它们。 1 常用的命令行工具 1.1 jps (JVM Process Status Tool) - 虚拟机进程状况工具 列出正在运行的虚拟机进程, 并显示虚拟机执行…...
融资项目——vue之双向数据绑定
上一篇文章中使用的v-bind是单向绑定方法,即数据改变,网页相应的视图发生改变,但是网页视图发生改变其相关联的数据不会发生改变。但是双向数据绑定不同之处在于网页视图发生改变其相关联的数据也会发生改变。Vue可以使用v-model进行双向数据…...
『番外篇五』SwiftUI 进阶之如何动态获取任意视图的 tag 和 id 值
概览 在某些场景下,我们需要用代码动态去探查 SwiftUI 视图的信息。比如任意视图的 id 或 tag 值: 如上图所示:我们通过动态探查技术在运行时将 SwiftUI 特定视图的 tag 和 id 值显示在了屏幕上。 这是如何做到的呢? 在本篇博文,您将学到如下内容: 概览1. “如意如意,…...
姿态识别、目标检测和跟踪的综合应用
引言: 近年来,随着人工智能技术的不断发展,姿态识别、目标检测和跟踪成为了计算机视觉领域的热门研究方向。这三个技术的综合应用为各个行业带来了巨大的变革和机遇。本文将分别介绍姿态识别、目标检测和跟踪的基本概念和算法,并探…...
数据结构考试测试编程题
作者前言 🎂 ✨✨✨✨✨✨🍧🍧🍧🍧🍧🍧🍧🎂 🎂 作者介绍: 🎂🎂 🎂 🎉🎉🎉…...
力扣每日一题day37[113.路径总和ii]
给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。 叶子节点 是指没有子节点的节点。 示例 1: 输入:root [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum 22 输出&a…...
Keras使用sklearn中的交叉验证和网格搜索
Keras是Python在深度学习领域非常受欢迎的第三方库,但Keras的侧重点是深度学习,而不是所以的机器学习。事实上,Keras力求极简主义,只专注于快速、简单地定义和构建深度学习模型所需要的内容。Python中的scikit-learn是非常受欢迎的…...
docker--Prometheus、Grafana、node_exporter的安装配置及Springboot集成Prometheus示例
1. 安装Prometheus Prometheus一个系统和服务监控系统。它以给定的时间间隔从配置的目标收集指标,计算规则表达式,显示结果,并在观察到某些条件为真时触发警报。 可观察性侧重于根据系统产生的数据了解系统的内部状态,这有助于确定基础设施是否健康。Prometheus是用于监视…...
数据结构和算法笔记2:二分法
二分法网上有两种写法,一种左闭右闭,一种左闭右开,个人习惯左闭右闭的写法, 有序数组查找数 这是标准二分法,对应力扣的704. 二分查找: 求值为target的索引 int search(vector<int>& nums, i…...
Mybatis3系列课程8-带参数查询
简介 上节课内容中讲解了查询全部, 不需要带条件查, 这节我们讲讲 带条件查询 目标 1. 带一个条件查询-基本数据类型 2.带两个条件查询-连个基本数据类型 3.带一个对象类型查询 为了实现目标, 我们要实现 按照主键 查询某个学生信息, 按照姓名和年级编号查询学生信息 按照学生…...
IDEA shorten command line介绍和JAR manifest 导致mybatis找不到接口类处理
如果类路径太长,或者有许多VM参数,程序就无法启动。原因是大多数操作系统都有命令行长度限制。在这种情况下,IntelliJIDEA将试图缩短类路径。最好选中 classpath file模式。 shorten command line 选项提供三种选项缩短类路径。 none&#x…...
泽攸科技SEM台式扫描电子显微镜
泽攸科技是一家国产的科学仪器公司,专注于研发、生产和销售原位电镜解决方案、扫描电镜整机、台阶仪、探针台等仪器。目前台式扫描电镜分为三个系列:ZEM15、ZEM18、ZEM20。 ZEM15台式扫描电镜: ZEM18台式扫描电镜: ZEM20台式扫描…...
华为交换机配置BGP的基本示例
BGP简介 定义 边界网关协议BGP(Border Gateway Protocol)是一种实现自治系统AS(Autonomous System)之间的路由可达,并选择最佳路由的距离矢量路由协议。早期发布的三个版本分别是BGP-1(RFC1105࿰…...
数据分析基础之《numpy(4)—ndarry运算》
一、逻辑运算 当我们要操作符合某一条件的数据时,需要用到逻辑运算 1、运算符 满足条件返回true,不满足条件返回false # 重新生成8只股票10个交易日的涨跌幅数据 stock_change np.random.normal(loc0, scale1, size(8, 10))# 获取前5行前5列的数据 s…...
分享一个项目——Sambert UI 声音克隆
文章目录 前言一、运行ipynb二、数据标注三、训练四、生成总结 前言 原教程视频 项目链接 运行一个ipynb,就可操作 总共四步 1)运行ipynb 2)数据标注 3)训练 4)生成 一、运行ipynb 等运行完毕后,获得该…...
ES6 语法精粹简读
本文旨在记录 ES6 的核心常用语法,略去一些细节。 文章目录 1 var 函数作用域与 let/const 块作用域2 解构赋值数组结构赋值对象结构赋值3 ES6 中字符串的新语法模板字符串模板编译标签模板4 ES6 中的函数默认值rest 参数箭头函数this 指向问题部署管道机制尾调用优化...
uniapp整合echarts(目前性能最优、渲染最快方案)
本文echarts示例如上图,可扫码体验渲染速度及loading效果,下文附带本小程序uniapp相关代码 实现代码 <template><view class="source...
解决Electron应用中的白屏问题的实用方法
在使用Electron构建应用程序时,一些开发者可能会面临窗口加载过程中出现的白屏问题。这种问题主要分为两个方面: Electron未加载完毕HTML: 这时Electron自身产生的白色背景可能导致用户在启动应用时看到一片空白。HTML加载渲染过程中的短暂白…...
大数据---34.HBase数据结构
一、HBase简介 HBase是一个开源的、分布式的、版本化的NoSQL数据库(即非关系型数据库),依托Hadoop分布式文件系统HDFS提供分布式数据存储,利用MapReduce来处理海量数据,用Zookeeper作为其分布式协同服务,一…...
【工具使用-有道云笔记】如何在有道云笔记中插入目录
一,简介 本文主要介绍如何在有道云笔记中插入目录,方便后续笔记的查看,供参考。 二,具体步骤 分为两个步骤:1,设置标题格式;2,插入标题。非常简单~ 2.1 设置标题格式 鼠标停在标…...
用户管理第2节课-idea 2023.2 后端一删除表,从零开始---【本人】
一、清空model文件夹下,所有文件 1.1.1效果如下: 1.1代码内容 package com.daisy.usercenter.model;import lombok.Data;Data public class User {private Long id;private String name;private Integer age;private String email; }二、清空mapper文件…...
如何添加jar包到本地Maven项目中
在 Maven 中添加一个外部 JAR 包的依赖,你需要使用 Maven 的 <dependency> 元素来指定该 JAR 包的坐标信息。以下是具体的步骤: 将 JAR 包手动添加到 Maven 本地仓库: 首先,确保将外部 JAR 包手动添加到 Maven 本地仓库。可…...
智能优化算法应用:基于学校优化算法3D无线传感器网络(WSN)覆盖优化 - 附代码
智能优化算法应用:基于学校优化算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于学校优化算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.学校优化算法4.实验参数设定5.算法结果6.…...
做网站的主要作用/网站建设的基本流程
皮尔逊Pearson 相关系数:使用前提:大小一致、连续、服从正态分布的数据集;斯皮尔曼spearman等级相关系数:皮尔逊Pearson 相关系数使用前提任何一个条件不满足时可以考虑使用该系数;肯德尔等级kendallta相关系数&#x…...
在阿里巴巴做网站多少钱2019/企业网站首页
通常我们定义一个基本数据类型的变量,函数调用的现场保存,一个对象的引用,都使用JVM中的栈空间; 通过new关键字和构造器创建的对象放在堆空间,堆是垃圾收集器管理的主要区域,由于现在的垃圾收集器都采用分…...
找人做效果图去什么网站/百度收录批量提交入口
1、问题描述 在新安装的PyCharm 2017.3(Community Edition)中,调试Python代码的时候,只启动Debugger,不启动Console,无法看打印出来的日志。 图1 debug代码结果页面只有Debugger 2、原因分析 根据以往调试经验,一定是…...
欧洲大带宽服务器/网站优化方案
字典(Dictionary) 字典是一种存储多个相同类型的值的容器。每个值(value)都关联唯一的键(key),键作为字典中的这个值数据的标识符。和数组中的数据项不同,字典中的数据项并没有具体顺…...
平板上做网站的软件/上海网络seo公司
如果是开平方根可以使用函数 SQRT(number),返回数值的平方根 比如SQRT(9) 计算返回3如果是开立方根或者n次方根,可以进e68a847a64364行幂运算,POWER(number,power)函数表示返回number数值的power次乘幂,如POWER(5,2)表示5的2次方&…...
桂林象鼻山门票/深圳优化公司哪家好
“Gotham” by James Gilleard♚作者:Nugine专栏地址:zhuanlan.zhihu.com/c_168195059在本篇文章中,我要向你展示使用 Cython 扩展 Python 的技巧。如果你同时有 C/C和 Python 的编码能力,我相信你会喜欢这个的。我们要造的轮子是…...