b2c 网站导航栏设计/最近几天的新闻
使用简单的代码逻辑,理一理实现逻辑
为了方便理解,案例中,没有使用虚拟dom和抽象语法树,是通过直接操作dom来实现的
1.模板语法
先看一个简单的实现:
this.compile( this.$el );
- 执行模板编译,
- 如果是文本节点,且有{{}}模板语法,则取$data中的值进行数据替换
- 如果是元素节点 ,继续递归判断
大概就是以此来实现modal中的数据,渲染到View中
html:
<body>
<div id='app'><h1> {{ str }} </h1>{{ str }}<p>{{b}}</p>
</div>
<script type="text/javascript" src='vue.js'></script>
<script type="text/javascript">
new Vue({el:'#app',data : {str:'你好',b:'这也是data的数据'}
})
</script>
</body>
vue.js
class Vue{constructor( options ){// 获取到#appthis.$el = document.querySelector(options.el);// 获取到data数据this.$data = options.data;// 执行模板解析this.compile( this.$el );}compile( node ){node.childNodes.forEach((item,index)=>{// 如果是元素节点 说明还有子,继续递归if( item.nodeType == 1 ){this.compile( item );}// 如果是文本节点,如果有{{}}就替换成数据if( item.nodeType == 3 ){//正则匹配{{}}let reg = /\{\{(.*?)\}\}/g;let text = item.textContent;//给节点赋值item.textContent = text.replace(reg,(match,vmKey)=>{// 排除空格 拿到属性名称vmKey = vmKey.trim();//属性名称 在$data中取值return this.$data[vmKey];})}})}
}
页面显示如下 ,替换了{{}}中的数据
2.生命周期执行顺序:
在编写代码时,不管外面怎么写顺序,内部生命周期执行顺序是固定的,不受顺序影响
class Vue{constructor( options ){// 1.执行beforeCreate 并绑定thisif( typeof options.beforeCreate == 'function' ){options.beforeCreate.bind(this)();}// 挂载data 从这里之后可以获取数据 this.$data值this.$data = options.data;// 2.执行created 并绑定thisif( typeof options.created == 'function' ){options.created.bind(this)();}// 3.执行beforeMount并绑定thisif( typeof options.beforeMount == 'function' ){options.beforeMount.bind(this)();}//挂载 节点 从这里之后可以获取dom this.$el值this.$el = document.querySelector(options.el);// 4.执行mounted 并绑定thisif( typeof options.mounted == 'function' ){options.mounted.bind(this)();}// 这里之后可与获取 this.$data值 和 this.$el值}
}
3.添加事件
模板编译过程中,判断元素节点是否有@click
,@change
…事件属性,有则addEventListener添加对应事件,当触发addEventListener的时候,执行绑定方法,一般方法在methods中会定义。
class Vue{constructor( options ){this.$options = options;if( typeof options.beforeCreate == 'function' ){options.beforeCreate.bind(this)();}this.$data = options.data;if( typeof options.created == 'function' ){options.created.bind(this)();}if( typeof options.beforeMount == 'function' ){options.beforeMount.bind(this)();}this.$el = document.querySelector(options.el);//模版解析this.compile( this.$el );if( typeof options.mounted == 'function' ){options.mounted.bind(this)();}}compile( node ){node.childNodes.forEach((item,index)=>{//元素节点if( item.nodeType == 1 ){// 判断元素节点是否绑定了@clickif( item.hasAttribute('@click') ){// @click后绑定的属性名称let vmKey = item.getAttribute('@click').trim();item.addEventListener('click',( event )=>{// 查找method里面的方法 并挂载事件this.eventFn = this.$options.methods[vmKey].bind(this);// 点击后 执行方法this.eventFn(event);})}if( item.childNodes.length > 0 ){this.compile( item );}}//这是文本节点,如果有{{}}就替换成数据if( item.nodeType == 3 ){//正则匹配{{}}let reg = /\{\{(.*?)\}\}/g;let text = item.textContent;//给节点赋值item.textContent = text.replace(reg,(match,vmKey)=>{vmKey = vmKey.trim();return this.$data[vmKey];})}})}
}
4. 数据劫持
Object.defineProperty是 JavaScript 中的一个方法,用于在一个对象上定义一个新属性,或者修改一个现有属性的配置。
它接受三个主要参数:要定义属性的对象、属性名称(作为字符串)和一个包含属性描述符的对象。
let obj = {};
Object.defineProperty(obj, 'name', {value: 'John',writable: true,enumerable: true,configurable: true
});
console.log(obj.name); // 输出: John
先看一个简单的实现:
class Vue{constructor( options ){this.$options = options;if( typeof options.beforeCreate == 'function' ){options.beforeCreate.bind(this)();}// 这是datathis.$data = options.data;// 处理数据this.proxyData();if( typeof options.created == 'function' ){options.created.bind(this)();}if( typeof options.beforeMount == 'function' ){options.beforeMount.bind(this)();}this.$el = document.querySelector(options.el);if( typeof options.mounted == 'function' ){options.mounted.bind(this)();}}//1、给Vue大对象赋属性,来自于data中//2、data中的属性值和Vue大对象的属性保持双向(劫持)proxyData(){for( let key in this.$data ){Object.defineProperty(this,key,{get(){// 取值劫持return this.$data[key];},set( val ){// 设置值劫持this.$data[key] = val;}})}}
}
5. 依赖收集
Dep:依赖收集器类的简单结构示例,用于依赖收集和通知更新
class Dep {constructor() {this.subs = [];}addSub(watcher) {this.subs.push(watcher);}notify() {this.subs.forEach(watcher => {watcher.update();});}
}
function defineReactive (obj, key, val) {var dep = new Dep();Object.defineProperty(obj, key, {enumerable: true,configurable: true,get: function () {if (Dep.target) {// 依赖收集dep.addSub(Dep.target);}return val;},set: function (newVal) {if (newVal === val) return;val = newVal;dep.notify();}});
}
上溯代码中, if (Dep.target) 为ture
,才会依赖收集,那什么时候 if (Dep.target) 为ture?
只有当 模板渲染场景
计算属性场景computed
监听器场景watch
情况下才会创建一个watcher ,调用watcher.get
获取数据,把watcher实例赋值给Dep.target
,触发依赖收集。
模板渲染场景:1.插值表达式 {{}}2.指令绑定条件 v-bind:class="activeClass"3.循环指令 v-if v-for
例如:下面是一个模板渲染场景的插值表达式
情况,生成watcher,第三个参数是是监听到更改值的时候,调用的函数。
function generateRenderFunction(ast) {// 遍历节点ast.nodes.forEach(node => {if (node.type === 'Interpolation') {let propertyName = node.content;let watcher = new Watcher(vm, propertyName, () => {// 当数据变化时更新节点内容updateNode(node, vm[propertyName]);});}});
}
Watcher.prototype.get = function () {// Dep.target 表是当前是有监听的Dep.target = this;// 然后去取值 走到defineProperty中的get方法中,判断 Dep.target不为空,依赖收集var value = this.getter.call(this.vm);// 依赖收集后,清空 Dep.targetDep.target = null;// 返回value值return value;
};
6. 视图更新
1.模板编译基础
在 Vue 2 中,模板编译主要分为三个阶段: 解析(parse)、优化(optimize)和代码生成(codegen)。
在解析阶段,会将模板字符串转换为抽象语法树(AST),这个 AST 包含了模板中的各种元素、指令和插值等信息。
2.解析阶段添加Watcher的线索
当解析到模板中的插值表达式(如{{ message }})或指令(如v - bind、v - model等)时,编译器会识别出对数据属性的使用。
编译器会为插值表达式创建一个对应的 AST 节点,并且在这个节点中记录下需要获取的数据属性。
例如
{type: 'Interpolation',content: 'message'
}
3.从 AST 到Watcher的创建
在代码生成阶段,编译器会根据 AST 生成渲染函数(render函数),
在这个过程中,对于每个与数据属性相关的 AST 节点,会创建一个Watcher实例来监听对应的数据变化。
function generateRenderFunction(ast) {// 遍历AST节点ast.nodes.forEach(node => {//发现是{{}} 插值表达式if (node.type === 'Interpolation') {let propertyName = node.content;// 生成watcherlet watcher = new Watcher(vm, propertyName, () => {// 当数据变化时更新节点内容updateNode(node, vm[propertyName]);});}});// 根据AST和创建的Watcher等生成完整的渲染函数
}
- 当发现类型为Interpolation的节点(插值表达式)时,会提取出相关的数据属性名(propertyName),然后创建一个Watcher实例。
- 这个Watcher的getter函数会获取对应的vm[propertyName]的值,并且在数据变化时,会执行一个回调函数来更新对应的节点内容(updateNode函数,这里假设它用于更新节点)。
Watcher 内容:
function Watcher (vm, expOrFn, cb, options) {this.vm = vm;this.getter = parsePath(expOrFn);this.value = this.get();
}
Watcher.prototype.get = function () {// Dep.target 表是当前是有监听的Dep.target = this;var value = this.getter.call(this.vm);Dep.target = null;return value;
};
Watcher.prototype.update = function () {// 处理更新逻辑,可能是异步或同步更新if (this.lazy) {this.dirty = true;} else if (this.sync) {this.run();} else {queueWatcher(this);}
};
Watcher.prototype.run = function () {var value = this.get();var oldValue = this.value;this.value = value;if (this.cb) {this.cb.call(this.vm, value, oldValue);}
};
7、虚拟 DOM 和 真实DOM(概念、作用)
1.1 概念
真实 DOM(Document Object Model):是浏览器中用于表示文档结构的树形结构。
<h2>你好</h2>
虚拟DOM:用 JavaScript 对象来模拟真实 DOM 的结构
{children: undefineddata: {}elm: h1key: undefinedsel: "h1"text: "你好h1"
}
步骤
1.用JS对象表示真实的DOM结构,生成一个虚拟DOM,再用虚拟DOM构建一个真实DOM树,渲染到页面
2.状态改变生成新的虚拟DOM,与旧的虚拟DOM进行比对,比对的过程就是DIFF算法,利用patch记录差异
3.把记录的差异用在第一个虚拟DOM生成的真实DOM上,视图就更新了。
(Vue.js 在早期开发过程中借鉴了 Snabbdom 的设计理念来构建自己的虚拟 DOM 系统)
1.2 作用
性能优化方面
真实DOM
- 当直接操作真实 DOM 时,比如频繁地添加、删除或修改节点,会引起浏览器的重排(reflow)和重绘(repaint)。
- 重排: DOM 结构的改变导致浏览器重新计算元素的几何属性,如位置、大小等;
- 重绘:元素的外观发生改变,如颜色、背景等变化,只是重新绘制外观而不涉及布局调整。
虚拟DOM
- 通过一种高效的 Diff 算法比较新旧虚拟 DOM 树的差异,可以快速地找出需要更新的部分,而不是每次都对整个 DOM 进行重新渲染。
- 虚拟 DOM 的操作在 JavaScript 层面进行,比直接操作真实 DOM 快得多
- 当组件的数据发生变化时,Vue.js 会收集一段时间内的数据变化,然后统一进行虚拟 DOM 的更新和差异比较,并根据差异更新真实 DOM,避免大量的无谓计算。
8、Diff 算法
(源码地址)
它的主要作用是比较新数据与旧数据虚拟 DOM 树的差异,从而找出需要更新的部分,以便将这些最小化的变更应用到真实 DOM上,减少不必要的 DOM 操作,提高性能。
- 首先sameVNode 比较一下新旧节点是不是同一个节点(同级对比,不跨级)
下图比较第二层级的右侧,左边是P,右边是div, 那么会认为这两个节点完全不同,直接删除旧的p替换新的div。
因为 dom 节点做跨层级移动的情况还是比较少的,一般情况下都是同一层级的 dom 的增删改。
但是 diff 算法除了考虑本身的时间复杂度之外,还要考虑一个因素:dom 操作的次数。
如果是一个list数组,新旧节点只是前后顺序的改变,直接删除新增,dom渲染成本会增加。
2.当节点类型相同的时候,Diff 算法会比较节点的属性是否有变化。如果属性有变化,就更新真实 DOM 节点的属性。
例如input节点,旧虚拟 DOM 中的value属性为abc,新虚拟 DOM 中的value属性为def,Diff 算法会更新真实 DOM 中input节点的value属性。
3.当节点类型,属性都相同,则比较是否存在子节点,
4.如果新节点和老节点都有子节点,需要进一步比较(双端diff核心updateChildren)
- diff 算法我们从一端逐个处理的,叫做简单 diff 算法。简单 diff 算法其实性能不是最好的,比如旧的 vnode 数组是 ABCD,新的 vnode 数组是 DABC,按照简单 diff 算法,A、B、C 都需要移动。
那怎么优化这个算法呢?
- vue使用的是双端 diff 算法:是头尾指针向中间移动,分别判断头尾节点是否可以复用,如果没有找到可复用的节点再去遍历查找对应节点的下标,然后移动。全部处理完之后也要对剩下的节点进行批量的新增和删除。
开启一个循环,循环的条件就是 oldStart 不能大于oldEnd ,newStart不能大于newEnd,以下是循环的重要判断
- 跳过undefined
**if (isUndef(oldStartVnode))**
为什么会有undefined,老节点移动过程中,会产生undefined占位,之后的流程图会说明清楚。这里只要记住,如果旧开始节点为undefined,就后移一位;如果旧结束节点为undefined,就前移一位。
- 快捷对比(https://www.jianshu.com/p/b9916979a740
)**4个 else if(sameVnode(xxx))**
1
新开始和旧开始节点比对 如果匹配,表示它们位置都是对的,Dom不用改,就将新、旧节点开始的下标往后移一位即可。
2
旧结束和新结束节点比对 如果匹配,也表示它们位置是对的,Dom不用改,就将新、旧节点结束的下标前移一位即可。
3
旧开始和新结束节点比对 如果匹配,位置不对需要更新Dom视图,将旧开始节点对应的真实Dom插入到最后一位,旧开始节点下标后移一位,新结束节点下标前移一位。
4
旧结束和新开始节点比对 如果匹配,位置不对需要更新Dom视图,将旧结束节点对应的真实Dom插入到旧开始节点对应真实Dom的前面,旧结束节点下标前移一位,新开始节点下标后移一位。
- key值查找(2.快捷对比都不满足的情况下)
**}else {**
将旧节点数组剩余的vnode(oldStartIdx到oldEndIdx之间的节点)进行一次遍历,生成由vnode.key作为键,idx索引作为值的对象oldKeyToIdx,然后遍历新节点数组的剩余vnode(newStartIdx 到 newEndIdx 之间的节点),根据新的节点的key在oldKeyToIdx进行查找。
1
找到相同的key
- 如果和已有key值匹配 那就说明是已有的节点,只是位置不对,则将找到的节点插入到 oldStartIdx 对应的 vnode 之前;并且,这里会将旧节点数组中 idxInOld 对应的元素设置为 undefined。
- 如果和已有key值不匹配,那就说明是新的节点,那就创建一个对应的真实Dom节点,插入到旧开始节点对应的真实Dom前面即可
2
没有相同key
- 没有找到对应的索引,则直接createElm创建新的dom节点并将新的vnode插入 oldStartIdx 对应的 vnode 之前。
以上是while内部处理,以下是while外部处理
- 剩余元素处理(不满足循环条件后退出,循环外处理剩余元素)
循环外
旧节点数组遍历结束、新节点数组仍有剩余
,经过两端对比查找都没有查找到,则说明新插入内容是处于 oldstartIdx与 oldEndIdx 之间的,所以可以直接在 newEndIdx 对应的 vnode 之前创建插入新节点即可。新节点数组遍历结束、旧节点数组仍有剩余
,则遍历旧节点oldStartIdx 到 oldEndIdx 之间的剩余数据,进行移除
因为旧节点oldStartIdx之前的数据和 oldEndIdx之后的数据都是对比确认之后的,且数量与新节点数组相同,则中间剩下的都是要删除的节点
以上便是vue2的diff的核心流程了,具体案例参考这里
什么是MVVM
1.概念
它主要目的是分离用户界面(View)和业务逻辑(Model),并通过一个中间层(ViewModel)来进行数据绑定和交互。
这种模式能够使代码更加清晰、易于维护和扩展。
- M: Model 主要代表应用程序的数据和业务逻辑;这包括像数据对象,如用户信息、产品列表;
- V:View 是用户直接看到和交互的界面部分;通常是指组件中的 template 标签内的 HTML 内容, style 标签内的 CSS
样式也属于视图。- VM:ViewModel 是连接 Model 和 View 的桥梁。像data函数(它返回数据对象)、computed属性、methods以及生命周期钩子都属于 ViewModel(vue源码)
- MVVM 模式的优势在于它能够很好地分离,这使得代码的维护和扩展变得更加容易。
- 开发人员专注于 Model 的业务逻辑,设计人员专注于 View 的界面设计, ViewModel 则负责两者之间的沟通和协调。
例如,当业务逻辑发生变化,如待办事项的完成状态需要增加一个审核流程,我们只需要在 Model 部分修改相关的数据结构和处理函数,而不会影响到视图的展示逻辑。同样,如果要改变视图的外观,如将待办事项列表从无序列表改为表格形式,只要修改
View 部分的 HTML 和 CSS,而不需要大量改动业务逻辑部分。这种分离使得团队协作更加高效,也提高了代码的可复用性和可测试性。
web1.0时代
文件全在一起,也就是前端和后端的代码全在一起:
1、前端和后端都是一个人开发。(技术没有侧重点或者责任不够细分)
2、项目不好维护。
3、html、css、js页面的静态内容没有,后端是没办法工作的(没办法套数据)mvc…都是后端先出的
web2.0时代
ajax出现了,就可以:前端和后数据分离了 解决问题:
后端不用等前端页面弄完没,后端做后端的事情(写接口)、前布局、特效、发送请求问题:
1、html、c5s、js都在一个页面中,单个页面可能内容也是比较多的(也会出现不好维护的情况)
MVC、MVVM 前端框架
解决问题:可以把一个"特别大”页面,进行拆分(组件化),单个组件进行维护
相关文章:

Vue2 常见知识点(二)
使用简单的代码逻辑,理一理实现逻辑 为了方便理解,案例中,没有使用虚拟dom和抽象语法树,是通过直接操作dom来实现的 1.模板语法 先看一个简单的实现: this.compile( this.$el ); 执行模板编译,如果是文本…...

SAP-ABAP开发-第二代增强示例
CUSTOMER EXIT 以VA01为例 目录 一、查找出口 二、出口对象 三、销售订单的增强 一、查找出口 ①查找事务代码的主程序 ②搜索CALL CUSTOMER-FUNCTION SE37下查看函数 函数名称命名规则:EXIT_<程序名>_<序号> ③使用函数查找:MODX_FU…...

UDP 协议与端口绑定行为解析:理解 IP 地址和端口的绑定规则
UDP 协议与端口绑定行为解析:理解 IP 地址和端口的绑定规则 1. UDP 协议与端口绑定基础2. UDP 端口绑定行为与示例3. 关键结论:占有权与消息接收权4. 异常现象:多个程序绑定 0.0.0.0:80805. 端口共享与操作系统的行为差异6. 实践建议与最佳实践7. 总结在网络通信中,UDP(用…...

【Vue3】【Naive UI】<n-message>标签
【Vue3】【Naive UI】标签 content (String | VNode) 【VUE3】【Naive UI】<NCard> 标签 【VUE3】【Naive UI】<n-button> 标签 【VUE3】【Naive UI】<a> 标签 【VUE3】【Naive UI】<NDropdown&…...

C++ 变量和常量:开启程序构建之门的关键锁钥与永恒灯塔
目录 一、变量 1.1 变量的创建 1.2 变量的初始化 1.3 变量的分类 1.4 变量的初始化 二、常量 2.1 字面常量 2.2 #define定义常量 2.3 const 定义常量 一、变量 1.1 变量的创建 data_type name; | | | | 数据类型 变量名 ------------- int age; //整型变量 char ch; …...

Linux部分实用操作
目录 1、快捷键 2、软件安装 3、systemctl 4、ln命令创建软连接 5、IP地址 6、主机名 7、域名解析 8、网络传输 ping wget curl命令 9、端口 10、进程 11、主机状态 查看系统资源占用--top 磁盘信息监控--df--iostat 网络状态监控--sar -n DEV 12、环境…...

Linux笔记---进程:进程地址空间
1. 地址空间 程序地址空间是指程序在执行期间可以访问的内存范围。它由操作系统为每个进程分配,以确保进程之间不会相互干扰。地址空间包含了程序所需的所有内存区域,包括代码、已初始化和未初始化的数据、堆(heap)、栈ÿ…...

flutter in_app_purchase google支付 PG-GEMF-01错误
问题:PG-GEMF-01错误 flutter 使用in_app_purchase插件升降级订阅时报错PG-GEMF-01。 解决方案: 升降级订阅时,确保不调用 MethodCallHandlerImpl.java文件中的 setObfuscatedAccountId()方法、setObfuscatedProfileId()方法 原因…...

“精神内耗”的神经影像学证据:担忧和反刍会引发相似的神经表征
摘要 重复性消极思维(RNT)包括面向未来的担忧和面向过去的反刍,两者在认知和情感上具有相似的特征。这些不同但相关的过程在大多程度上会激活重叠的神经结构尚不确定,因为大多数神经科学研究只单独研究担忧或反刍。为了解决这个问题,本研究使…...

Linux--Debian或Ubuntu上扩容、挂载磁盘并配置lvm
一、三块12TB组RAID 5 可用容量约24TB 二、安装LVM工具(已安装请忽略) sudo apt-get install lvm2二、查看可用磁盘 sudo lsblk 或者 sudo fdisk -l三、创建物理卷(PV) 选中刚做的磁盘组 sudo pvcreat /dev/sdb1四、创建卷组…...

【k8s】kubelet 的相关证书
在 Kubernetes 集群中,kubelet 使用的证书通常存放在节点上的特定目录。这些证书用于 kubelet 与 API 服务器之间的安全通信。具体的位置可能会根据你的 Kubernetes 安装方式和配置有所不同,下图是我自己环境【通过 kubeadm 安装的集群】中的kubelet的证…...

01-树莓派基本配置-基础配置配置
树莓派基本配置 文章目录 树莓派基本配置前言硬件准备树莓派刷机串口方式登录树莓派接入网络ssh方式登录树莓派更换国内源xrdp界面登录树莓派远程文件传输FileZilla 前言 树莓派是一款功能强大且价格实惠的小型计算机,非常适合作为学习编程、物联网项目、家庭自动化…...

【Windows 11专业版】使用问题集合
博文将不断学习补充 I、设置WIN R打开应用默认使用管理员启动 1、WIN R输入 secpol.msc 进入“本地安全策略”。 2、按照如下路径,找到条目: “安全设置”—“本地策略”—“安全选项”—“用户账户控制:以管理员批准模式运行所有管理员” …...

前端 vue3 + element-plus + ts 组件通讯,defineEmits,子传父示例
父组件: 子组件:...

【Django-xadmin】
时间长不用,会忘的系列 1、Django-xadmin后台字段显示处理 主要是修改每个模块下adminx.py文件 代码解释:第1行控制表单字段显示第2行控制列表字段显示第3行控制搜索条件第4行控制过滤条件第5行支持单个或多个字段信息修改第6行列表分页,每页显示多少行…...

Ubuntu24.04初始化教程(包含基础优化、ros2)
将会不断更新。但是所有都是基础且必要的操作。 为重装系统之后的环境配置提供便捷信息来源。记录一些错误的解决方案。 目录 构建系统建立系统备份**Timeshift: 系统快照和备份工具****安装 Timeshift****使用 Timeshift 创建快照****还原快照****自动创建快照** 最基本配置换…...

45 基于单片机的信号选择与温度变化
目录 一、主要功能 二、硬件资源 三、程序编程 四、实现现象 一、主要功能 基于51单片机,采用DS18B20检测温度,通过三种LED灯代表不同状态。 采用DAC0832显示信号脉冲,通过8位数码管显示温度。 信号脉冲可以根据两个按键分别调整为正弦…...

#JAVA-常用API-爬虫
1.爬虫 我们在正则表达式的讲解中可以使用字符串的方法materchs()来匹配,并且返回一个boolean值 String name "lshhhljh"; System.out.println(name.matches("lsh{3}\\s{3}")); //true现在我们将利用正则表达式来爬取本地或者网站上的文本内…...

Qt 面试题复习10~12_2024-12-2
Qt 面试题 28、Qt 如果一个信号的处理方法一直未被执行有哪些可能性29、Qt 三大核心机制30、虚函数表31、什么是Qt事件循环 ?32、纯虚函数和普通的虚函数有什么区别33、Qt 的样式表是什么?34、描述Qt的TCP通讯流程35、自定义控件流程36、什么是Qt的插件机…...

在OpenHarmony系统下开发支持Android应用的双框架系统
在 OpenHarmony 系统下开发支持 Android 应用的双框架系统,主要的目标是实现 OpenHarmony 本身作为底层操作系统,并通过兼容层或者桥接技术,允许 Android 应用在其上运行。双框架系统的架构设计会涉及到 OpenHarmony 和 Android 的结合&#…...

对力扣77组合优化的剪枝操作的理解
77. 组合 代码随想录放出了这一张图 我乍一看觉得想当然,但是仔细想想,又不知道以下剪枝代码作何解释,因此我想通过这篇文章简要解释一下 class Solution { private:vector<vector<int>> result;vector<int> path;void backtracking(int n, int k, int sta…...

SpringMVC中的Handler、HandlerMapping、HandlerAdapter
SpringMVC中的Handler、HandlerMapping、HandlerAdapter到底是啥 这东西,虽然说和我们的开发没啥关系,尤其是当你用SpringBoot进行开发时,这些接口离你越来越远了。讲实话,要不是这学期扫一眼学校的课件,我都不知道有这东西,这东西本来就是对使用框架进行开发的开发者隐藏…...

tomcat 8在idea启动控制台乱码
Tomcat 8在IntelliJ IDEA(简称IDEA)启动控制台出现乱码的问题,通常是由于Tomcat的默认编码格式(UTF-8)与IDEA或操作系统的默认编码格式(如GBK)不一致所导致的。以下是一些解决此问题的步骤&…...

windows下kafka初体验简易demo
这里提供了windows下的java1.8和kafka3.9.0版本汇总,可直接免费下载 【免费】java1.8kafka2.13版本汇总资源-CSDN文库 解压后可以得到一个文件夹 资料汇总内有一个kafka文件资料包.tgz,解压后可得到下述文件夹kafka_2.13-3.9.0,资料汇总内还…...

证明直纹极小曲面是平面或者正螺旋面.
目录 证明直纹极小曲面是平面或者正螺旋面 证明直纹极小曲面是平面或者正螺旋面 证明:设极小直纹面 S S S的参数表示为 r ( u , v ) a ( u ) v c ( u ) . (u,v)\mathbf{a}(u)v\mathbf{c}(u). (u,v)a(u)vc(u).则 r u a ′ v c ′ , r v c , r u ∧ r v a ′ ∧…...

matlab2024a安装
1.开始安装 2.点击安装 3.选择安装密钥 4.接受条款 5.安装密钥 21471-07182-41807-00726-32378-34241-61866-60308-44209-03650-51035-48216-24734-36781-57695-35731-64525-44540-57877-31100-06573-50736-60034-42697-39512-63953 6 7.选择许可证文件 8.找许可证文件 9.选…...

Observability:如何在 Kubernetes pod 中轻松添加应用程序监控
作者:来自 Elastic Jack Shirazi•Sylvain Juge•Alexander Wert Elastic APM K8s Attacher 允许将 Elastic APM 应用程序代理(例如 Elastic APM Java 代理)自动安装到 Kubernetes 集群中运行的应用程序中。该机制使用变异 webhook࿰…...

关于Nginx前后端分离部署spring boot和vue工程以及反向代理的配置说明
最近项目中用到关于Nginx前后端分离部署spring boot和vue工程以及反向代理的配置,总结了一下说明: 1、后端是spring boot工程,端口8000,通过 jar命令启动 nohup java -jar xxx-jsonflow-biz.jar > /usr/local/nohup.out 2>…...

redis渐进式遍历
文章目录 一. 渐进式遍历介绍二. scan命令 一. 渐进式遍历介绍 keys * , 一次性把整个redis中所有的key都获取到, 这个操作比较危险, 可能会阻塞redis服务器 通过渐进式遍历, 就可以做到, 既能够获取到所有的key, 又不会卡死服务器 渐进式遍历, 不是一个命令把所有key都拿到,…...

【C++】数据类型与操作实践:详细解析与优化
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯题目一:三个数的倒序输出1.1 题目描述与代码实现代码实现: 1.2 代码解析与细节说明1.3 使用 int 类型的合理性分析1.4 其他数据类型的考虑1.5 代码优…...