JavaScript高级篇 - 浏览器事件详解 DOM事件以及独立封装事件Util和Ajax封装

Dom事件

Model(特定领域对象的抽象)、Protocal(针对数据格式的约定)
DOM(Document Object Model,文档对象模型)是针对HTML文档和XML文档的一个API。DOM描绘了一个层次化的节点树,允许开发人员添加、移出和修改页面的某一部分,DOM 脱胎于Netscape 及微软公司创始的 DHTML(动态HTML)。但现在它已经成为表现和操作页面标记的真正跨平台、语言中立的方式。
Netscape Navigator 4 和 IE4 分别发布于 1997 年的 6 月和 10 月发布的 DHTML,由于 IE4 和 Netscape Navigator4 分别支持不同的 DHTML,为了统一标准,W3C开始制定 DOM。1998 年10 月 W3C 总结了 IE 和 Navigator4 的规范,制定了 DOMLevel 1即 DOM1,之前 IE 与 Netscape 的规范则被称为 DOMLevel 0 即 DOM0 。

DOM0级事件

btn.onclick = function(){console.log('this is a click event')
}

事件就是用户或浏览器自身执行的某种操作,如click、load、mouseover等,都是事件的名字,而响应某个事件的函数就被称为事件处理程序。

click事件过程
在上述的例子中,click 事件并没有像其他函数一样,必须要调用才可以执行,click 事件并不确定什么时候发生,而当浏览器发现用户点击该按钮时,浏览器就检测btn.onclick是否有值,如果有,就会执行btn.onclick.call(btn,event),此时函数执行,call() 方法接收两个参数,第一个指向调用当前方法的对象,也就是this。
需要注意的是,指定的 this 值并不一定是该函数执行时真正的this值,如果这个函数处于非严格模式下,则指定为 null 和 undefined 的 this 值会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的自动包装对象。
另一个参数则是事件对象 event,该对象也可以通过 arguments[0] 来访问,它包含了事件相关的所有信息,如本例子中,则包含了点击事件的全部信息。可以通过给函数传参来获取事件信息。

btn.onclick = function(e){console.log('this is a click event');console.log(e);  //  事件对象
}

但是在 IE 中,在使用 DOM0 级方法添加事件处理程序时,event 是作 window 对象的一个属性而存在的。此时访问事件对象需要通过 window.event。

btn.onclick = function(){console.log(window.event);  //  IE中事件对象    
}

在 DOM0级中,如果想要实现一个对象绑定多个函数,可以这样实现:

function fn1(){// do something
}
function fn2(){// do something
}
btn.onclick = function(e){fn1.call(this.xxx);fn2.call(this.yyy);
}

DOM1级事件
DOM级别1于1998年10月1日成为W3C推荐标准。1级DOM标准中并没有定义事件相关的内容,所以没有所谓的1级DOM事件模型。在2级DOM中除了定义了一些DOM相关的操作之外还定义了一个事件模型 ,这个标准下的事件模型就是我们所说的2级DOM事件模型。

DOM2级事件
W3C 后来将 DOM1 升级为 DOM2,DOM2级规范开始尝试以一种符合逻辑的方式来标准化 DOM事件。DOM0级 可以认为 onclick 是 btn 的一个属性,DOM2级 则将属性升级为队列。
DOM2级 事件定义了两个方法,用于处理指定和删除事件处理程序的操作,addEventListener()和removeEventListener(),所有的 DOM 节点中都包含这两个方法,它们都接收 3 个参数。

  1. 要处理的事件名;
  2. 作为事件处理程序的函数;
  3. 布尔值,true 代表在捕获阶段调用事件处理程序,false 表示在冒泡阶段调用事件处理程序,默认为 false;
btn.addEventListener('click',function(){//  do something
})
btn.addEventListener('click',function(){//  do something else
})

addEventListener()将事件加入到监听队列中,当浏览器发现用户点击按钮时,click 队列中依次执行匿名函数1、匿名函数2。

function fn1(){//  do something
}
function fn1(){//  do something else
}
btn.addEventListener('click',fn1)
btn.addEventListener('click',fn2)

如果这样写,click 队列中依次fn1.call(btn,event),fn2.call(btn,event)。
通过addEventListener()添加的事件只能由removeEventListener()来移除,并且removeEventListener()只能移除具名函数,不能移除匿名函数。

IE 中 DOM2级事件
IE8 及之前,实现类似addEventListener()和removeEventListener()的两个方法是attachEvent()和detachEvent(),这两个方法接受相同的两个参数。

  1. 要处理的事件名;
  2. 作为事件处理程序的函数;

IE8 之前的只支持事件冒泡,所以通过attachEvent()添加的事件处理程序只能添加到冒泡阶段。

btn.attachEvent('click',fn1)
btn.attachEvent('click',fn2)

当用户点击时,click 队列依次fn1.call(undefined,undefined),fn2.call(undefined,undefined)。
类似的detachEvent()也只能移除具名函数,不能移除匿名函数。

function eventHandler() {console.log('xianzao);
}btn.attachEvent('onClick', eventHandler);
btn.detachEvent('onClick, eventHandler);

兼容处理

if(typeof btn.addEventListener === 'function'){btn.addEventListener('click',fn);
}else if(typeof btn.attachEvent === 'function'){btn.attachEvent('onclick',fn)
}else{btn.onclick=function(){// do something}
}

总结

var btn = document.getElementById('btn');btn.onClick = () => {console.log('我是DOM0级事件处理程序');
}
btn.onClick = null;btn.addEventListener('click', () => {console.log('我是DOM2级事件处理程序');
}, false);
btn.removeEventListener('click', handler, false)btn.attachEvent('onclick', () => {console.log('我是IE事件处理程序')
})
btn.detachEvent('onclicn', handler);
  1. DOM2级的好处是可以添加多个事件处理程序;DOM0对每个事件只支持一个事件处理程序;
  2. 通过DOM2添加的匿名函数无法移除,上面写的例子就移除不了,addEventListener和removeEventListener的handler必须同名;
  3. 作用域:DOM0的handler会在所属元素的作用域内运行,IE的handler会在全局作用域运行,this === window;
  4. 触发顺序:添加多个事件时,DOM2会按照添加顺序执行,IE会以相反的顺序执行;
  5. 跨浏览器的事件处理程序
var EventUtil = {// element是当前元素,可以通过getElementById(id)获取// type 是事件类型,一般是click ,也有可能是鼠标、焦点、滚轮事件等等// handle 事件处理函数addHandler: (element, type, handler) => {// 先检测是否存在DOM2级方法,再检测IE的方法,最后是DOM0级方法(一般不会到这)if (element.addEventListener) {// 第三个参数false表示冒泡阶段element.addEventListener(type, handler, false);} else if (element.attachEvent) {element.attachEvent(`on${type}`, handler)} else {element[`on${type}`] = handler;}},removeHandler: (element, type, handler) => {if (element.removeEventListener) {// 第三个参数false表示冒泡阶段element.removeEventListener(type, handler, false);} else if (element.detachEvent) {element.detachEvent(`on${type}`, handler)} else {element[`on${type}`] = null;}}
}// 获取元素
var btn = document.getElementById('btn');
// 定义handler
var handler = function(e) {console.log('我被点击了');
}
// 监听事件
EventUtil.addHandler(btn, 'click', handler);
// 移除事件监听
// EventUtil.removeHandler(button1, 'click', clickEvent);

事件捕获&事件冒泡

事件流描述的是从页面中接收事件的顺序
IE 的事件流是事件冒泡流
而 Netscape Communicator 的事件流是事件捕获流
DOM2级事件规定的事件流包括三个阶段:

  • 事件捕获阶段;
  • 处于目标阶段;
  • 事件冒泡阶段;

首先发生的是事件捕获,为截获事件提供了机会。
然后是实际的目标接收到事件。
最后一个阶段是冒泡阶段,可以在这个阶段对事件做出响应
在这里插入图片描述

  1. 当处于目标阶段,没有捕获与冒泡之分,执行顺序会按照addEventListener的添加顺序决定,先添加先执行;
  2. 使用stopPropagation()取消事件传播时,事件不会被传播给下一个节点,但是,同一节点上的其他listener还是会被执行;如果想要同一层级的listener也不执行,可以使用stopImmediatePropagation();
// list 的捕获
$list.addEventListener('click', (e) => {console.log('list capturing');e.stopPropagation();
}, true)// list 捕获 2
$list.addEventListener('click', (e) => {console.log('list capturing2');
}, true)// list capturing
// list capturing2
  1. preventDefault()只是阻止默认行为,跟JS的事件传播一点关系都没有;
  2. 一旦发起了preventDefault(),在之后传递下去的事件里面也会有效果;

测试
如果有以下例子:

<!DOCTYPE html> 
<html> 
<head> <title>Event Bubbling Example</title> 
</head> 
<body> <div id="myDiv">Click Me</div> 
</body> 
</html>
  1. 事件捕获
    最不具体的节点最先收到事件,而最具体的节点最后收到事件。事件捕获实际上是为了在事件到达最终目标
    前拦截事件。
    如果前面的例子使用事件捕获,则点击
    元素会以下列顺序触发 click 事件:
    在这里插入图片描述
  2. 事件冒泡
    在点击页面中的div元素后,click 事件会以如下顺序发生:
    在这里插入图片描述
    div元素,即被点击的元素,最先触发 click 事件。然后,click 事件沿 DOM 树一路向上,在经过的每个节点上依次触发,直至到达 document 对象。

事件对象
DOM0和DOM2的事件处理程序都会自动传入event对象
IE中的event对象取决于指定的事件处理程序的方法。
IE的handler会在全局作用域运行,this === window,所以在IE中会有window.event、event两种情况,只有在事件处理程序期间,event对象才会存在,一旦事件处理程序执行完成,event对象就会被销毁
event对象里需要关心的两个属性:

  1. target:target永远是被添加了事件的那个元素;
  2. eventPhase:调用事件处理程序的阶段,有三个值
    a 捕获阶段;
    b. 处于目标;
    c 冒泡阶段;

preventDefault与stopPropagation
preventDefault:比如链接被点击会导航到其href指定的URL,这个就是默认行为;
stopPropagation:立即停止事件在DOM层次中的传播,包括捕获和冒泡事件;
IE中对应的属性:

  • srcElement => target
  • returnValue => preventDefaukt()
  • cancelBubble => stopPropagation()

IE 不支持事件捕获,因而只能取消事件冒泡,但stopPropagation可以同时取消事件捕获和冒泡。
再针对上面不同类型的事件及属性进行区分:

var EventUtil = {// element是当前元素,可以通过getElementById(id)获取// type 是事件类型,一般是click ,也有可能是鼠标、焦点、滚轮事件等等// handle 事件处理函数addHandler: (element, type, handler) => {// 先检测是否存在DOM2级方法,再检测IE的方法,最后是DOM0级方法(一般不会到这)if (element.addEventListener) {// 第三个参数false表示冒泡阶段element.addEventListener(type, handler, false);} else if (element.attachEvent) {element.attachEvent(`on${type}`, handler)} else {element[`on${type}`] = handler;}},removeHandler: (element, type, handler) => {if (element.removeEventListener) {// 第三个参数false表示冒泡阶段element.removeEventListener(type, handler, false);} else if (element.detachEvent) {element.detachEvent(`on${type}`, handler)} else {element[`on${type}`] = null;}},// 获取event对象getEvent: (event) => {return event ? event : window.event},// 获取当前目标getTarget: (event) => {return event.target ? event.target : event.srcElement},// 阻止默认行为preventDefault: (event) => {if (event.preventDefault) {event.preventDefault()} else {event.returnValue = false}},// 停止传播事件stopPropagation: (event) => {if (event,stopPropagation) {event.stopPropagation()} else {event.cancelBubble = true}}
}

事件委托
事件委托:用来解决事件处理程序过多的问题
页面结构如下

<ul id="myLinks"><li id="goSomewhere">Go somewhere</li><li id="doSomething">Do something</li><li id="sayHi">Say hi</li>
</ul>

按照传统的做法,需要像下面这样为它们添加 3 个事 件处理程序。

var item1 = document.getElementById("goSomewhere");
var item2 = document.getElementById("doSomething");
var item3 = document.getElementById("sayHi");
EventUtil.addHandler(item1, "click", function(event){location.href = "http://www.xianzao.com";
});
EventUtil.addHandler(item2, "click", function(event){document.title = "I changed the document's title";
});
EventUtil.addHandler(item3, "click", function(event){alert("hi");
});

如果在一个复杂的 Web 应用程序中,对所有可单击的元素都采用这种方式,那么结果就会有数不 清的代码用于添加事件处理程序。此时,可以利用事件委托技术解决这个问题。使用事件委托,只需在 DOM 树中尽量最高的层次上添加一个事件处理程序,如下面的例子所示

var list = document.getElementById("myLinks");
EventUtil.addHandler(list, "click", function(event) {event = EventUtil.getEvent(event);var target = EventUtil.getTarget(event);switch(target.id) {case "doSomething":document.title = "I changed the document's title";break;case "goSomewhere":location.href = "http://www.wrox.com";break;case "sayHi": 9 alert("hi");break; }
}

子节点的点击事件会冒泡到父节点,并被这个注册事件处理
最适合采用事件委托技术的事件包括 click、mousedown、mouseup、keydown、keyup 和 keypress。 虽然 mouseover 和 mouseout 事件也冒泡,但要适当处理它们并不容易,而且经常需要计算元素的位置。
可以考虑为 document 对象添加一个事件处理程序,用以处理页面上发生的某种特定类型的事件,需要跟踪的事件处理程序越少,移除它们就越容易(移除事件处理程序关乎内存和性能)。
只要是通过 onload 事件处理程序添加的东西,最后都要通过 onunload 事件处理程序将它们移除。

浏览器请求

在浏览器端发送网络请求的常见方式:

  1. ajax;
  2. fetch;
  3. axios;

ajax

Asynchronous JavaScript And XML,翻译过来就是“异步的 Javascript 和 XML”。

ajax是js异步技术的术语,早起相关的api是XHR。
Ajax 是一个技术统称,是一个概念模型,它囊括了很多技术,并不特指某一技术,它很重要的特性之一就是让页面实现局部刷新。
特点:

  • 局部刷新页面,无需重载整个页面。

简单来说,Ajax 是一种思想,XMLHttpRequest 只是实现 Ajax 的一种方式。其中 XMLHttpRequest 模块就是实现 Ajax 的一种很好的方式。

手写ajax
利用 XMLHttpRequest 模块实现 Ajax。
1)创建异步对象

let xmlHttp;
if (window.XMLHttpRequest) {// code for IE7+, Firefox, Chrome, Opera, SafarixmlHttp = new XMLHttpRequest();
} else {// code for IE6, IE5xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');
}

通过XMLHttpRequest构造函数创建一个异步对象xmlhttp, IE6, IE5 使用ActiveXObject创建,创建的这个异步对象上有很多属性和方法,常用的有:

  1. onreadystatechange:监听异步对象请求状态码readyState的改变,每当readyState改变时,就会触发onreadystatechange事件;
  2. readyState:请求状态码
    readyState表示异步对象目前的状态,状态码从0到4:
    0: 表示请求未初始化,还没有调用 open();
    1: 服务器连接已建立,但是还没有调用 send();
    2: 请求已接收,正在处理中(通常现在可以从响应中获取内容头);
    3: 请求处理中,通常响应中已有部分数据可用了,没有全部完成;
    4: 当readyState状态码为4时,表示请求已完成;此阶段确认全部数据都已经解析完毕,可以通过异步对象的属性获取对应数据;
  3. status:http状态码
    http状态码表示成功的http状态码有
    xmlHttp.status >= 200 && xmlHttp.status < 300 || xmlHttp.status == 304
  4. responseText:后台返回的字符串形式的响应数据;
  5. responseXML:后台返回的XML形式的响应数据;

设置请求方式和请求地址

创建异步对象之后,通过open()方法设置ajax请求方式和请求地址 格式:
xmlHttp.open(“GET/POST”,“ajax-get.txt”,true)
第一个参数:请求的类型;GET 还是 POST;
第二个参数:表示请求的文件的地址url;
第三个参数:设置请求方法是不是异步async,true为异步, false为同步。AJAX存在的意义就是发异步请求,所以第三个参数永远传true;

注意:有个问题,就是IE中的缓存问题
在IE浏览器中,如果通过Ajax发送GET请求,那么IE浏览器认为,同一个URL只有一个结果,如果地址没有发生变化,它就会把上一次返回的结果,直接返回。这样我们不能实时的拿到变化后的数据。如果要想我们拿到实时数据,必须保证每次的URL都是不一样的,有两种方式:

  1. Math.random();
  2. new Date().getTime();

即在请求地址后面拼接上?t=随机数或者1970.01.01至当前的毫秒数 所以在IE中通过ajax发送get请求时,可以设置请求地址为:

xmlHttp.open("GET","ajax-get.txt?t=" + (new Date().getTime()),true);
//或
xmlHttp.open("GET","ajax-get.txt?t=" + Math.random(),true);

发送请求
直接通过异步对象的send()发送请求

xmlHttp.send();

特别注意的是: 如果发送POST请求,使用setRequestHeader()来添加 HTTP请求头,并在send()方法中传递要发送的数据:

xmlHttp.open("POST","ajax_test.html",true); 
xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 
xmlHttp.send("fname=Henry&lname=Ford");

通过onreadystatechange监听状态变化

当异步对象的readyState发生改变,会触发onreadystatechange函数,当readyState变成为4时,表示当前状态是请求完毕的状态,同时当http的响应码status为200到300之间(包括200和300)或为304时,表示ajax请求成功;当http状态码不是200到300之间的数也不是304时,表示请求不成功

//4.监听状态变化
xmlHttp.onreadystatechange = () => {// 判断当前状态改变是请求完毕的状态吗if (xmlHttp.readyState === 4) {if (xmlHttp.status >= 200 && xmlHttp.status < 300 || xmlHttp.status == 304) {console.log("成功的接收到服务器返回的数据");}else{console.log("不成功!");}   }
}  

处理返回的结果
如果成功,可通过异步对象的responseText属性来获取服务器返回的字符串
接下来,我们来封装一个方法ajax()用于发送请求
封装的时候,需要注意:

  1. URL当中只能出现字母 数字 下划线和ASCII码,不能出现中文,可以使用encodeURIComponent()转码;
  2. 当我们利用我们的ajax放的发送一个请求到远处服务器时,我们需要等待远程服务器去响应我们的请求,等待远程服务器将响应的结果返回给我们,但是这个响应的速度是不确定的,因为响应的速度是由本地网络和远程服务器的网速等共同决定的,所以我们不可能一直等待服务器的响应。这里需要设置超时时间;
ajax({type: 'GET',url: 'http://localhost:3000/posts',timeout: 1000,success: data => {console.log('success', data);},error: err => {console.log('error', err);},
});

其他
至此,jQuery官方的ajax还是有一定的差异,所以还需要进一步完善
3. 传递多个参数,需要保持传递顺序。解决方案是可以改写成传递的是一个对象;因为对象里面的值,传递的是一个对象就不用考虑先后顺序,里面用的参数通过对象名.属性名的形式获取;
4. 传递请求类型的区分大小写,jQuery官方的是大小写都可以;解决方案是可以使用toLowerCase()或者toUpperCase()将类型转成大写或小写再对比;
5. 我们传递的数据用的名字是obj,jQuery官方用的是data;

const ajax = option => {//type, url, data, timeout, success, error将所有参数换成一个对象{}//  0.将对象转换成字符串//处理objconst objToString = data => {data.t = new Date().getTime();let res = [];for (let key in data) {//需要将key和value转成非中文的形式,因为url不能有中文。使用encodeURIComponent();res.push(encodeURIComponent(key) + ' = ' + encodeURIComponent(data[key]));}return res.join('&');};let str = objToString(option.data || {});//  1.创建一个异步对象xmlHttp;var xmlHttp, timer;if (window.XMLHttpRequest) {xmlHttp = new XMLHttpRequest();} else if (xmlHttp) {// code for IE6, IE5xmlHttp = new ActiveXObject('Microsoft.xmlHttp');}//  2.设置请求方式和请求地址;// 判断请求的类型是POST还是GETif (option.type.toLowerCase() === 'get') {xmlHttp.open(option.type, option.url + '?t=' + str, true);//  3.发送请求;xmlHttp.send();} else {xmlHttp.open(option.type, option.url, true);// 注意:在post请求中,必须在open和send之间添加HTTP请求头:setRequestHeader(header,value);xmlHttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');//  3.发送请求;xmlHttp.send(str);}//  4.监听状态的变化;xmlHttp.onreadystatechange = function () {clearInterval(timer);debugger;if (xmlHttp.readyState === 4) {if ((xmlHttp.status >= 200 && xmlHttp.status < 300) || xmlHttp.status == 304) {//  5.处理返回的结果;option.success(xmlHttp.responseText); //成功后回调;} else {option.error(xmlHttp.responseText); //失败后回调;}}};//判断外界是否传入了超时时间if (option.timeout) {timer = setInterval(function () {xmlHttp.abort(); //中断请求clearInterval(timer);}, option.timeout);}
};

实现Upload的request封装
针对fusion中 Upload 组件,实现自定义请求的封装。

function customRequest(option) {/* coding here */return {abort() {/* coding here */}};
}<Upload request={customRequest}/>

其中,customRequest的实现如下:

/*** clone from https://github.com/react-component/upload/blob/master/src/request.js*/function getError(option, xhr, msg) {msg = msg || `cannot post ${option.action} ${xhr.status}'`;const err = new Error(msg);err.status = xhr.status;err.method = option.method;err.url = option.action;return err;
}function getBody(xhr) {const text = xhr.responseText || xhr.response;if (!text) {return text;}try {return JSON.parse(text);} catch (e) {return text;}
}// option {
//  onProgress: (event: { percent: number }): void,
//  onError: (event: Error, body?: Object): void,
//  onSuccess: (body: Object): void,
//  data: Object,
//  filename: String,
//  file: File,
//  withCredentials: Boolean,
//  action: String,
//  headers: Object,
//  method: String
//  timeout: Number
// }
export default function upload(option) {const xhr = new XMLHttpRequest();if (option.onProgress && xhr.upload) {xhr.upload.onprogress = function progress(e) {if (e.total > 0) {e.percent = (e.loaded / e.total) * 100;}option.onProgress(e);};}const formData = new FormData();if (option.data) {Object.keys(option.data).forEach(key => {formData.append(key, option.data[key]);});}if (option.file instanceof Blob) {formData.append(option.filename, option.file, option.file.name);} else {formData.append(option.filename, option.file);}xhr.onerror = function error(e) {option.onError(e);};xhr.onload = function onload() {// allow success when 2xx status// see https://github.com/react-component/upload/issues/34if (xhr.status < 200 || xhr.status >= 300) {return option.onError(getError(option, xhr), getBody(xhr));}option.onSuccess(getBody(xhr), xhr);};option.method = option.method || 'POST';xhr.open(option.method, option.action, true);// In Internet Explorer, the timeout property may be set only after calling the open() method and before calling the send() method.// see https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/timeoutconst { timeout } = option;if (typeof timeout === 'number' && timeout > 0) {xhr.timeout = timeout;xhr.ontimeout = () => {const msg = `Upload abort for exceeding time (timeout: ${timeout}ms)`;option.onError(getError(option, xhr, msg), getBody(xhr));};}// Has to be after `.open()`. See https://github.com/enyo/dropzone/issues/179if (option.withCredentials && 'withCredentials' in xhr) {xhr.withCredentials = true;}const headers = option.headers || {};// when set headers['X-Requested-With'] = null , can close default XHR header// see https://github.com/react-component/upload/issues/33if (headers['X-Requested-With'] !== null) {xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');}for (const h in headers) {if (headers.hasOwnProperty(h) && headers[h] !== null) {xhr.setRequestHeader(h, headers[h]);}}xhr.send(formData);return {abort() {xhr.abort();},};
}

我们可以发现,ajax只是一种异步请求的方式,并不特指某一种具体的实现方式,但随着使用这种方式实现网络请求时内部又包含请求的情况,就会出现回调地狱,这也是XHR的诟病之一,因此,后来才催生了更加优雅的请求方式。

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

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

相关文章

MinIO 的 S3 over RDMA 计划: 为高速人工智能数据基础设施设定对象存储新标准

随着 AI 和机器学习的需求不断加速&#xff0c;数据中心网络正在迅速发展以跟上步伐。对于许多企业来说&#xff0c;400GbE 甚至 800GbE 正在成为标准选择&#xff0c;因为数据密集型和时间敏感型 AI 工作负载需要高速、低延迟的数据传输。用于大型语言处理、实时分析和计算机视…

git config是做什么的?

git config是做什么的&#xff1f; git config作用配置级别三种配置级别的介绍及使用&#xff0c;配置文件说明 使用说明git confi查看参数 默认/不使用这个参数 情况下 Git 使用哪个配置等级&#xff1f; 一些常见的行为查看配置信息设置配置信息删除配置信息 一些常用的配置信…

使用 npm 安装 Yarn

PS E:\WeChat Files\wxid_fipwhzebc1yh22\FileStorage\File\2024-11\spid-admin\spid-admin> yarn install yarn : 无法将“yarn”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写&#xff0c;如果包括路径&#xff0c;请确保路径正确&#xff0c;然后…

常用在汽车PKE无钥匙进入系统的高度集成SOC芯片:CSM2433

CSM2433是一款集成2.4GHz频段发射器、125KHz接收器和8位RISC&#xff08;精简指令集&#xff09;MCU的SOC芯片&#xff0c;用在汽车PKE无钥匙进入系统里。 什么是汽车PKE无钥匙进入系统&#xff1f; 无钥匙进入系统具有无钥匙进入并且启动的功能&#xff0c;英文名称是PKE&…

机器学习基础05

目录 1.随机森林 1.1随机森林的介绍 1.2算法原理 1.3API 2.线性回归 2.1回归的含义 2.2线性回归 2.3损失函数 2.4多参数回归 2.5最小二乘法MSE 2.6API 1.随机森林 集成学习的基本思想就是将多个分类器组合&#xff0c;从而实现一个预测效果更好的集成分类器。 集成…

数据库范式、MySQL 架构、算法与树的深入解析

一、数据库范式 在数据库设计中&#xff0c;范式是一系列规则&#xff0c;用于确保数据的组织和存储具有良好的结构、完整性以及最小化的数据冗余。如果不遵循范式设计&#xff0c;数据可能会以平铺式罗列&#xff0c;仅使用冒号、分号等简单分隔。这种方式存在诸多弊端&#…

SQL面试题——奔驰SQL面试题 车辆在不同驾驶模式下的时间

SQL面试题——奔驰SQL面试题 我们的表大致如下 CREATE TABLE signal_log( vin STRING COMMENTvehicle frame id, signal_name STRING COMMENTfunction name, signal_value STRING COMMENT signal value , ts BIGINT COMMENTevent timestamp, dt STRING COMMENTformat yyyy-mm…

Hadoop生态圈框架部署(六)- HBase完全分布式部署

文章目录 前言一、Hbase完全分布式部署&#xff08;手动部署&#xff09;1. 下载Hbase2. 上传安装包3. 解压HBase安装包4. 配置HBase配置文件4.1 修改hbase-env.sh配置文件4.2 修改hbase-site.xml配置文件4.3 修改regionservers配置文件4.4 删除hbase中slf4j-reload4j-1.7.33.j…

YOLOv11改进,YOLOv11添加GnConv递归门控卷积,二次创新C3k2结构

摘要 视觉 Transformer 在多种任务中取得了显著的成功,这得益于基于点积自注意力的新空间建模机制。视觉 Transformer 中的关键因素——即输入自适应、长距离和高阶空间交互——也可以通过卷积框架高效实现。作者提出了递归门控卷积(Recursive Gated Convolution,简称 gnCo…

Queuing 表(buffer表)的优化实践 | OceanBase 性能优化实践

案例问题描述 该案例来自一个金融行业客户的问题&#xff1a;他们发现某个应用对一个数据量相对较小的表&#xff08;仅包含数千条记录&#xff09;访问时&#xff0c;频繁遇到性能下降的情况。为解决此问题&#xff0c;客户向我们求助进行分析。我们发现这张表有频繁的批量插…

CentOS 8 安装 chronyd 服务

操作场景 目前原生 CentOS 8 不支持安装 ntp 服务&#xff0c;因此会发生时间不准的问题&#xff0c;需使用 chronyd 来调整时间服务。CentOS 8以及 TencentOS 3.1及以上版本的实例都使用 chronyd 服务实现时钟同步。本文介绍了如何在 CentOS 8 操作系统的腾讯云服务器上安装并…

AI大模型(二):AI编程实践

一、软件安装 1. 安装 Visual Studio Code VSCode官方下载&#xff1a;Visual Studio Code - Code Editing. Redefined 根据自己的电脑系统选择相应的版本下载 安装完成&#xff01; 2. 安装Tongyi Lingma 打开VSCode&#xff0c;点击左侧菜单栏【extensions】&#xff0c;…

Win10/11 安装使用 Neo4j Community Edition

如果你下载的是 Neo4j Community Edition 的压缩包&#xff0c;意味着你需要手动解压并配置 Neo4j。以下是详细的使用步骤&#xff1a; 0. 下载压缩包 访问Neo4j官网&#xff0c;找到 Community Edition 版本并选择 4.x 或者 5.x 下载&#xff1a;https://neo4j.com/deployme…

使用json配置动态区间及动态执行公式

背景 有时候可能线上一直需要调整公式或者区间以及参数等等&#xff0c;如果使用代码方式&#xff0c;将会变得比较麻烦&#xff0c;可以在redis或者数据库配置一份动态配置&#xff0c;让代码进行解析并执行&#xff0c;可以对公式以及参数等进行动态调节 需求 x 是估值&…

腾讯地图GL JS点标识监听:无dragend事件的经纬度获取方案

引入腾讯地图SDK <!--腾讯地图 API--><script charset"utf-8" src"https://map.qq.com/api/gljs?librariestools&v1.exp&key***"></script>构建地图容器 <div class"layui-card"><div class"layui-car…

Tiktok对接和内容发布申请流程

这段时间在搞AI生成视频&#xff0c;希望用户能一键发布到Tiktok&#xff0c;因此研究了一下Tiktok的开发者申请流程&#xff0c;发现好复杂&#xff0c;同时也发现Tiktok的开发也跟我一样&#xff0c;挺草台班子的 0、流程简述 废话不多说&#xff0c;Tiktok的开发者申请和…

企业生产环境-麒麟V10(ARM架构)操作系统部署kafka高可用集群

前言&#xff1a;Apache Kafka是一个分布式流处理平台&#xff0c;由LinkedIn开发并捐赠给Apache软件基金会。它主要用于构建实时数据流管道和流应用。Kafka具有高吞吐量、可扩展性和容错性的特点&#xff0c;适用于处理大量数据。 以下是Kafka的一些核心概念和特性&#xff1…

xcode-select: error: tool ‘xcodebuild‘ requires Xcode, but active developer

打开 .sh 文件所在的终端窗口&#xff0c;执行终端命令&#xff1a;sh 文件名.sh&#xff0c;出现如下错误&#xff1a; 解决办法&#xff1a;

CC6学习记录

&#x1f338; cc6 cc6和cc1的国外链其实后半条链子是一样的&#xff0c;但是cc6的不局限于jdk的版本和commons-collections的版本。 回忆一下cc1的后半条链子&#xff1a; LazyMap.get()->InvokerTransformer.transform() 这里我们就结合了URLDNS链的思路&#xff0c;在…

嵌入式硬件实战基础篇(一)-STM32+DAC0832 可调信号发生器-产生方波-三角波-正弦波

引言&#xff1a;本内容主要用作于学习巩固嵌入式硬件内容知识&#xff0c;用于想提升下述能力&#xff0c;针对学习STM32与DAC0832产生波形以及波形转换&#xff0c;对于硬件的降压和对于前面硬件篇的实际运用&#xff0c;针对仿真的使用&#xff0c;具体如下&#xff1a; 设…