Web阶段性技术文档(二)

 

一、Ajax学习与理解

1、如何发请求?

用 form 可以发请求,但是会刷新页面或新开页面。

用 a 可以发 get 请求,但是也会刷新页面或新开页面。

用 img 可以发 get 请求,但是只能以图片的形式展示。

用 link 可以发 get 请求,但是只能以 CSS、favicon 的形式展示。

用 script 可以发 get 请求,但是只能以脚本的形式运行。

 

<form action="xxx" method="POST">

  <input type="text" name="password">

  <input type="submit">

</form>

使用form发送请求,查看请求的内容:

password=123456就是POST请求的第四部分

思考:有没有什么方式可以实现?

  1. get、post、put、delete 请求都行
  2. 想以什么形式展示就以什么形式展示

 

2、微软的突破

IE 5 率先在 JS 中引入 ActiveX 对象(API),使得 JS 可以直接发起 HTTP 请求(想用getpost都可以,想以什么形式展示就以什么形式展示)

随后 Mozilla、 Safari、 Opera 也跟进(抄袭)了,取名 XMLHttpRequest(全局对象),并被纳入 W3C 规范。

XMLHttpRequest使得浏览器有了和软件一样的体验,不局限于看文章和刷新。

 

3、AJAX

Jesse James Garrett 讲如下技术取名叫做 AJAX:异步的 JavaScript 和 XML

  1. 使用 XMLHttpRequest 发请求
  2. 服务器返回 XML 格式的字符串

(因为当时XML在当时是流行的数据传输格式,后来用json)

  1. JS 解析 XML,并更新局部页面

 

2005年2月,AJAX 这个词第一次正式提出,它是 Asynchronous JavaScript and XML 的缩写,指的是通过 JavaScript 的异步通信,从服务器获取 XML 文档从中提取数据,再更新当前网页的对应部分,而不用刷新整个网页。后来,AJAX 这个词就成为 JavaScript 脚本发起 HTTP 通信的代名词,也就是说,只要用脚本发起通信,就可以叫做 AJAX 通信。W3C 也在2006年发布了它的国际标准。

 

具体来说,AJAX 包括以下几个步骤:

  1. 创建 XMLHttpRequest 实例
  2. 发出 HTTP 请求
  3. 接收服务器传回的数据
  4. 更新网页数据

 

概括起来,就是一句话,AJAX 通过原生的XMLHttpRequest对象发出 HTTP请求,得到服务器返回的数据后,再进行处理。现在,服务器返回的都是JSON格式的数据,XML 格式已经过时了,但是 AJAX这个名字已经成了一个通用名词,字面含义已经消失了。

 

4、如何使用XMLHttpRequest对象

(1)服务器端代码:

if(path === '/'){

    response.statusCode = 200

    let string = fs.readFileSync('./index.html')

    response.setHeader('Content-Type', 'text/html;charset=utf-8')

    response.write(string)

    response.end()

  }

 

对于响应来说,第四部分始终都是字符串,因为response.write(string)返回的是字符串,我们给浏览器返回了符合html格式的字符串

然后再设置响应头中的Content-Type,response.setHeader('Content-Type', 'text/html;charset=utf-8'),即要求浏览器以HTML的语法解析这段字符串,所以我们可以设置浏览器使用的解析方法为json,也可设置为xml.所以JSON 是一门语言。

http请求的路径都是绝对路径.所以都是以/开头。

 

(2)开始使用:

我们请求一个以xml格式解析的字符串,然后看响应是什么

服务器端代码:

else if (path === '/xxx') {

    response.statusCode = 200

    response.setHeader('Content-Type', 'text/xml;charset=utf-8')

    response.write(`

    <note>

      <to>Tove</to>

      <from>Jani</from>

      <heading>Reminder</heading>

      <body>Don't forget me this weekend!</body>

    </note>

    `)

    response.end()

  }

 

main.js

let myButton = document.getElementById('myButton');

myButton.addEventListener("click",(e)=>{

let request = new XMLHttpRequest();

request.open('GET','/xxx')

//配置request.参数分别为方法和路径

request.send();//发送请求

})

 

index.html

<body>

<button id="myButton">点我</button>

<script src="main.js"></script>

</body>

当点击点我按钮时,查看发送的请求和收到的响应:

 

将request打印出来,观察结构:

 

(3)理解代码中的时间概念:

a. XMLHttpRequest.readyState返回一个整数,表示实例对象的当前状态。该属性只读。 

b. 能够返回0,1,2,3,4,具体数字代表看上面的文档.

c. 4,表示服务器返回的数据已经完全接收,或者本次接收已经失败。

d. 通信过程中,每当实例对象发生状态变化,它的readyState属性的值就会改变。这个值每一次变化,都会触发readyStateChange事件。

var xhr = new XMLHttpRequest();

if (xhr.readyState === 4) {

  // 请求结束,处理服务器返回的数据

} else {

  // 显示提示“加载中……”

}

上面代码中,xhr.readyState等于4时,表明脚本发出的 HTTP 请求已经成功。其他情况,都表示 HTTP 请求还在进行中。

从时间角度看这个过程:

当我们发送一个/xxx请求,使用的时间为9ms,9毫秒实际上很长,看一看在代码中9毫秒可以干什么。

在控制台执行:

console.time();

var a=1 ; 

console.timeEnd();

返回结果为default: 0.008056640625ms,声明一个变量只用了0.008ms,打印一句话只用了1ms。

 

所以9ms对于浏览器来说,对于代码来说是很长的,可以做很多事情。接下来看看readyState属性在一次请求中的变化过程:

let request = new XMLHttpRequest();

    request.open('GET','/xxx')

    request.send();

    setInterval(()=>{//在发送请求的过程中,每一毫秒问一下

        console.log(request.readyState);

    },1)

结果为:

readyState在这个过程中从1变为4

 

readyState各个值的含义:

刚刚只显示了1和4的原因是因为2,3太快,比一毫秒还快。01234这四个状态是逐个经过的。我们只需要记住4,4代表请求已经把响应下载完毕了。

 

(4)XMLHttpRequest.onreadystatechange

XMLHttpRequest.onreadystatechange = callback;

当 readyState 的值改变的时候,callback 函数会被调用。

var xhr= new XMLHttpRequest(),

            method = "GET",

            url = "https://developer.mozilla.org/";

xhr.open(method, url, true);

xhr.onreadystatechange = function () {

            if(xhr.readyState === XMLHttpRequest.DONE && xhr.status ===200) {

        console.log(xhr.responseText)

     }}

xhr.send();

XMLHttpRequest.DONE就是4

onreadystatechange测试

把监听函数往上写,这样就不会错过每一个readyState的变化:

myButton.addEventListener("click",(e)=>{

    let request = new XMLHttpRequest();

    request.onreadystatechange = ()=>{//把监听函数往上写,这样就不会错过每一个readyState的变化

        console.log(request.readyState);

    }

    request.open('GET','/xxx')//配置request.参数分别为方法和路径

    request.send();//发送请求

    // console.log(request)

})

打印结果为1,2,3,4

4代表请求已经把响应下载完毕了,但是请求成功和失败还要看status状态码是大于200小于300还是大于400

 request.onreadystatechange = ()=>{

        if(request.readyState ===4){

            console.log("请求和响应都完毕了");

            if ( request.status>=200&&request.status<=400){

                console.log('说明请求成功');

              console.log(request.responseText);//打印响应的第四部分,字符串

            }else if(request.status>=400){

                console.log("响应失败");

            }

        }

    }

 

但是xml结构不方便,需要使用DOMapi去获取数据.现在使用json

(5)使用json解析响应的第四部分

什么是json:json是一门数据格式化语言,用来表示数据

参考网站:https://www.json.org/

 

 

以下都是合法的json语法:

"hi",null,["a","b"],{"name":"马涛涛","isBoy":true}

下面不符合:{'x':"y"}必须是双引号

 

接下来我们返回一个符合json语法的字符串

else if (path === '/xxx') {

    response.statusCode = 200

    response.setHeader('Content-Type', 'text/xml;charset=utf-8')

    response.write(`

    {

      "note":{

        "from":"mataotao",

        "to":"ni",

        "bool":true,

        "arr":["a",1,2,3],

        "num":3

      }

    }

    `)

    response.end()

使用window.JSON这个API,把符合json语法的字符串转化为js对应的值。这个API就像window.document.getElementById一样,是浏览器提供的api。修改一下main.js将json转化为:

if ( request.status>=200&&request.status<=400){

                console.log('说明请求成功');

                console.log(request.responseText);

                console.log( typeof request.responseText);//string

 

                let string = request.responseText;

                //把符合json语法的字符串转化为js对应的值

                let object2 = window.JSON.parse(string);

                console.log( typeof object2)

                console.log(object2)

            }

 

这样我们就可以用object.note.from取到"mataotao"这个字符串

http响应第四部分永远是字符串,只是写的这个字符串刚好符合json对象的语法

 

5、使用原生JS发送Ajax请求

myButton.addEventListener("click",(e)=>{

//这四句一定要记住

    let request = new XMLHttpRequest();

    request.onreadystatechange = ()=>{

    if(request.readyState === XMLHttpRequest.DONE && request.status === 200) {

 

    console.log(request.responseText)

  }

    }

 

    request.open('GET','/xxx')//配置request.参数分别为方法和路径

    request.send();//发送请求

//这四句一定要记住

})

 

 

  • 简化版自己实现JQuery

1、自己写jQuery与用jQuery

 
<!DOCTYPE html><html lang="en"><head>
    <meta charset="UTF-8">
    <title>jQuery-Study</title>
    <script src="01_myjQuery1.js"></script>
    <script src="jQuery3.3.1min.js"></script>
<style>
 
        .red{
            color: red;
        }
        .blue{
            color: blue;
        }
        .big{
            font-size: larger;
        }
        .green{
            color: green;
        }
        .pink{
            color: pink;
        }
    </style></head><body>

 

 

01_myjQuery1.js

// 得到兄妹结点//传入的参数是一个节点,返回兄妹结点的数组function getSiblings(node) {
    var allSilings = node.parentNode.children;
    var siblingsArray = {length:0};
    for (let i = 0; i < allSilings.length; i++) {
        if (allSilings[i]!==node){
            siblingsArray[siblingsArray.length] = allSilings[i];
            siblingsArray.length++;
        }
    }
    return siblingsArray;
}//添加或删除class//传入的第一个参数是结点,第二个参数是对象, 这个对象里是key:value,key就是要操作的class,value判断操作类型,true添加,false删除function addClass(node,object){
    for (let key in object){
        //对象调用方法的两种方式:
        // obj.f()
        // obj['f']()
 
        var methodName;
 
        methodName = object[key] ? 'add':'remove';
        node.classList[methodName](key);
 
        /*上面两句代码相当于
        if (object[key]) {
            node.classList.add(key);
        }else {
            node.classList.remove(key);
        }*/
    }
}window.mydom = {};
mydom.getSiblings = getSiblings;
mydom.addClass = addClass;//命名空间,常用的设计或者组合就叫做设计模式.哈希,数组,都是一种设计模式//所以jQuery就是这样来的,jQuery就是一个命名空间,里面有很多函数.
// 命名空间作用:1.方便识别库,2.如果都放在window里,可能会覆盖别的库,所以命名空间是为了防止覆盖别的函数
window.onload = function () {// 测试
 
    // 如何直接使用item3.addclass()?,item3.getSiblings()?
    // 方法一:给原型链加公有属性公有方法,但是有缺点,容易覆盖
    Node.prototype.getSiblings = function () {
        var allSilings = this.parentNode.children;//谁调用这个函数,this就是谁
        var siblingsArray = {length:0};
        for (let i = 0; i < allSilings.length; i++) {
            if (allSilings[i]!==this){
                siblingsArray[siblingsArray.length] = allSilings[i];
                siblingsArray.length++;
            }
        }
        return siblingsArray;
    }
    let item3 = document.getElementById('item3');
    // console.log(item3.getSiblings.call(item3));如果用cal.第一个参数就是函数里的this,如果不用call(),那么this就自动变成了item3
    console.log(' 方法一:');
    console.log(item3.getSiblings());//测试成功
 
    Node.prototype.addClass = function (object) {
        for (let key in object){
            var methodName;
            methodName = object[key] ? 'add':'remove';
            this.classList[methodName](key);
        }
    }
    // item3.addClass.call(item3,{a:true,xxx:false,c:true});;如果用call.第一个参数就是函数里的this,如果不用call(),那么this就自动变成了item3
    console.log(' 方法一:');
    item3.addClass.call(item3,{a:true,xxx:false,c:true});
    // item3.addClass({a:true,xxx:false,c:true});
    console.log(item3);//测试成功
 
 
    // 如何直接使用item3.addclass()?,item3.getSiblings()?
    // 方法二:因为方法一在原型中添加函数容易覆盖,所以自己做一个类似的Node出来
    var Node2 = function (node) {// 将要操作的结点传进去,然后返回一个对象,这个对象里给添加了有操作这个节点方法,所以对象.方法就可以实现操作了,而不需要mydom.addclass(item3,...)这样了
        return{
            getSiblings: function () {
                var allSilings = node.parentNode.children;
                var siblingsArray = {length:0};
                for (let i = 0; i < allSilings.length; i++) {
                    if (allSilings[i]!==node){
                        siblingsArray[siblingsArray.length] = allSilings[i];
                        siblingsArray.length++;
                    }
                }
                return siblingsArray;
            },
            addClass:function (object) {
                for (let key in object){
 
                    var methodName;
 
                    methodName = object[key] ? 'add':'remove';
                    node.classList[methodName](key);
 
                }
            }
        }
    }
    let item4 = document.getElementById('item4');
 
    var item4obj = Node2(item4);
 
    console.log(' 方法二:');
    console.log(item4obj.getSiblings());//测试成功
 
    console.log(' 方法二:');
    item4obj.addClass({a:true,xxx:false,c:true});
    console.log(item4);//测试成功
 
    // 改为jQuery
    var jQuery = function (nodeOrSelector) {//将Node2改为jQuery,jQuery可以根据选择器去找到对应的元素
        var node;
        if(typeof nodeOrSelector==="string"){
            node = document.querySelector(nodeOrSelector);
        }else {
            node = nodeOrSelector;
        }
        return{
            getSiblings: function () {
                var allSilings = node.parentNode.children;
                var siblingsArray = {length:0};
                for (let i = 0; i < allSilings.length; i++) {
                    if (allSilings[i]!==node){
                        siblingsArray[siblingsArray.length] = allSilings[i];
                        siblingsArray.length++;
                    }
                }
                return siblingsArray;
            },
            addClass:function (object) {
                for (let key in object){
                    var methodName;
                    methodName = object[key] ? 'add':'remove';
                    node.classList[methodName](key);
                }
            }
        }
    }
    let item5 = document.getElementById('item5');
 
    var $item5 = jQuery(item5);
    console.log(' 改为jQuery方法:');
    console.log($item5.getSiblings());
 
    console.log(' 改为jQuery方法:');
    $item5.addClass({red:true,xxx:false,c:true});
    console.log(item5);//测试成功
     var child3 = jQuery('ul>li:nth-child(3)');
     child3.addClass({blue:true});
 
 
     // jQuery操作多个节点
    var jQueryS = function (nodeOrSelector) {
        var node = {};
        if (typeof nodeOrSelector ==='string'){
            var temp = document.querySelectorAll(nodeOrSelector);//先用querySelectorAll获取这个伪数组
            for (let i = 0; i < temp.length; i++) {
                node[i] = temp[i];
            }
            node.length = temp.length;//将伪数组净化,净化成只有0123值和length的伪数组
 
        } else if(nodeOrSelector instanceof Node){// 如果是node,也将其转化成伪数组
            node[0] =nodeOrSelector;
            node.length = 1;
        }
        node.getSiblings = function () {
 
        };
        node.addClass = function (classesArray) {//传入class数组,给选择的多个节点都加上数组中class
            classesArray.forEach(value=>{
                for (let i = 0; i < node.length; i++) {
                    node[i].classList.add(value);
                }
            })
        }
        node.getTexts = function () {
            var texts=[];
            for (let i = 0; i < node.length; i++) {
                texts.push(node[i].textContent);
            }
            return texts;
        }
        node.setTexts = function (text) {
            for (let i = 0; i < node.length; i++) {
                node[i].textContent = text;
            }
        }
 
        //set和get合并
        node.text = function (text) {
            if (text===undefined){
                var texts=[];
                for (let i = 0; i < node.length; i++) {
                    texts.push(node[i].textContent);
                }
                return texts;
            }else{
                for (let i = 0; i < node.length; i++) {
                    node[i].textContent = text;
                }
            }
        }
        return node;
    }
 
    var allNodes = jQueryS('ul>li:nth-child(even)');//偶数孩子
    allNodes.addClass(['big','green']);
    console.log(allNodes.getTexts());
    console.log(allNodes.text());
    // console.log(allNodes.text(1));//测试成功
 
    //总结:jQuery的作用就是将选择其选择的元素放到一个对象里,这个对象里有01234标序,代表每一个选择的元素,有length代表所有元素加起来总共的长度,有各种方法,addclass,gettext等等.就是反悔了这样一个hash
};

 

UseJquery.js

var $nodes = $('ul>li:nth-child(even)');//注意$nodesjQuery声明的变量前面要加一个$,防止混淆,因为jQuery声明的变量只能用jQuery的api,不能用dom的api. console.log($nodes); 
x.onclick = function () { 
          $nodes.toggleClass('pink');//toggle,开关,切换 
          // console.log(1); 
} 
var colorArray = ['blue','yellow','red','pink','big'] 
var $nodes2 = $('#ol2>li'); 
$nodes2.addClass(function (index,currentClass) { 
          return colorArray[index];
          //ol里面的每一个li加了'blue','yellow','red','pink','big'这几个属性
 }) //https://www.jquery123.com/addClass/
 

2、jQuery的原型

测试代码:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.0.js"></script>
    <script>
        console.log($.prototype)
        console.log($.prototype.__proto__)
        console.log($.prototype.__proto__ === Object.prototype)//继承自Object
    </script>
</head>
<body>
 
</body>
</html>

结果如下:


就像Boolea,Array一样,
他的原型就是jQuery.prototype

  1. 自己实现jQuery的例子
var myjQueryS = function(node){
    var Node = {}
    Node.length = 0
    if((typeof node)==='string'){
        var nodearr  = document.querySelectorAll(node)
        for (let index = 0; index < nodearr.length; index++) {
            let element = nodearr[index];
            Node[index] = element
            Node.length++
        }
    }else{
        Node['0'] = node
        Node.length++
    }
    Node.addClass = function(addclass){
        for (let index = 0; index < Node.length; index++) {
            let element = Node[index]
            element.classList.add(addclass)
        }
    }
    Node.text = function(text){
        if(text===undefined){
            let textArr = []
            for (let index = 0; index < Node.length; index++) {
                let element = Node[index]
                textArr.push(element.textContent)
            }
            return textArr
        }else{
            for (let index = 0; index < Node.length; index++) {
                let element = Node[index]
                element.textContent = text
            }
        }
    }
    return Node
}
var $div = myjQueryS('div')
console.log($div)
$div.addClass('xxx')
console.log($div.text())
// $div.text('xxx')
 

六、参考资料

1、如何实现一个简化版的 jQuery

https://www.jianshu.com/p/139154f2972f

2、自己封装的简易版jQuery

https://blog.csdn.net/weixin_42755677/article/details/92637467

3、AJAX 教程-w3school

https://www.w3school.com.cn/ajax/index.asp

4、jQuery ajax - ajax() 方法

https://www.w3school.com.cn/jquery/ajax_ajax.asp

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值