vue的双向绑定原理及实现
vue的双向绑定原理及实现
前言
使用vue也好有一段时间了,虽然对其双向绑定原理也有了解个大概,但也没好好探究下其原理实现,所以这次特意花了几晚时间查阅资料和阅读相关源码,自己也实现一个简单版vue的双向绑定版本,先上个成果图来吸引各位:
代码:
效果图:
是不是看起来跟vue的使用方式差不多?接下来就来从原理到实现,从简到难一步一步来实现这个SelfVue。由于本文只是为了学习和分享,所以只是简单实现下原理,并没有考虑太多情况和设计,如果大家有什么建议,欢迎提出来。
本文主要介绍两大内容:
- vue数据双向绑定的原理。
- 实现简单版vue的过程,主要实现{{}}、v-model和事件指令的功能。
相关代码地址:https://github.com/canfoo/self-vue
vue数据双向绑定原理
vue数据双向绑定是通过数据劫持结合发布者-订阅者模式的方式来实现的,那么vue是如果进行数据劫持的,我们可以先来看一下通过控制台输出一个定义在vue初始化数据上的对象是个什么东西。
代码:
var vm = new Vue({data: {obj: {a: 1}},created: function () {console.log(this.obj);}
});
结果:
我们可以看到属性a有两个相对应的get和set方法,为什么会多出这两个方法呢?因为vue是通过Object.defineProperty()来实现数据劫持的。
Object.defineProperty( )是用来做什么的?它可以来控制一个对象属性的一些特有操作,比如读写权、是否可以枚举,这里我们主要先来研究下它对应的两个描述属性get和set,如果还不熟悉其用法,请点击这里阅读更多用法。
在平常,我们很容易就可以打印出一个对象的属性数据:
var Book = {name: 'vue权威指南'
};
console.log(Book.name); // vue权威指南
如果想要在执行console.log(book.name)的同时,直接给书名加个书名号,那要怎么处理呢?或者说要通过什么监听对象 Book 的属性值。这时候Object.defineProperty( )就派上用场了,代码如下:
var Book = {}
var name = '';
Object.defineProperty(Book, 'name', {set: function (value) {name = value;console.log('你取了一个书名叫做' + value);},get: function () {return '《' + name + '》'}
})Book.name = 'vue权威指南'; // 你取了一个书名叫做vue权威指南
console.log(Book.name); // 《vue权威指南》
我们通过Object.defineProperty( )设置了对象Book的name属性,对其get和set进行重写操作,顾名思义,get就是在读取name属性这个值触发的函数,set就是在设置name属性这个值触发的函数,所以当执行 Book.name = ‘vue权威指南’ 这个语句时,控制台会打印出 “你取了一个书名叫做vue权威指南”,紧接着,当读取这个属性时,就会输出 “《vue权威指南》”,因为我们在get函数里面对该值做了加工了。如果这个时候我们执行下下面的语句,控制台会输出什么?
console.log(Book);
结果:
乍一看,是不是跟我们在上面打印vue数据长得有点类似,说明vue确实是通过这种方法来进行数据劫持的。接下来我们通过其原理来实现一个简单版的mvvm双向绑定代码。
思路分析
实现mvvm主要包含两个方面,数据变化更新视图,视图变化更新数据:
关键点在于data如何更新view,因为view更新data其实可以通过事件监听即可,比如input标签监听 ‘input’ 事件就可以实现了。所以我们着重来分析下,当数据改变,如何更新视图的。
数据更新视图的重点是如何知道数据变了,只要知道数据变了,那么接下去的事都好处理。如何知道数据变了,其实上文我们已经给出答案了,就是通过Object.defineProperty( )对属性设置一个set函数,当数据改变了就会来触发这个函数,所以我们只要将一些需要更新的方法放在这里面就可以实现data更新view了。
思路有了,接下去就是实现过程了。
实现过程
我们已经知道实现数据的双向绑定,首先要对数据进行劫持监听,所以我们需要设置一个监听器Observer,用来监听所有属性。如果属性发上变化了,就需要告诉订阅者Watcher看是否需要更新。因为订阅者是有很多个,所以我们需要有一个消息订阅器Dep来专门收集这些订阅者,然后在监听器Observer和订阅者Watcher之间进行统一管理的。接着,我们还需要有一个指令解析器Compile,对每个节点元素进行扫描和解析,将相关指令对应初始化成一个订阅者Watcher,并替换模板数据或者绑定相应的函数,此时当订阅者Watcher接收到相应属性的变化,就会执行对应的更新函数,从而更新视图。因此接下去我们执行以下3个步骤,实现数据的双向绑定:
-
实现一个监听器Observer,用来劫持并监听所有属性,如果有变动的,就通知订阅者。
-
实现一个订阅者Watcher,可以收到属性的变化通知并执行相应的函数,从而更新视图。
-
实现一个解析器Compile,可以扫描和解析每个节点的相关指令,并根据初始化模板数据以及初始化相应的订阅器。
流程图如下:
1.实现一个Observer
Observer是一个数据监听器,其实现核心方法就是前文所说的Object.defineProperty( )。如果要对所有属性都进行监听的话,那么可以通过递归方法遍历所有属性值,并对其进行Object.defineProperty( )处理。如下代码,实现了一个Observer。
function defineReactive(data, key, val) {observe(val); // 递归遍历所有子属性Object.defineProperty(data, key, {enumerable: true,configurable: true,get: function() {return val;},set: function(newVal) {val = newVal;console.log('属性' + key + '已经被监听了,现在值为:“' + newVal.toString() + '”');}});
}function observe(data) {if (!data || typeof data !== 'object') {return;}Object.keys(data).forEach(function(key) {defineReactive(data, key, data[key]);});
};var library = {book1: {name: ''},book2: ''
};
observe(library);
library.book1.name = 'vue权威指南'; // 属性name已经被监听了,现在值为:“vue权威指南”
library.book2 = '没有此书籍'; // 属性book2已经被监听了,现在值为:“没有此书籍”
思路分析中,需要创建一个可以容纳订阅者的消息订阅器Dep,订阅器Dep主要负责收集订阅者,然后再属性变化的时候执行对应订阅者的更新函数。所以显然订阅器需要有一个容器,这个容器就是list,将上面的Observer稍微改造下,植入消息订阅器:
function defineReactive(data, key, val) {observe(val); // 递归遍历所有子属性var dep = new Dep(); Object.defineProperty(data, key, {enumerable: true,configurable: true,get: function() {if (是否需要添加订阅者) {dep.addSub(watcher); // 在这里添加一个订阅者}return val;},set: function(newVal) {if (val === newVal) {return;}val = newVal;console.log('属性' + key + '已经被监听了,现在值为:“' + newVal.toString() + '”');dep.notify(); // 如果数据变化,通知所有订阅者}});
}function Dep () {this.subs = [];
}
Dep.prototype = {addSub: function(sub) {this.subs.push(sub);},notify: function() {this.subs.forEach(function(sub) {sub.update();});}
};
从代码上看,我们将订阅器Dep添加一个订阅者设计在getter里面,这是为了让Watcher初始化进行触发,因此需要判断是否要添加订阅者,至于具体设计方案,下文会详细说明的。在setter函数里面,如果数据变化,就会去通知所有订阅者,订阅者们就会去执行对应的更新的函数。到此为止,一个比较完整Observer已经实现了,接下来我们开始设计Watcher。
2.实现Watcher
订阅者Watcher在初始化的时候需要将自己添加进订阅器Dep中,那该如何添加呢?我们已经知道监听器Observer是在get函数执行了添加订阅者Wather的操作的,所以我们只要在订阅者Watcher初始化的时候出发对应的get函数去执行添加订阅者操作即可,那要如何触发get的函数,再简单不过了,只要获取对应的属性值就可以触发了,核心原因就是因为我们使用了Object.defineProperty( )进行数据监听。这里还有一个细节点需要处理,我们只要在订阅者Watcher初始化的时候才需要添加订阅者,所以需要做一个判断操作,因此可以在订阅器上做一下手脚:在Dep.target上缓存下订阅者,添加成功后再将其去掉就可以了。订阅者Watcher的实现如下:
function Watcher(vm, exp, cb) {this.cb = cb;this.vm = vm;this.exp = exp;this.value = this.get(); // 将自己添加到订阅器的操作
}Watcher.prototype = {update: function() {this.run();},run: function() {var value = this.vm.data[this.exp];var oldVal = this.value;if (value !== oldVal) {this.value = value;this.cb.call(this.vm, value, oldVal);}},get: function() {Dep.target = this; // 缓存自己var value = this.vm.data[this.exp] // 强制执行监听器里的get函数Dep.target = null; // 释放自己return value;}
};
这时候,我们需要对监听器Observer也做个稍微调整,主要是对应Watcher类原型上的get函数。需要调整地方在于defineReactive函数:
function defineReactive(data, key, val) {observe(val); // 递归遍历所有子属性var dep = new Dep(); Object.defineProperty(data, key, {enumerable: true,configurable: true,get: function() {if (Dep.target) {. // 判断是否需要添加订阅者dep.addSub(Dep.target); // 在这里添加一个订阅者}return val;},set: function(newVal) {if (val === newVal) {return;}val = newVal;console.log('属性' + key + '已经被监听了,现在值为:“' + newVal.toString() + '”');dep.notify(); // 如果数据变化,通知所有订阅者}});
}
Dep.target = null;
到此为止,简单版的Watcher设计完毕,这时候我们只要将Observer和Watcher关联起来,就可以实现一个简单的双向绑定数据了。因为这里没有还没有设计解析器Compile,所以对于模板数据我们都进行写死处理,假设模板上又一个节点,且id号为’name’,并且双向绑定的绑定的变量也为’name’,且是通过两个大双括号包起来(这里只是为了掩饰,暂时没什么用处),模板如下:
<body><h1 id="name">{{name}}</h1>
</body>
这时候我们需要将Observer和Watcher关联起来:
function SelfVue (data, el, exp) {this.data = data;observe(data);el.innerHTML = this.data[exp]; // 初始化模板数据的值new Watcher(this, exp, function (value) {el.innerHTML = value;});return this;
}
然后在页面上new以下SelfVue类,就可以实现数据的双向绑定了:
<body><h1 id="name">{{name}}</h1>
</body>
<script src="js/observer.js"></script>
<script src="js/watcher.js"></script>
<script src="js/index.js"></script>
<script type="text/javascript">var ele = document.querySelector('#name');var selfVue = new SelfVue({name: 'hello world'}, ele, 'name');window.setTimeout(function () {console.log('name值改变了');selfVue.data.name = 'canfoo';}, 2000);</script>
这时候打开页面,可以看到页面刚开始显示了是’hello world’,过了2s后就变成’canfoo’了。到这里,总算大功告成一半了,但是还有一个细节问题,我们在赋值的时候是这样的形式 ’ selfVue.data.name = ‘canfoo’ ’ 而我们理想的形式是’ selfVue.name = ‘canfoo’ '为了实现这样的形式,我们需要在new SelfVue的时候做一个代理处理,让访问selfVue的属性代理为访问selfVue.data的属性,实现原理还是使用Object.defineProperty( )对属性值再包一层:
function SelfVue (data, el, exp) {var self = this;this.data = data;Object.keys(data).forEach(function(key) {self.proxyKeys(key); // 绑定代理属性});observe(data);el.innerHTML = this.data[exp]; // 初始化模板数据的值new Watcher(this, exp, function (value) {el.innerHTML = value;});return this;
}SelfVue.prototype = {proxyKeys: function (key) {var self = this;Object.defineProperty(this, key, {enumerable: false,configurable: true,get: function proxyGetter() {return self.data[key];},set: function proxySetter(newVal) {self.data[key] = newVal;}});}
}
这下我们就可以直接通过’ selfVue.name = ‘canfoo’ '的形式来进行改变模板数据了。如果想要迫切看到现象的童鞋赶快来获取代码!
3.实现Compile
虽然上面已经实现了一个双向数据绑定的例子,但是整个过程都没有去解析dom节点,而是直接固定某个节点进行替换数据的,所以接下来需要实现一个解析器Compile来做解析和绑定工作。解析器Compile实现步骤:
-
解析模板指令,并替换模板数据,初始化视图
-
将模板指令对应的节点绑定对应的更新函数,初始化相应的订阅器
为了解析模板,首先需要获取到dom元素,然后对含有dom元素上含有指令的节点进行处理,因此这个环节需要对dom操作比较频繁,所有可以先建一个fragment片段,将需要解析的dom节点存入fragment片段里再进行处理:
function nodeToFragment (el) {var fragment = document.createDocumentFragment();var child = el.firstChild;while (child) {// 将Dom元素移入fragment中fragment.appendChild(child);child = el.firstChild}return fragment;
}
接下来需要遍历各个节点,对含有相关指定的节点进行特殊处理,这里咱们先处理最简单的情况,只对带有 ‘{{变量}}’ 这种形式的指令进行处理,先简道难嘛,后面再考虑更多指令情况:
function compileElement (el) {var childNodes = el.childNodes;var self = this;[].slice.call(childNodes).forEach(function(node) {var reg = /\{\{(.*)\}\}/;var text = node.textContent;if (self.isTextNode(node) && reg.test(text)) { // 判断是否是符合这种形式{{}}的指令self.compileText(node, reg.exec(text)[1]);}if (node.childNodes && node.childNodes.length) {self.compileElement(node); // 继续递归遍历子节点}});
},
function compileText (node, exp) {var self = this;var initText = this.vm[exp];this.updateText(node, initText); // 将初始化的数据初始化到视图中new Watcher(this.vm, exp, function (value) { // 生成订阅器并绑定更新函数self.updateText(node, value);});
},
function (node, value) {node.textContent = typeof value == 'undefined' ? '' : value;
}
获取到最外层节点后,调用compileElement函数,对所有子节点进行判断,如果节点是文本节点且匹配{{}}这种形式指令的节点就开始进行编译处理,编译处理首先需要初始化视图数据,对应上面所说的步骤1,接下去需要生成一个并绑定更新函数的订阅器,对应上面所说的步骤2。这样就完成指令的解析、初始化、编译三个过程,一个解析器Compile也就可以正常的工作了。为了将解析器Compile与监听器Observer和订阅者Watcher关联起来,我们需要再修改一下类SelfVue函数:
function SelfVue (options) {var self = this;this.vm = this;this.data = options;Object.keys(this.data).forEach(function(key) {self.proxyKeys(key);});observe(this.data);new Compile(options, this.vm);return this;
}
更改后,我们就不要像之前通过传入固定的元素值进行双向绑定了,可以随便命名各种变量进行双向绑定了:
<body><div id="app"><h2>{{title}}</h2><h1>{{name}}</h1></div>
</body>
<script src="js/observer.js"></script>
<script src="js/watcher.js"></script>
<script src="js/compile.js"></script>
<script src="js/index.js"></script>
<script type="text/javascript">var selfVue = new SelfVue({el: '#app',data: {title: 'hello world',name: ''}});window.setTimeout(function () {selfVue.title = '你好';}, 2000);window.setTimeout(function () {selfVue.name = 'canfoo';}, 2500);</script>
如上代码,在页面上可观察到,刚开始titile和name分别被初始化为 ‘hello world’ 和空,2s后title被替换成 ‘你好’ 3s后name被替换成 ‘canfoo’ 了。废话不多说,再给你们来一个这个版本的代码(v2),获取代码!
到这里,一个数据双向绑定功能已经基本完成了,接下去就是需要完善更多指令的解析编译,在哪里进行更多指令的处理呢?答案很明显,只要在上文说的compileElement函数加上对其他指令节点进行判断,然后遍历其所有属性,看是否有匹配的指令的属性,如果有的话,就对其进行解析编译。这里我们再添加一个v-model指令和事件指令的解析编译,对于这些节点我们使用函数compile进行解析处理:
function compile (node) {var nodeAttrs = node.attributes;var self = this;Array.prototype.forEach.call(nodeAttrs, function(attr) {var attrName = attr.name;if (self.isDirective(attrName)) {var exp = attr.value;var dir = attrName.substring(2);if (self.isEventDirective(dir)) { // 事件指令self.compileEvent(node, self.vm, exp, dir);} else { // v-model 指令self.compileModel(node, self.vm, exp, dir);}node.removeAttribute(attrName);}});
}
上面的compile函数是挂载Compile原型上的,它首先遍历所有节点属性,然后再判断属性是否是指令属性,如果是的话再区分是哪种指令,再进行相应的处理,处理方法相对来说比较简单,这里就不再列出来,想要马上看阅读代码的同学可以马上点击这里获取。
最后我们在稍微改造下类SelfVue,使它更像vue的用法:
function SelfVue (options) {var self = this;this.data = options.data;this.methods = options.methods;Object.keys(this.data).forEach(function(key) {self.proxyKeys(key);});observe(this.data);new Compile(options.el, this);options.mounted.call(this); // 所有事情处理好后执行mounted函数
}
这时候我们可以来真正测试了,在页面上设置如下东西:
<body><div id="app"><h2>{{title}}</h2><input v-model="name"><h1>{{name}}</h1><button v-on:click="clickMe">click me!</button></div>
</body>
<script src="js/observer.js"></script>
<script src="js/watcher.js"></script>
<script src="js/compile.js"></script>
<script src="js/index.js"></script>
<script type="text/javascript">new SelfVue({el: '#app',data: {title: 'hello world',name: 'canfoo'},methods: {clickMe: function () {this.title = 'hello world';}},mounted: function () {window.setTimeout(() => {this.title = '你好';}, 1000);}});</script>
是不是看起来跟vue的使用方法一样,哈,真正的大功告成!想要代码,直接点击这里获取!现象还没描述?直接上图!!!请观赏
其实这个效果图,就是本文开头贴出来的效果图了,前文说着要带着大家实现,所以就在这里把图再贴一次了,这叫首尾呼应嘛。
最后希望本文对你有帮助,如果有问题请留言一起探讨。
转载自:vue的双向绑定原理及实现
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- 虚拟机安装Ubuntu系统及Samba配置实现与Win10文件共享
材料:Window10+VMware+Ubuntu16.04+Samba Ubuntu16.04下载 VMware15安装包,提取码: rpak 目录①VMware的安装②虚拟机安装Ubuntu系统③虚拟机中Ubuntu系统的汉化及文件共享配置 ①VMware的安装 1.下载并运行exe文件进行安装;2.下载并运行KeyGen.exe;3.输入KeyGen.exe提供的…...
2024/5/3 20:46:08 - Comunion 区块链深度学习系列|区块链的发展历程
打开一切科学的钥匙都毫无异议地是问号,我们大部分的伟大发现都应当归功于如何?而生活的智慧大概就在于逢事都问个为什么? —— 巴尔扎克 之前写过一篇区块链新手学习要有系统性的文章,也有读者获取到了学习视频,但也有反映视频音质问题,故此将其拆分成单独的系列,以方便…...
2024/4/15 14:06:24 - 万字长文系统梳理C++函数指针
本篇的内容相对比较简单 主要从语法的层面讲解函数指针的使用以及应用场景。都是些面向入门者的基础,大佬轻喷。首先:什么是函数指针。 这个问题老生常谈了,不用理解的多么复杂,它其实就是一个特殊的指针,它用于指向函数被加载到的内存首地址,可用于实现函数调用。 听上有…...
2024/4/29 9:30:49 - js对象、原型、继承(学习篇)
想要搞清楚 原型、原型链、继承 这一堆概念之前首先要搞清楚 对象 是啥ECMAScript 中的对象其实就是一组数据和功能的集合。 ——— javascript 高级编程设计第三版对象是一种数据类型,js 中的数据类型分为 原始类型 和 引用类型,原始类型也叫基本类…...
2024/4/18 14:26:52 - 计算机网络08:因特网上的视频音频服务
文章目录8.1、概述8.2、流式存储音频/视频8.3、IP 电话计算机网络:因特网上的视频音频服务8.1、概述 计算机网络最初是为传送数据信息设计的。因特网 IP 层提供的“尽最大努力交付”服务,以及每一个分组独立交付的策略,对传送数据信息也是很合适的。 因特网使用的 TCP 协议可…...
2024/4/18 14:41:32 - SpringMVC基础知识(下篇)
一、处理JSON JSON知识:JSON 有两种格式:① Json 对象:{key:value,key:value…},②Json数组:[value1, value2…]Json 对象解析方式: 对象.key; Json 数组的解析方式:for循环遍历java对象转Json: ① Bean 和 map —》Json 对象;② List —》 json数组1、 返回JSON加…...
2024/4/17 22:28:04 - 过滤器--监听器(基本配置)
《过滤器》 1、实现javax.servlet.Filter接口 2、在web.xml中配置过滤器 <!-- Fillter --><filter><filter-name>myFilter</filter-name><filter-class>com.filter.MyFilter</filter-class></filter><filter-mapping><filt…...
2024/4/17 21:15:04 - 医院his源码,B/S医院管理系统源码 ASP.NET医院HIS源码 MVC医院系统源码
医院HIS源码,B/S医院管理系统源码 ASP.NET医院HIS源码 MVC医院系统源码大型his系统源码,适用在县乡一体化,医联体分级诊疗项目上本源码开发语言asp.net c#,数据库sqlserver2012,开发工具vs2015。技术框架mvc、ef等功能模块1.门诊建档2.门诊挂号3.门诊收费3.住院收费4.门诊…...
2024/4/15 19:41:41 - 零基础入门NLP - 新闻文本分类 | 天池 | Task6 基于深度学习的文本分类3
Transformer原理Transformer是在"Attention is All You Need"中提出的,模型的编码部分是一组编码器的堆叠(论文中依次堆叠六个编码器),模型的解码部分是由相同数量的解码器的堆叠。我们重点关注编码部分。他们结构完全相同,但是并不共享参数,每一个编码器都可以…...
2024/4/27 2:46:06 - 5G时代必备 音视频WebRTC实时互动直播技术入门与实战
5G时代必备 音视频WebRTC实时互动直播技术入门与实战 下载地址:百度云盘 5G时代下,音视频行业将会得到前所未有的蓬勃发展,音视频人才将成为新的宠儿。本课程将从入门到实战,系统讲解WebRTC实时互动直播技术【音视频领域核心技术】,让你低门槛进入音视频行业,快速成为企业…...
2024/4/24 8:59:01 - JavaScript基础复习
一、简介 JavaScript是一种专为网页交互而设计的脚本语言,由三个部分组成:ECMAScript,提供核心语言功能 DOM(文档对象模型),提供访问和操作网页内容的方法和接口 BOM(浏览器对象模型),提供与浏览器交互的方法和接口二、在HTML中使用JavaScript 1.<script>标签de…...
2024/5/3 20:06:58 - JavaScript王国的一次旅行,一个没有类的世界怎么玩转面向对象?
一、前言 作为Java 帝国的未来继承人,Java小王子受到了严格的教育, 不但精通Java语言、Java虚拟机、java类库和框架,还对各种官方的Java规范了如指掌。 近日他听说一个叫做Javascript的屌丝逆袭了, 成功地建立了一个独立的王国, 不但成了前端编程之王, 还不断地蚕食Java帝…...
2024/5/3 18:53:50 - 超快速ocr文字识别 mac版
text scanner功能介绍 1、【场景功能】1. 文字识别,识别图片上的文字2. 二维码识别3. 手写体识别4. 身份证识别5. 名片识别6. 银行卡识别7. 驾驶证识别8. 营业执照识别9. 增值税发票10. 表格识别2、【精准识别】自动精准识别图片,提供多种场景下精准的图像文字识别技术,让您…...
2024/5/3 12:06:38 - 【机器学习】算法总览及优先级
参考书目1:《机器学习》周志华,别称“西瓜书”①引言②模型评估选择③线性模型linear regression,logistic regression④决策树⑤NN:神经网络⑥SVM:支持向量机⑦贝叶斯分类器⑧集成学习 rf boosting⑨聚类⑩降维...回归\分类\无监督参考书目2:《统计学习方法》①引入②感…...
2024/4/19 0:34:05 - 过滤器--监听器
《过滤器》 1、实现javax.servlet.Filter接口 2、在web.xml中配置过滤器 <!-- Fillter --><filter><filter-name>myFilter</filter-name><filter-class>com.filter.MyFilter</filter-class></filter><filter-mapping><filt…...
2024/4/27 5:20:55 - 引入科研院所中科微研携手-林裕豪:从玉农业谋定农业大健康
引入科研院所中科微研携手-林裕豪:从玉农业谋定农业大健康新闻中国采编网 中国新闻采编网 谋定研究中国智库网 经信研究 国研智库 国情讲坛 万赢信采编:“科学技术是第一生产力。科技改变生活,这是当今科技迅速发展给人们的最大感受。”谋定研究农业大健康,全国工商联执委、…...
2024/4/17 12:17:58 - Java如何记录程序启动时间?
1、使用jre自带的ManagementFactory类获取java.lang.management.ManagementFactory.getRuntimeMXBean().getStartTime()2、在WEB监听器/定时器中定义时间戳变量public class TimerListener implements ServletContextListener {public static final long StartTime = System.cu…...
2024/4/20 13:21:54 - 亿级流量系统多级缓存架构10 阿里云实战
亿级流量系统多级缓存架构10 阿里云实战 域名购买解析 域名的价值 域名的价值就像商标一样,体现在你注册一个域名之后,别人就不可以再注册这个域名了,域名的稀缺性就产生了。域名可以买卖,一个域名我注册了,有人也想要的话,我可以选择卖给他。域名没有标准的价格,一般域…...
2024/4/17 11:30:16 - Python基础教程:函数及其参数
1、函数 定义一个函数,就好像是给一段代码取个名字。 def 是关键字 表示定义一个函数 然后是函数的 + 名字 (): 缩进的代码表示这个函数名字代表的具体动作是什么,称之为 函数体。 def workflow():print("第一步:打开")print("第二步:输入")print(&…...
2024/4/15 14:06:39 - SSM项目整合时,报“UnsatisfiedDependencyException”和“NoSuchBeanDefinitionException”错误
整合SSM项目时,单独测试SpringMVC、mybatis都没问题,spring整合mybatis时, 报“UnsatisfiedDependencyException”和“NoSuchBeanDefinitionException”错误。 Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with nam…...
2024/4/28 8:59:20
最新文章
- 硬盘选购指南
转载请注明出处! author karrysmile date 2024年5月3日19:10:52 结论 先给用途分类和价格表 前置知识 没有不好的品牌,只有不好的系列。不用认准哪个品牌就不好,认准口碑好,稳定性好的系列买。(杂牌别买࿰…...
2024/5/3 21:18:42 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/3/20 10:50:27 - 设计模式学习笔记 - 设计模式与范式 -行为型:3.模板模式(下):模板模式与Callback回调函数的区别和联系
上篇文章 学习了模板模式的原理、实现和应用。它常用在框架开发中,通过提供功能扩展点,让框架用户在不修改框架源码的情况下,基于扩展点定制化框架的功能。此外,模板模式还可以起到代码复用的作用。 复用和扩展是模板模式的两大作…...
2024/4/27 12:18:09 - 16个Python接单平台,做私活爽歪歪!(附100个爬虫源码)
一、python爬虫是可以做副业的,主要是爬取网站、小程序或者APP的数据,对数据进行分析与处理,或者直接向客户提供爬虫程序与技术支持。 当初学会Python那会儿,有朋友来介绍我去接私活,是为一家公司做网站,那…...
2024/5/1 13:37:03 - git总结
建议配合gitlab实操 git分区:工作区(修改的地方),暂存区(add),本地仓库(commit) 常用命令 初次使用配置 git config --global user.name "xxx" git config --global user.email "xxxqq.com" 这2个是针对整个主机的全局…...
2024/5/3 17:12:58 - 416. 分割等和子集问题(动态规划)
题目 题解 class Solution:def canPartition(self, nums: List[int]) -> bool:# badcaseif not nums:return True# 不能被2整除if sum(nums) % 2 ! 0:return False# 状态定义:dp[i][j]表示当背包容量为j,用前i个物品是否正好可以将背包填满ÿ…...
2024/5/3 11:50:27 - 【Java】ExcelWriter自适应宽度工具类(支持中文)
工具类 import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet;/*** Excel工具类** author xiaoming* date 2023/11/17 10:40*/ public class ExcelUti…...
2024/5/2 16:04:58 - Spring cloud负载均衡@LoadBalanced LoadBalancerClient
LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon,直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件,我们讨论Spring负载均衡以Spring Cloud2020之后版本为主,学习Spring Cloud LoadBalance,暂不讨论Ribbon…...
2024/5/2 23:55:17 - TSINGSEE青犀AI智能分析+视频监控工业园区周界安全防范方案
一、背景需求分析 在工业产业园、化工园或生产制造园区中,周界防范意义重大,对园区的安全起到重要的作用。常规的安防方式是采用人员巡查,人力投入成本大而且效率低。周界一旦被破坏或入侵,会影响园区人员和资产安全,…...
2024/5/3 16:00:51 - VB.net WebBrowser网页元素抓取分析方法
在用WebBrowser编程实现网页操作自动化时,常要分析网页Html,例如网页在加载数据时,常会显示“系统处理中,请稍候..”,我们需要在数据加载完成后才能继续下一步操作,如何抓取这个信息的网页html元素变化&…...
2024/5/3 11:10:49 - 【Objective-C】Objective-C汇总
方法定义 参考:https://www.yiibai.com/objective_c/objective_c_functions.html Objective-C编程语言中方法定义的一般形式如下 - (return_type) method_name:( argumentType1 )argumentName1 joiningArgument2:( argumentType2 )argumentName2 ... joiningArgu…...
2024/5/2 6:03:07 - 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】
👨💻博客主页:花无缺 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】🌏题目描述🌏输入格…...
2024/5/2 9:47:30 - 【ES6.0】- 扩展运算符(...)
【ES6.0】- 扩展运算符... 文章目录 【ES6.0】- 扩展运算符...一、概述二、拷贝数组对象三、合并操作四、参数传递五、数组去重六、字符串转字符数组七、NodeList转数组八、解构变量九、打印日志十、总结 一、概述 **扩展运算符(...)**允许一个表达式在期望多个参数࿰…...
2024/5/2 23:47:43 - 摩根看好的前智能硬件头部品牌双11交易数据极度异常!——是模式创新还是饮鸩止渴?
文 | 螳螂观察 作者 | 李燃 双11狂欢已落下帷幕,各大品牌纷纷晒出优异的成绩单,摩根士丹利投资的智能硬件头部品牌凯迪仕也不例外。然而有爆料称,在自媒体平台发布霸榜各大榜单喜讯的凯迪仕智能锁,多个平台数据都表现出极度异常…...
2024/5/3 13:26:06 - Go语言常用命令详解(二)
文章目录 前言常用命令go bug示例参数说明 go doc示例参数说明 go env示例 go fix示例 go fmt示例 go generate示例 总结写在最后 前言 接着上一篇继续介绍Go语言的常用命令 常用命令 以下是一些常用的Go命令,这些命令可以帮助您在Go开发中进行编译、测试、运行和…...
2024/5/3 1:55:15 - 用欧拉路径判断图同构推出reverse合法性:1116T4
http://cplusoj.com/d/senior/p/SS231116D 假设我们要把 a a a 变成 b b b,我们在 a i a_i ai 和 a i 1 a_{i1} ai1 之间连边, b b b 同理,则 a a a 能变成 b b b 的充要条件是两图 A , B A,B A,B 同构。 必要性显然࿰…...
2024/5/2 9:47:28 - 【NGINX--1】基础知识
1、在 Debian/Ubuntu 上安装 NGINX 在 Debian 或 Ubuntu 机器上安装 NGINX 开源版。 更新已配置源的软件包信息,并安装一些有助于配置官方 NGINX 软件包仓库的软件包: apt-get update apt install -y curl gnupg2 ca-certificates lsb-release debian-…...
2024/5/3 16:23:03 - Hive默认分割符、存储格式与数据压缩
目录 1、Hive默认分割符2、Hive存储格式3、Hive数据压缩 1、Hive默认分割符 Hive创建表时指定的行受限(ROW FORMAT)配置标准HQL为: ... ROW FORMAT DELIMITED FIELDS TERMINATED BY \u0001 COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMI…...
2024/5/3 1:55:09 - 【论文阅读】MAG:一种用于航天器遥测数据中有效异常检测的新方法
文章目录 摘要1 引言2 问题描述3 拟议框架4 所提出方法的细节A.数据预处理B.变量相关分析C.MAG模型D.异常分数 5 实验A.数据集和性能指标B.实验设置与平台C.结果和比较 6 结论 摘要 异常检测是保证航天器稳定性的关键。在航天器运行过程中,传感器和控制器产生大量周…...
2024/5/2 8:37:00 - --max-old-space-size=8192报错
vue项目运行时,如果经常运行慢,崩溃停止服务,报如下错误 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 因为在 Node 中,通过JavaScript使用内存时只能使用部分内存(64位系统&…...
2024/5/3 14:57:24 - 基于深度学习的恶意软件检测
恶意软件是指恶意软件犯罪者用来感染个人计算机或整个组织的网络的软件。 它利用目标系统漏洞,例如可以被劫持的合法软件(例如浏览器或 Web 应用程序插件)中的错误。 恶意软件渗透可能会造成灾难性的后果,包括数据被盗、勒索或网…...
2024/5/2 9:47:25 - JS原型对象prototype
让我简单的为大家介绍一下原型对象prototype吧! 使用原型实现方法共享 1.构造函数通过原型分配的函数是所有对象所 共享的。 2.JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象,所以我们也称为原型对象…...
2024/5/2 23:47:16 - C++中只能有一个实例的单例类
C中只能有一个实例的单例类 前面讨论的 President 类很不错,但存在一个缺陷:无法禁止通过实例化多个对象来创建多名总统: President One, Two, Three; 由于复制构造函数是私有的,其中每个对象都是不可复制的,但您的目…...
2024/5/2 18:46:52 - python django 小程序图书借阅源码
开发工具: PyCharm,mysql5.7,微信开发者工具 技术说明: python django html 小程序 功能介绍: 用户端: 登录注册(含授权登录) 首页显示搜索图书,轮播图࿰…...
2024/5/3 7:43:42 - 电子学会C/C++编程等级考试2022年03月(一级)真题解析
C/C++等级考试(1~8级)全部真题・点这里 第1题:双精度浮点数的输入输出 输入一个双精度浮点数,保留8位小数,输出这个浮点数。 时间限制:1000 内存限制:65536输入 只有一行,一个双精度浮点数。输出 一行,保留8位小数的浮点数。样例输入 3.1415926535798932样例输出 3.1…...
2024/5/3 1:54:59 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...
2022/11/19 21:17:16 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在iPhone上关闭“请勿打扰”
Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...
2022/11/19 21:16:57