vue源码解析——vue如何将template转换为render函数
Vue 将模板(template)转换为渲染函数(render function)是 Vue 编译器的核心功能,它是 Vue 实现响应式和虚拟 DOM 的关键步骤。在 Vue 中,模板(template)是开发者编写的类似 HTML 的代码,用于描述页面的结构和交互逻辑。渲染函数(render function)是 Vue 编译器将模板转换为JavaScript 函数,用于生成虚拟 DOM,并最终渲染到页面上。所以render的作用是生成虚拟dom。你可能会想,为什么vue要写template而不是html?为什么写了template通过render将模板生成虚拟dom,而不是直接生成html呢?请往下看
vue模板渲染是个很复杂的过程,牵扯vue的响应式和虚拟dom。本文只抓核心流程,不关心具体实现。纵向深入,不做横向扩展,避免罗里吧嗦又抓不住重点。
vue中的template模板
在Vue中,模板(template)指的是开发者编写的类似HTML的代码,用于描述页面的结构、样式和交互逻辑。模板中可以包含Vue特有的指令、数据绑定、事件处理等内容,通过Vue的编译器将模板转换为渲染函数,最终渲染到页面上。
vue2的template
以下是一个简单的Vue2模板示例:比较简单的Vue模板,描述了页面的结构和交互逻辑,通过Vue的数据绑定和事件处理机制实现了动态更新页面内容的功能
<template><div><h1>{{ message }}</h1><p>计数:{{ count }}</p><button @click="increment">增加</button></div>
</template><script>
export default {data() {return {message: 'Hello, Vue!',count: 0};},methods: {increment() {this.count++;}}
};
</script><style>
h1 {color: blue;
}
p {font-size: 16px;
}
button {background-color: green;color: white;padding: 5px 10px;cursor: pointer;
}
</style>
在上面的示例中,
<template>
标签内包含了页面的结构,包括一个标题、一个段落和一个按钮。模板中使用了双大括号语法{{ }}
进行数据绑定,将message
和count
的值动态显示在页面上。按钮上使用了@click
指令绑定了increment
方法,实现点击按钮增加计数的功能。
vue3的template
以下是一个简单的Vue3模板示例:使用
<script setup>
语法的Vue 3模板,通过更简洁的语法实现了相同的功能。
<template><div><h1>{{ message }}</h1><p>计数:{{ count }}</p><button @click="increment">增加</button></div>
</template><script setup>
import { ref } from 'vue';const message = ref('Hello, Vue 3!');
const count = ref(0);const increment = () => {count.value++;
};
</script><style>
h1 {color: blue;
}
p {font-size: 16px;
}
button {background-color: green;color: white;padding: 5px 10px;cursor: pointer;
}
</style>
在这个示例中,我们使用
<script setup>
语法来定义组件的逻辑部分。通过import { ref } from 'vue';
引入ref
函数,然后直接在<script setup>
中定义message
和count
两个响应式数据,以及increment
方法。这样可以更加简洁地管理组件的状态和逻辑。
思考:为什么vue写成template形式而不是html
Vue.js 使用
template
而不是直接使用 HTML主要考虑了以下几个原因:
- 数据绑定:Vue.js 使用了数据绑定技术,可以动态地渲染和更新视图。如果直接使用 HTML,则需要使用一些特殊的语法来实现数据绑定,这会使 HTML 变得复杂和难以维护。
- 组件化:Vue.js 是一个基于组件的框架,可以将复杂的应用分解成多个小的组件。如果直接使用 HTML,则无法实现组件化的特性,因为 HTML 本身不支持组件的概念。
- 虚拟 DOM:Vue.js 使用了虚拟 DOM 技术,可以更高效地渲染和更新视图。如果直接使用 HTML,则需要使用一些特殊的语法来实现虚拟 DOM,这会使 HTML 变得复杂和难以维护。
- 编译优化:Vue.js 在编译期间可以对
template
进行优化,例如将相同的元素合并成一个元素,提高渲染性能。如果直接使用 HTML,则无法进行这种优化。
因此,Vue.js 使用
template
可以更好地支持数据绑定、组件化、虚拟 DOM 和编译优化等特性,同时可以让我们使用简单直观的方式来定义组件的结构和内容。
为什么render不直接将template转成html,而是转成了虚拟dom?
当我们使用
Vue
,往往会将页面拆分为各种组件,通过拼装组件来形成页面和应用,就像搭积木一样。模板编译后组件所产出的内容并不是html
字符串,而是大家所熟知的Virtual DOM。
组件最核心的东西是
render
函数,剩余的其他内容,如data
、compouted
、props
等都是为render
函数提供数据来源服务的。render
函数本可以直接产出html
字符串,但却产出了Virtual DOM
。Virtual DOM
终究要渲染真实 DOM,这个过程就可以理解为模板引擎年代的完全替换html
,只不过它采用的不是完全替换,我们通常把这个过程叫做patch。
当数据变更时,组件会产出新的VNode
,我们只需再次调用patch
函数即可
为何组件要从直接产出 html
变成产出 Virtual DOM
呢?
其原因是
Virtual DOM
带来了 分层设计,它对渲染过程的抽象,使得框架可以渲染到web
(浏览器) 以外的平台,以及能够实现SSR
等。至于Virtual DOM
相比原生 DOM 操作的性能,这并非Virtual DOM
的目标,确切地说,如果要比较二者的性能是要“控制变量”的,例如:页面的大小、数据变化量等
组件从直接产出 HTML 变成产出 Virtual DOM 的主要原因包括以下几点:
-
性能优化:Virtual DOM 可以作为一个轻量级的内存数据结构存在于内存中,通过对 Virtual DOM 进行比对,可以最小化对实际 DOM 的操作,从而提高性能。相比直接操作实际 DOM,Virtual DOM 的比对操作更高效,可以减少不必要的 DOM 操作,提升页面渲染性能。
-
跨平台兼容:Virtual DOM 的抽象层可以使得组件的渲染逻辑与具体平台无关,从而实现跨平台兼容。通过 Virtual DOM,可以将组件的渲染逻辑统一抽象,使得组件可以在不同平台上进行渲染,提高了组件的复用性和可移植性。
-
方便的状态管理:Virtual DOM 可以轻松地与状态管理库(如 Vuex、Redux 等)结合使用,实现组件状态的管理和更新。通过 Virtual DOM,可以更方便地管理组件的状态变化,实现数据驱动的视图更新。
-
简化复杂的 DOM 操作:直接操作实际 DOM 可能会涉及复杂的 DOM 操作,而 Virtual DOM 可以将这些操作抽象成简单的数据结构,使得组件的开发和维护更加简单和高效。
-
提高开发效率:通过 Virtual DOM,开发者可以更加专注于组件的逻辑和交互,而不需要过多关注底层的 DOM 操作细节。这样可以提高开发效率,减少开发成本。
综上所述,组件从直接产出 HTML 变成产出 Virtual DOM 主要是为了提高性能、跨平台兼容、方便的状态管理、简化复杂的 DOM 操作以及提高开发效率等方面的考虑。通过 Virtual DOM,可以更好地实现组件化开发和优化页面性能,提升用户体验。
编译VS运行时render
在大多数情况下,Vue会在编译阶段将模板(template)转换为渲染函数。这意味着Vue的编译器会在构建时将模板解析成渲染函数的静态代码,然后将这些静态代码打包到最终的构建文件中。编译时生成的渲染函数可以提高性能,因为它们是预先生成的静态代码,不需要在运行时进行解析和编译。
部分render函数在运行时生成:
- 在某些情况下,特别是在使用Vue的单文件组件(.vue文件)时,渲染函数可能会在运行时动态生成。这种情况下,Vue会在运行时解析模板并生成渲染函数。
- 在运行时动态生成渲染函数的过程中,Vue会利用编译器将模板转换为可执行的JavaScript代码,以便在每次组件渲染时动态生成虚拟DOM。这种方式相对于编译时生成静态渲染函数会带来一些性能开销,因为需要在每次渲染时进行模板解析和代码生成。
注:使用npm run dev,开发模式下虽然不会生成最终的生产构建文件,但是在使用
npm run dev
启动开发服务器时,Vue 项目中的代码仍然会经历编译和预处理过程,以便在开发服务器上实时编译和加载。
vue2的模板编译
实现模板编译共有三个阶段:解析、优化和生成
在vue2中,通过重写$mount方法,使得在调用原始的
$mount
函数之前,从template
选项中获取模板字符串或 DOM 元素,并将其编译为render
函数和staticRenderFns
数组。确保当前实例在调用$mount
函数时已经具有render
函数,从而可以正确地渲染到页面上。编译时生成的 render 函数会被挂载到组件实例的$options
对象上的render
属性中。这样,在组件实例化时,Vue 就可以直接从$options.render
中获取到预先编译好的 render 函数,而不需要每次都重新编译。
过程具体如下:
首先,Vue的编译器会将Vue模板(template)字符串解析为抽象语法树(Abstract Syntax Tree,AST)。AST表示了模板的结构和内容。编译器会对AST进行静态分析,识别模板中的静态内容(不会改变的部分)和动态内容(会改变的部分)。在静态分析的基础上,编译器会进行一些优化操作,例如静态节点提升(Static Node Hoisting)和静态属性提升(Static Props Hoisting),以减少渲染时的开销。根据AST和优化后的结果,编译器会生成对应的渲染函数代码。静态内容会被转换为静态的JavaScript代码,而动态内容会被转换为动态的JavaScript表达式。最终生成的渲染函数代码会被包含在最终的构建文件中,用于在组件渲染时生成虚拟DOM并更新页面。
render伪代码
重写$mount方法
const mount = Vue.prototype.$mount;//记录原$mount
Vue.prototype.$mount = function (el) {const vm = this;const options = vm.$options;el = document.querySelector(el);// 如果没有render方法if (!options.render) {let template = options.template;// 如果没有模板但是有elif (!template && el) {template = el.outerHTML;}const render = compileToFunctions(template);// 将render函数挂载到options上。options.render = render;}mount.call(this,..)//调用原$mount方法
}Vue.prototype._init = function (options) {const vm = this;vm.$options = options;// 初始化状态initState(vm);// 页面挂载if (vm.$options.el) {vm.$mount(vm.$options.el);}
}
compileToFunctions
export function compileToFunctions(template) {const root = parseHTML(template);let code = generate(root);let render = `with(this){return ${code}}`;let renderFn = new Function(render);return renderFn
}
vue2源码实现
重写$mount方法
首先,重写的$mount函数会检查
el
参数是否为字符串或 DOM 元素,如果不是,则会将其转换为字符串或 DOM 元素。如果el
参数为document.body
或document.documentElement
,则会打印一个警告信息,并返回当前实例。
接下来,这个$mount函数会检查当前实例的
$options
对象是否包含render
函数,如果不包含,则会尝试从template
选项中获取模板字符串或 DOM 元素,并将其编译为render
函数。如果template
选项为字符串,则会将其转换为模板字符串或 ID 选择器,并查找对应的 DOM 元素。如果template
选项为 DOM 元素,则会获取其innerHTML
属性。如果template
选项不存在,则会尝试从el
参数获取模板字符串或 DOM 元素。
如果
template
选项为字符串或 DOM 元素,则会使用compileToFunctions
函数将其编译为render
函数和staticRenderFns
数组。并且将render
函数和staticRenderFns
数组挂载到当前实例的$options
对象上。
compileToFunctions
函数是 Vue.js 中的编译器函数,它可以将模板字符串或 DOM 元素编译为render
函数和staticRenderFns
数组,并将其返回。最后,这个函数会调用原始的
$mount
函数,并将el
和hydrating
参数传递给它。
compileToFunctions方法
compileToFunctions
函数,它是将模板编译为 render 函数的入口函数。在这个函数中,Vue 的编译器会将模板解析成抽象语法树(AST),然后根据 AST 生成对应的 render 函数。
通过render函数反向去找怎么生成的
在 Vue.js 的源码中,createCompiler
函数是用于创建一个新的编译器的函数。createCompiler
函数调用createCompilerCreator函数,接收一个名为 baseCompile
的函数作为参数,并返回一个新的编译器函数。
当调用 createCompilerCreator函数时,会返回一个新的编译器函数,该函数包含 compile
和 compileToFunctions
两个方法。
compile
方法用于编译模板,并返回一个包含渲染函数和抽象语法树(AST)的对象。渲染函数是一个可以直接在渲染过程中使用的函数,而 AST 是模板的抽象语法树,可以用于进一步优化和代码生成。
compileToFunctions
方法也用于编译模板,但返回的是一个包含渲染函数和静态渲染函数数组的对象。这个方法可以用于将模板编译为可以直接在浏览器中运行的 JavaScript 函数。
baseCompile函数
baseCompile
是一个函数,在createCompiler
函数中被用作参数,返回一个新的编译器函数。baseCompile
函数的作用是将模板编译为抽象语法树(AST)并对其进行优化和代码生成。具体来说,编译器会遍历模板的 AST,根据不同的节点类型生成相应的代码片段,最终拼接成一个完整的 render 函数。这个 render 函数会在组件实例化时被调用,用于生成虚拟 DOM。
baseCompile
函数接收两个参数:
template
:要编译的模板字符串。options
:编译选项。
baseCompile
函数首先调用 parse
函数将模板解析为 AST,然后对 AST 进行优化,最后调用 generate
函数生成渲染函数和静态渲染函数数组。
在 parse
函数中,模板被解析为一个包含元素、指令和表达式的 AST。在 optimize
函数中,对 AST 进行优化以提高渲染性能。在 generate
函数中,根据 AST 生成渲染函数和静态渲染函数数组。
每个阶段具体如下:
1.模板解析-ast语法树
首先,Vue的编译器会将Vue模板(template)字符串解析为抽象语法树(Abstract Syntax Tree,AST)。AST表示了模板的结构和内容。
解析html的parse代码很长,几百行,它的作用就是将模板转换为ast语法树。给个示例看下ast语法树的样子吧
在AST explorer这个网站,可以看vue的模板转换为ast语法树的效果
AST (Abstract Syntax Tree),抽象语法树,记录了源代码的结构和语法信息。具体来说,AST 记录了以下信息:
- 节点类型:每个节点都有一个类型,例如表达式、函数、变量声明等。
- 节点内容:每个节点都有具体的内容,例如表达式的值、函数的名称和参数等。
- 子节点:每个节点可能有多个子节点,例如函数可能有多个参数,表达式可能有多个操作数。
- 位置信息:每个节点都有位置信息,包括行号和列号,用于定位源代码中的位置。
在 Vue.js 中,AST 记录了模板的结构和语法信息,包括以下内容:
- 元素:每个AST节点对应一个模板中的元素,包括标签、文本和注释。
- 属性:每个元素可能有多个属性,包括普通属性和指令属性。
- 表达式:元素和属性可能包含表达式,例如
v-if
指令中的表达式。- 位置信息:每个AST节点都有位置信息,包括行号和列号,用于定位模板中的位置。
通过记录这些信息,可以更好地理解和分析模板,并进行优化和代码生成,以提高渲染性能。
2.静态分析
编译器会对AST进行静态分析,识别模板中的静态内容(不会改变的部分)和动态内容(会改变的部分)。
3.优化
在静态分析的基础上,编译器会进行一些优化操作,例如静态节点提升(Static Node Hoisting)和静态属性提升(Static Props Hoisting)。优化器的作用是在AST中找出静态子树并打上标记。静态子树是在AST中永远不变的节点,如纯文本节 点,以减少渲染时的开销。
标记静态子树的好处:
- 每次重新渲染,不需要为静态子树创建新节点
- 虚拟DOM中patch时,可以跳过静态子树
4.代码生成
根据AST和优化后的结果,编译器会生成对应的渲染函数代码。静态内容会被转换为静态的JavaScript代码,而动态内容会被转换为动态的JavaScript表达式。
5.渲染函数输出
最终生成的渲染函数代码会被包含在最终的构建文件中,用于在组件渲染时生成虚拟DOM并更新页面。
vue2运行时动态生成render函数
在 Vue 2 中,当组件没有提供 render 函数且在编译阶段没有编译好的 render 函数时,那么在组件实例化时会动态生成 render 函数。这个 render 函数会在运行时生成,并且会被挂载到组件实例的
$options
对象上的render
属性中。
具体来说,Vue 会检查组件选项中的 render
方法。如果存在 render
方法,Vue 会调用该方法来动态生成 render 函数。这个 render
方法可以返回一个用于渲染组件的虚拟 DOM 树。
因此,在运行时动态生成 render 函数时,Vue 会调用组件实例的 $options.render
方法来生成 render 函数。这个方法的返回值将用于渲染组件的内容。
vue3的模板编译
Vue 3 在
render
函数方面相比 Vue 2 进行了一些改进和优化,在性能优化方面主要有两点改变
- 静态树提升(Static Tree Hoisting): Vue 3 在编译阶段会对模板进行静态分析,将静态节点提升为常量,减少渲染时的节点比对和更新操作,提高性能。
- 事件侦听器缓存(Event listener caching): Vue 3 会对事件侦听器进行缓存,避免每次渲染都重新创建事件侦听器,减少性能开销
vue3模板编译过程
parse 模板解析: 首先会调用
parse
方法,将模板源码解析为 AST(抽象语法树)的树形结构。AST 是对模板的抽象表示,方便后续的处理和转换。transform AST 转换: 接着可能会调用一系列的
transform
方法,对 AST 进行一些转换和优化操作。这些转换可以包括静态节点提升、插槽处理、指令转换等。generate 代码生成: 经过 AST 转换后,会调用
generate
方法,将经过处理后的 AST 节点转换为渲染函数的代码字符串。这个过程会将 AST 节点转换为可执行的 JavaScript 代码。优化代码: 可能会对生成的代码进行一些优化,例如进行尾部优化、静态节点提升等,以提高渲染函数的性能。
返回 CodegenResult: 最终将生成的代码字符串以及其他相关信息(如错误信息、提示等)封装在
CodegenResult
对象中返回,供后续使用。
render伪代码
compileToFunction伪代码
function compileToFunction(template, options) {const key = template;const cache = new Map();if (cache.has(key)) {return cache.get(key);}const { code } = compile(template, options); // 假设 compile 函数可以将模板编译成代码const render = new Function('Vue', code)(Vue); // 假设 Vue 是运行时的 Vue 实例// 标记函数为已编译render._rc = true;cache.set(key, render);return render;
}
function baseCompiler(source,options){const ast = baseParse(source,options);//生成ast语法树transform(ast,...)//对ast进行一个优化return generate(ast,options);//返回generate生成code
}
vue3源码实现
源码中,compileToFunction方法的实现位于core-main\packages\vue\src\index.ts文件中
compileToFunction方法
vue3模板编译的核心仍然是
compileToFunction
函数,将template模板转换成render函数。
整个过程可以分为以下几个步骤:
- 传入模板和选项参数: 函数接受两个参数,一个是模板
template
,另一个是选项参数options
。- 生成缓存键值: 将传入的模板作为键值
key
,用于缓存已经编译过的模板函数。- 检查缓存: 使用
cache
Map 对象来检查是否已经缓存了该模板对应的函数,如果有,则直接返回缓存的函数。- 模板编译: 调用
compile
函数对传入的模板进行编译,得到编译后的代码code
。这里假设compile
函数是一个能够将模板编译成代码的函数。- 创建函数: 使用
new Function
构造函数,将编译后的代码作为函数体,生成一个新的函数render
。这个函数在运行时将会接收一个 Vue 实例作为参数。- 执行函数: 调用生成的函数
render
,并传入 Vue 实例作为参数,得到最终的渲染函数。- 标记函数: 将生成的渲染函数标记为已编译,以便下次可以直接从缓存中获取。
- 缓存函数: 将生成的渲染函数存入缓存中,以备下次使用。
- 返回函数: 返回生成的渲染函数。
核心调用了compile方法,compile又调了baseCompile方法
baseCompiler方法
关键方法还是看baseCompile方法。在 Vue 3 的
baseCompile
函数中,主要完成了将模板源码编译为渲染函数的过程。
整个过程可以分为以下几个步骤:
parse 模板解析
首先会调用 parse
方法,将模板源码解析为 AST(抽象语法树)的树形结构。AST 是对模板的抽象表示,方便后续的处理和转换。
transform AST 转换
接着可能会调用一系列的 transform
方法,对 AST 进行一些转换和优化操作。这些转换可以包括静态节点提升、插槽处理、指令转换等。
generate 代码生成
经过 AST 转换后,会调用 generate
方法,将经过处理后的 AST 节点转换为渲染函数的代码字符串。这个过程会将 AST 节点转换为可执行的 JavaScript 代码。
优化代码
可能会对生成的代码进行一些优化,例如进行尾部优化、静态节点提升等,以提高渲染函数的性能。
返回 CodegenResult
最终将生成的代码字符串以及其他相关信息(如错误信息、提示等)封装在 CodegenResult
对象中返回,供后续使用。
如何查看打包后的render函数?
在 Vue 项目中,不论是编译时还是运行时,打包后的构建文件通常都会包含 render 函数。区别在于编译时生成的 render 函数是静态的,而运行时生成的 render 函数是动态的。
具体来说:
-
编译时生成的 render 函数:在编译阶段,Vue 的编译器会将模板(template)编译为静态的 render 函数。这个静态 render 函数会被包含在最终的构建文件中,用于在组件渲染时生成虚拟 DOM。
-
运行时生成的 render 函数:有时候,Vue 组件可能会在运行时动态生成 render 函数,特别是在动态组件或函数式组件的情况下。这些动态生成的 render 函数通常不会在编译时静态生成,而是在组件实例化或渲染时动态生成。
打包 Vue 项目时,通常会将 Vue 组件中的模板(template)转换为渲染函数(render function),然后将这些渲染函数打包到最终的构建文件中。如果想查看 render 函数被打包到哪里了,可以按照以下步骤进行:
查看构建输出文件:
- 查看生成的构建文件,通常在
dist
目录下。- 打开生成的构建文件,查找包含 Vue 组件代码的文件,通常是经过处理的 JavaScript 文件。
搜索渲染函数代码:
- 在构建文件中搜索 Vue 组件的代码,特别是包含
render
函数的部分。- 渲染函数通常会以函数的形式存在,搜索关键字如
render: function
或render() {
来找到渲染函数所在的位置
思考:一个template对应一个render函数吗?
在 Vue 中,一个 template 可以对应多个 render 函数。在 Vue 的编译过程中,一个 template 会被编译为一个 render 函数,这个 render 函数用于生成组件的虚拟 DOM。然而,有时候一个 template 也可以对应多个 render 函数,这取决于 Vue 组件的定义方式和使用场景。
-
单文件组件:在 Vue 单文件组件中,通常一个 template 会对应一个 render 函数。这是因为单文件组件中的 template 会被编译为一个 render 函数,并且在组件的定义中只会有一个 render 函数。
-
动态组件:在某些情况下,一个 template 可能会对应多个 render 函数,特别是在动态组件的情况下。动态组件可以根据不同的条件或状态渲染不同的组件,每个组件可能有不同的 template 和 render 函数。
-
函数式组件:在函数式组件中,通常不会有 template,而是直接使用 render 函数来定义组件的渲染逻辑。
思考:打包后的每个.js文件都会有render函数吗?
在 Vue 项目中,经过编译和打包后的每个
.js
文件并不一定都会包含 render 函数。Render 函数通常是在 Vue 单文件组件中定义的,然后经过编译器编译为 JavaScript 代码,并最终打包到构建文件中。
具体来说:
-
单文件组件:在 Vue 单文件组件中,通常会包含 template 和 render 函数。编译器会将 template 编译为 render 函数,并将这个 render 函数包含在最终的构建文件中。
-
普通 JavaScript 文件:在普通的 JavaScript 文件中,如果没有定义 Vue 组件或没有使用 render 函数,那么这些文件通常不会包含 render 函数。
-
动态组件和函数式组件:动态组件和函数式组件可能会在运行时动态生成 render 函数,这些 render 函数可能不会在打包后的每个
.js
文件中静态存在,而是根据需要动态生成。
相关文章:
vue源码解析——vue如何将template转换为render函数
Vue 将模板(template)转换为渲染函数(render function)是 Vue 编译器的核心功能,它是 Vue 实现响应式和虚拟 DOM 的关键步骤。在 Vue 中,模板(template)是开发者编写的类似 HTML 的代…...
深入理解zookeeper
如果是zookeeper的初学者,可以看: zookeeper快速入门(合集)-CSDN博客 如果想要深入理解zookeeper,并在面试中取得更好的表现,可以看下面的文章,都是偏面试向的角度写的。 三分钟明白zookeeper…...
【漏洞复现】WordPress Plugin LearnDash LMS 敏感信息暴漏
漏洞描述 WordPress和WordPress plugin都是WordPress基金会的产品。WordPress是一套使用PHP语言开发的博客平台。该平台支持在PHP和MySQL的服务器上架设个人博客网站。WordPress plugin是一个应用插件。 WordPress Plugin LearnDash LMS 4.10.2及之前版本存在安全漏洞&#x…...
phpmyadmin页面getshell
0x00 前言 来到phpmyadmin页面后如何getshell呢?下面介绍两种方法 0x01 select into outfile直接写入 1、利用条件 对web目录需要有写权限能够使用单引号(root) 知道网站绝对路径(phpinfo/php探针/通过报错等) secure_file_priv没有具体值 2、查看secure_file…...
题目:学习static定义静态变量的用法
题目:学习static定义静态变量的用法 There is no nutrition in the blog content. After reading it, you will not only suffer from malnutrition, but also impotence. The blog content is all parallel goods. Those who are worried about being cheate…...
【C++】编程规范之函数规则
对所有函数入参进行合法性检查 在编写函数时,应该始终对所有传入的参数进行合法性检查,以防止出现意外的错误或异常情况。这包括但不限于检查指针是否为空、整数是否在有效范围内、数组是否越界等等。通过对参数进行严格的合法性检查,可以避免…...
HTML常用的图片标签和超链接标签
目录 一.常用的图片标签和超链接标签: 1.超链接标签: 前言: 超链接的使用: target属性: 1)鼠标样式: 2)颜色及下划线: 总结: 2.图片标签: 前言: img的使用: 设置图片: 1.设置宽度和高度: 2.HTM…...
浏览器工作原理与实践--WebAPI:XMLHttpRequest是怎么实现的
在上一篇文章中我们介绍了setTimeout是如何结合渲染进程的循环系统工作的,那本篇文章我们就继续介绍另外一种类型的WebAPI——XMLHttpRequest。 自从网页中引入了JavaScript,我们就可以操作DOM树中任意一个节点,例如隐藏/显示节点、改变颜色、…...
TCP网络协议栈和Posix网络部分API总结
文章目录 Posix网络部分API综述TCP协议栈通信过程TCP三次握手和四次挥手(看下图)三次握手常见问题?为什么是三次握手而不是两次?三次握手和哪些函数有关?TCP的生命周期是从什么时候开始的? 四次挥手通信状态…...
《解释器模式(极简c++)》
本文章属于专栏- 概述 - 《设计模式(极简c版)》-CSDN博客 模式说明 方案: 对每个data建立一个单点解释器对象X,dataA和dataB之间的关系,建立一个关系解释器对象Y,这里的Y处理的是X1和X2。这样,…...
c#仿ppt案例
画曲线 namespace ppt2024 {public partial class Form1 : Form{public Form1(){InitializeComponent();}//存放所有点的位置信息List<Point> lstPosition new List<Point>();//控制开始画的时机bool isDrawing false;//鼠标点击开始画private void Form1_MouseD…...
10.图像高斯滤波的原理与FPGA实现思路
1.概念 高斯分布 图像滤波之高斯滤波介绍 图像处理算法|高斯滤波 高斯滤波(Gaussian filter)包含很多种,包括低通、高通、带通等,在图像上说的高斯滤波通常是指的高斯模糊(Gaussian Blur),是一种高斯低通滤波。通常这个算法也可以用来模…...
WebGIS 地铁交通线网 | 图扑数字孪生
数字孪生技术在地铁线网的管理和运维中的应用是一个前沿且迅速发展的领域。随着物联网、大数据、云计算以及人工智能技术的发展,地铁线网数字孪生在智能交通和智慧城市建设中的作用日益凸显。 图扑软件基于 HTML5 的 2D、3D 图形渲染引擎,结合 GIS 地图…...
Docker 哲学 - push 本机镜像 到 dockerhub
注意事项: 1、 登录 docker 账号 docker login 2、docker images 查看本地镜像 3、注意的是 push镜像时 镜像的tag 需要与 dockerhub的用户名保持一致 eg:本地镜像 express:1 直接 docker push express:1 无法成功 原因docker不能识别 push到哪里 …...
大数据学习第十二天(hadoop概念)
1、服务器之间数据文件传递 1)服务器之间传递数据,依赖ssh协议 2)http协议是web网站之间的通讯协议,用户可已通过http网址访问到对应网站数据 3)ssh协议是服务器之间,或windos和服务器之间传递的数据的协议…...
管理科学笔记
1.线性规划 画出区域,代入点计算最大最小值 2.最小生成树 a.断线法,从大的开始断 b.选择法,从小的开始选 3.匈牙利法 维度数量直线覆盖所有的0 4.一直选最当前路线最短路径 5.线性规划 6.决策论...
WebKit结构简介
WebKit是一款开源的浏览器引擎,用于渲染网页内容。它负责将HTML、CSS和JavaScript等网络资源转换为用户在屏幕上看到的图形界面。WebKit是一个跨平台的引擎,可以在多种操作系统上运行,如Windows、macOS、Linux等。 以下是一篇关于WebKit结构…...
Kaggle:收入分类
先看一下数据的统计信息 import pandas as pd # 加载数据(保留原路径,但在实际应用中建议使用相对路径或环境变量) data pd.read_csv(r"C:\Users\11794\Desktop\收入分类\training.csv", encodingutf-8, encoding_errorsrepl…...
【Go】十七、进程、线程、协程
文章目录 1、进程、线程2、协程3、主死从随4、启动多个协程5、使用WaitGroup控制协程退出6、多协程操作同一个数据7、互斥锁8、读写锁9、deferrecover优化多协程 1、进程、线程 进程作为资源分配的单位,在内存中会为每个进程分配不同的内存区域 一个进程下面有多个…...
深入剖析JavaScript中的this(上)
在Javascript中,this 关键字是一个非常重要的概念,this这个关键字可以说是很常见也用的很多,说它简单也很简单,说它难也很难。我们经常会用到this,也经常会因为this头疼,是一个经常被误解和误用的概念&…...
Junit深入讲解(JAVA单元测试框架)
1、此处用的是Junit5,此处pom文件需要引的依赖是 <dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><version>5.9.1</version><scope>test</scope></depende…...
Spring boot如何执行单元测试?
Spring Boot 提供了丰富的测试功能,主要由以下两个模块组成: spring-boot-test:提供测试核心功能。spring-boot-test-autoconfigure:提供对测试的自动配置。 Spring Boot 提供了一个 spring-boot-starter-test一站式启动器&…...
Django详细教程(一) - 基本操作
文章目录 前言一、安装Django二、创建项目1.终端创建项目2.Pycharm创建项目(专业版才可以)3.默认文件介绍 三、创建app1.app介绍2.默认文件介绍 四、快速上手1.写一个网页步骤1:注册app 【settings.py】步骤2:编写URL和视图函数对…...
Qt编译QScintilla(C++版)过程记录,报错-lqscintilla2_qt5d、libqscintilla2_qt5找不到问题解决
Qt编译QScintilla [C版] 过程记录 本文是编译该 QScintilla 组件库供 QtCreater 开发 C 桌面软件 流程记录一、编译环境 系统: Windows 10Qt:Qt 5.14.2编译套件:MinGW 64Qscintilla:QScintilla_src-2.11.6 二、下载链接 网站链…...
android QtScrcpy 共享屏幕 获取本地Address
android QtScrcpy https://gitee.com/B arryda/QtScrcpy scrcpy - 手机无线投屏到电脑 https://zhuanlan.zhihu.com/p/80264357?utm_sourcewechat_session public String getLocalIpAddress() { String ipv4; List<NetworkInterface> nilist …...
【SQL Server】1. 认识+使用
1. 创建数据库的默认存储路径 C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Microsoft SQL Server 2008 R2 当我们选择删除数据库时,对应路径下的文件也就删除了 2. 导入导出数据工具的路径 3. 注册数据库遇到的问题 ??? 目前的问题就是服务器新建…...
视频汇聚/安防监控/视频存储EasyCVR平台EasyPlayer播放器更新:新增【性能面板】
视频汇聚/安防监控/视频存储平台EasyCVR基于云边端架构,可以在复杂的网络环境中快速、灵活部署,平台视频能力丰富,可以提供实时远程视频监控、视频录像、录像回放与存储、告警、语音对讲、云台控制、平台级联、磁盘阵列存储、视频集中存储、云…...
图神经网络实战(7)——图卷积网络(Graph Convolutional Network, GCN)详解与实现
图神经网络实战(7)——图卷积网络详解与实现 0. 前言1. 图卷积层2. 比较 GCN 和 GNN2.1 数据集分析2.2 实现 GCN 架构 小结系列链接 0. 前言 图卷积网络 (Graph Convolutional Network, GCN) 架构由 Kipf 和 Welling 于 2017 年提出,其理念是…...
大话设计模式之外观模式
外观模式(Facade Pattern)是一种软件设计模式,旨在提供一个简单的接口,隐藏系统复杂性,使得客户端能够更容易地使用系统。这种模式属于结构型模式,它通过为多个子系统提供一个统一的接口,简化了…...
CAD Plant3D 2024 下载地址及安装教程
CAD Plant3D是一款专业的三维工厂设计软件,用于在工业设备和管道设计领域进行建模和绘图。它是Autodesk公司旗下的AutoCAD系列产品之一,专门针对工艺、石油、化工、电力等行业的设计和工程项目。 CAD Plant3D提供了一套丰富的工具和功能,帮助…...
一个数据库怎么做二个网站/百度收录技术
今天终于考完了70-528,长长舒口气 呵呵,可以安安心心的回国度假了。这次考试真是一波三折啊。下面先说说考试过程 一个月前开始准备考MCTS,但是当时只是似懂非懂这个东西,一直都觉得可有可无,所以当时也没有太放在心上。天天70-536的Training…...
手机wap网站模板/seo推广费用需要多少
seayehin 实现结果 var arr [1, 2, 3, 4, 5]; 删除 arr 的第一个元素,不修改 arr。 返回新的数组 newArr newArr [2, 3, 4, 5]; 方法 1、slice() 浅克隆去复制 arr 元素从第二个开始到最后一个 var arr [1, 2, 3, 4, 5]; var newArr arr.slice(1); consol…...
百度网站怎么优化排名/seo推广的公司
组件的生命周期一、引出生命周期二、生命周期流程图(旧16.x)三、生命周期流程图(新 17.x)四、生命周期总结一、引出生命周期 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8&qu…...
建设一个购物网站要多少钱/china东莞seo
作者|硬糖君直播带货无疑是2020年最火爆的行业,但我们日常说起直播带货,往往只会讨论明星、主播等主角。殊不知,主角丰满、配角出彩那才算好戏。正如当初的李佳琦及“小助理”付鹏靠默契配合吸粉无数,一路扶摇直上。放眼如今的直播…...
手机做网站服务器吗/短视频获客系统
在子线程中new一个Handler为什么会报以下错误? java.lang.RuntimeException: Cant create handler inside thread that has not called Looper.prepare() 这是因为Handler对象与其调用者在同一线程中,如果在Handler中设置了延时操作,则调用…...
手机网站制作公司 广州/免费影视软件靠什么赚钱
医学影像诊断包括X线、CT、MRI、超声等,是重要的临床诊断方法之一。为了达到正确诊断,临床医生必须遵循一定的诊断原则和步骤,才能全面、客观地作出结论。今天给大家带来详细的诊断步骤、技巧与要点,真的学习借鉴&…...