jQuery原理——26——根据dom操作(insertBefore,replaceAll)编写自己的jQuery框架

HTML测试代码

<!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="../jQuery/jquery-3.4.1.min.js"></script> -->
    <script src="../jQuery/sjQuery.js"></script>
    <script>
        $(function () {
            var btn = document.getElementsByTagName('button')[0];
            btn.onclick = function () {
                //insertBefore和prependTo类似,不同的是insertBefore是将元素插入到外部的最前面
                // $("p").insertBefore(".item");
                function insertBefore(source, target) {
                    /*
                    调用者.insertBefore(插入的元素,参考的元素);
                    insertBefore方法,调用者是谁就会将元素插入到谁里面

                    思路,可以找参考元素的父级元素body,这样插入的元素和参考的元素就是同级的了
                    */
                    //1.拿到指定元素的父元素
                    var parent = target.parentNode;
                    //2.利用指定元素的父元素来调用insertBefore方法
                    parent.insertBefore(source, target)

                }
                var p = document.querySelector('p');
                var div = document.querySelector('div');
                // insertBefore(p, div);

                //replace方法
                $("p").replaceAll("li");
        
                //原生js实现方法
                function replaceAll(source, target) {
                    //思路:将p插入到li前面,再将li删除

                //1.将元素插入到指定元素的前面
                $(source).insertBefore(target);
                //2.将指定元素删除
                $(target).remove();
                }
                var p = document.querySelector("p");
                var li = document.querySelector("li");
                // replaceAll(p, li);
            }
        });
    </script>
</head>

<body>
    <button>测试方法</button>
    <div class="item">
        <p>我是段落</p>
        <li>我是第1个li</li>
        <li>我是第2个li</li>
        <li>我是第3个li</li>
    </div>
    <div class="item">
        <li>我是第1个li</li>
        <li>我是第2个li</li>
        <li>我是第3个li</li>
    </div>
</body>

</html>

编写自己的jQuery框架 sjQuery.js 代码389-448行

 (function (window, undefined) {
     var sjQuery = function (selector) {
         return new sjQuery.prototype.init(selector);
     }
     sjQuery.prototype = { //原型
         constructor: sjQuery,
         init: function (selector) {
             //0.去除字符串两边的空格 
             selector = sjQuery.trim(selector);
             //1.传入'' null undefined NaN 0 false,返回空的jQuery对象
             if (!selector) {
                 return this;
             } else if (sjQuery.insFuntion(selector)) {
                 // console.log('是方法');
                 sjQuery.ready(selector); //把传递进来的回调函数传递给ready方法

             }
             //2.字符串
             else if (sjQuery.isString(selector)) {
                 //2.1判断是否是代码片段<a>
                 if (sjQuery.isHTML(selector)) {
                     //console.log('代码片段');
                     //1.根据代码片段创建所有的元素
                     var temp = document.createElement('div');
                     temp.innerHTML = selector;
                     // console.log(temp);
                     //2.将创建好的一级元素添加到jQuery当中
                     //   console.log(temp.children);//children方法
                     //  for (var i = 0; i < temp.children.length; i++) {
                     //      this[i] = temp.children[i];
                     //  }
                     //3.给jQuery对象添加length属性

                     //简化第2,3步
                     [].push.apply(this, temp.children);
                     //4.返回加工好的this(jQuery)
                     //  return this;
                 }
                 //2.2判断是否是选择器
                 else {

                     // 1.根据传入的选择器找到对应的元素
                     var res = document.querySelectorAll(selector);
                     // 2.将找到的元素添加到sjQuery上
                     [].push.apply(this, res);
                     // 3.返回加工上的this
                     //  return this;
                 }


             } //3.数组
             //   else if(typeof selector==='object'&&'length' in selector&&selector!==window){//window也是对象,并且length=0
             /*
           //3.1真数组
           if(({}).toString.apply(selector)==="[object Array]"){
            //   console.log('真数组');
            //真数组转换为伪数组
            [].push.apply(this,selector);
            // return this;
               
           }
           //3.2伪数组
           else{
        //    console.log('伪数组');
        //企业开发中,要将自定义伪数组转换为伪数组,首先将它转换为真数组
        //因为IE8及以下不能直接将自定义的伪数组包装成伪数组返回
        //将自定义的伪数组转换为真数组
        var arr=[].slice.call(selector);
        //将真数组转换为伪数组
        [].push.apply(this,arr);
        return this;
        
           }
           */
             //简化以上代码
             //将自定义的伪数组转换为真数组
             else if (sjQuery.isArray(selector)) {
                 var arr = [].slice.call(selector);
                 //将真数组转换为伪数组
                 [].push.apply(this, arr);
                 //   return this;
             }
             //除上述类型以外
             else {
                 this[0] = selector; //将其保存到jQuery
                 this.length = 1;
                 //  return this;
             }
             return this;
         },
         jQuery: "3.4.1", //模拟版本号
         selector: "", //默认为空
         length: 0,

         //[].push找到数组的push方法
         //冒号前面的push将由sjQuery对象调用

         //相当于[].push.apply(this);,把push内部的this替换成sjQUery对象
         push: [].push,
         sort: [].sort,
         splice: [].splice,
         toArray: function () {
             return [].slice.call(this);
         },
         get: function (num) {
             //没有传递参数
             if (arguments.length === 0) {
                 return this.toArray();
             }
             //传递参数,参数不是负数
             else if (num >= 0) {
                 return this[num];
             }
             //传递负数
             else {
                 return this[this.length + num];
             }
         },
         eq: function (num) {
             // 没有传递参数
             if (arguments.length === 0) {
                 return new sjQuery();
             } else {
                 return sjQuery(this.get(num));
             }
         },
         first: function (num) {
             return this.eq(0);
         },
         last: function (num) {
             return this.eq(-1);
         },
         each: function (fn) {
             return sjQuery.each(this, fn);
         },
         map: function (obj, fn) {

         }

     }
     sjQuery.extend = sjQuery.prototype.extend = function (obj) {
         for (var key in obj) {
             this[key] = obj[key];
         }
     }
     sjQuery.extend({ //key/value
         isString: function (str) {
             return typeof str === "string"
         },
         isHTML: function (str) {
             return str.charAt(0) == "<" && str.charAt(str.length - 1) == ">" && str.length >= 3
         },
         trim: function (str) {
             //如果不是字符串,则不用去除空格
             if (!sjQuery.isString(str)) {
                 return str;
             }
             //判断是否支持trim方法
             if (str.trim) {
                 return str.trim();
             } else {
                 return str.replace(/^\s+|\s+$/g, ''); //用空串代替空格字符串
             }
         },
         isObject: function (sele) {
             return typeof sele === "object"
         },
         isWindow: function (sele) {
             return sele === window;
         },
         isArray: function (sele) {
             if (sjQuery.isObject(sele) &&
                 !sjQuery.isWindow(sele) &&
                 "length" in sele) {
                 return true;
             }
             return false;
         },
         insFuntion: function (sele) {
             return typeof sele === 'function';
         },
         ready: function (fn) { //当传入的是方法函数类型,当判断页面的DOM元素加载完后开始执行代码,比如body里有div,若没有等dom加载完就执行代码,会找不到div
             //判断DOM是否加载完毕
             if (document.readyState == "complete") {
                 fn(); //直接回调
             } else if (document.addEventListener) { //如果浏览器兼容此方法
                 document.addEventListener('DOMContentLoaded', function () {
                     fn();
                 })
             } else {
                 document.attachEvent('onreadystatechange', function () { //attachEvent不兼容火狐谷歌
                     if (document.readyState == "complete") {
                         fn();
                     }
                 })
             }

         },
         each: function (obj, fn) {
             // 1.判断是否是数组
             if (sjQuery.isArray(obj)) {
                 for (var i = 0; i < obj.length; i++) {
                     // var res = fn(i, obj[i]);
                     var res = fn.call(obj[i], i, obj[i]);
                     if (res === true) {
                         continue;
                     } else if (res === false) {
                         break;
                     }
                 }
             }
             // 2.判断是否是对象
             else if (sjQuery.isObject(obj)) {
                 for (var key in obj) {
                     // var res = fn(key, obj[key]);
                     var res = fn.call(obj[key], key, obj[key]);
                     if (res === true) {
                         continue;
                     } else if (res === false) {
                         break;
                     }
                 }
             }
             return obj;
         },
         map: function (obj, fn) {
             var res = [];
             // 1.判断是否是数组
             if (sjQuery.isArray(obj)) {
                 for (var i = 0; i < obj.length; i++) {
                     var temp = fn(obj[i], i);
                     if (temp) {
                         res.push(temp);
                     }
                 }
             }
             // 2.判断是否是对象
             else if (sjQuery.isObject(obj)) {
                 for (var key in obj) {
                     var temp = fn(obj[key], key);
                     if (temp) {
                         res.push(temp);
                     }
                 }
             }
             return res;
         }
     });
     sjQuery.prototype.extend({
         empty: function () {
             //1.遍历所有找到的元素
             this.each(function (key, value) {
                 value.innerHTML = "";
             });
             //2.方便链式编程
             return this;
         },
         remove: function (sele) {
             if (arguments.length == 0) {
                 //1.遍历指定的元素
                 this.each(function (key, value) {
                     //js中,元素不能删除自己,只能通过这个元素找到其父元素,再通过父元素删除它
                     //根据遍历到的元素找到对象的父元素
                     var parent = value.parentNode;
                     //通过父元素删除指定的元素
                     parent.removeChild(value);
                 });
             } else {
                 var $this = this;
                 //1.根据传入的选择器找到对应的元素
                 $(sele).each(function (Key, value) {
                     //2.遍历找到的元素,获取对应的类型
                     var type = value.tagName;
                     //3.遍历指定的元素
                     $this.each(function (k, v) {
                         //4.获取指定元素的类型
                         var t = v.tagName;
                         //5.判断找到元素的类型和指定元素的类型
                         if (t === type) {
                             //根据遍历到的元素找到对象的父元素
                             var parent = value.parentNode;
                             //通过父元素删除指定的元素
                             parent.removeChild(value);
                         }
                     })
                 })


             }

             return this;
         },
         html: function (content) {
             if (arguments.length === 0) { //没有传参
                 return this[0].innerHTML;
             } else {
                 this.each(function (key, value) {
                     value.innerHTML = content;
                 })
             }
         },
         text: function (content) {
             if (arguments.length === 0) {
                 var res = "";
                 //遍历元素,用字符串拼接
                 this.each(function (key, value) {
                     res += value.innerText;
                 });
                 return res;
             } else {
                 this.each(function (key, value) {
                     value.innerText = content;
                 })
             }
         },
         appendTo: function (sele) {
             var $target = $(sele);
             var $this = this; //$("p").appendTo(".item");p是source元素,也就是this,谁调用谁就是this
             var res = [];
             //1.1遍历取出所有指定的元素target
             $.each($target, function (key, value) {

                 //1.11遍历取出所有的元素source
                 $this.each(function (k, v) {
                     //1.2判断当前是否是第0个指定的元素 因为本来放在了第一个div后面的p,在遍历到第二个div时,将第一个div的p放到了第二个div后面,所以需要克隆p
                     if (key === 0) {
                         //直接添加
                         value.appendChild(v);
                         res.push(v);
                     } else {
                         //先拷贝再添加
                         var temp = v.cloneNode(true);
                         value.appendChild(temp);
                         res.push(temp);
                     }
                 })


             });
             //返回所有添加的元素
             return $(res);
         },
         prependTo: function (sele) {
             //统一将传入的数据转换为jQuery对象
             var $target = $(sele);
             var $this = this; //$("p").appendTo(".item");p是source元素,也就是this,谁调用谁就是this
             var res = [];
             //1.1遍历取出所有指定的元素target
             $.each($target, function (key, value) {

                 //1.11遍历取出所有的元素source
                 $this.each(function (k, v) {
                     //1.2判断当前是否是第0个指定的元素 因为本来放在了第一个div后面的p,在遍历到第二个div时,将第一个div的p放到了第二个div后面,所以需要克隆p
                     if (key === 0) {
                         //直接添加
                         value.insertBefore(v, value.firstChild);
                         res.push(v);
                     } else {
                         //先拷贝再添加
                         var temp = v.cloneNode(true);
                         value.insertBefore(temp, value.firstChild);
                         res.push(temp);
                     }
                 })


             });
             //返回所有添加的元素
             return $(res);
         },
         append: function (sele) {
             //判断传入的参数是否是字符串
             if (sjQuery.isString(sele)) { //如果是字符串,直接添加
                 this[0].innerHTML += sele; //jQuery对象没有innerHTML,只有原生的DOM元素中才有,要从对象上取出DOM元素,就是this[0]
             } else {
                 $(sele).appendTo(this); //顺序和appendTo相反,其他功能都是一样的
             }
             return this;
         },
         prepend: function (sele) {
             //判断传入的参数是否是字符串
             if (sjQuery.isString(sele)) { //如果是字符串,直接添加
                 this[0].innerHTML = sele + this[0].innerHTML; //jQuery对象没有innerHTML,只有原生的DOM元素中才有,要从对象上取出DOM元素,就是this[0]
             } else {
                 $(sele).prependTo(this); //顺序和appendTo相反,其他功能都是一样的
             }
             return this;
         },
         insertBefore: function (sele) {
             //统一将传入的数据转换为jQuery对象
             var $target = $(sele);
             var $this = this; //$("p").appendTo(".item");p是source元素,也就是this,谁调用谁就是this
             var res = [];
             //1.1遍历取出所有指定的元素target
             $.each($target, function (key, value) {
                 var parent = value.parentNode;
                 //1.11遍历取出所有的元素source
                 $this.each(function (k, v) {
                     //1.2判断当前是否是第0个指定的元素 因为本来放在了第一个div后面的p,在遍历到第二个div时,将第一个div的p放到了第二个div后面,所以需要克隆p
                     if (key === 0) {
                         //直接添加
                         parent.insertBefore(v, value);
                         res.push(v);
                     } else {
                         //先拷贝再添加
                         var temp = v.cloneNode(true);
                         parent.insertBefore(temp, value);
                         res.push(temp);
                     }
                 })


             });
             //返回所有添加的元素
             return $(res);
         },
         replaceAll: function (sele) {
             // 1.统一的将传入的数据转换为jQuery对象
             var $target = $(sele);
             var $this = this;
             var res = [];
             // 2.遍历取出所有指定的元素
             $.each($target, function (key, value) {
                 var parent = value.parentNode;
                 // 2.遍历取出所有的元素
                 $this.each(function (k, v) {
                     // 3.判断当前是否是第0个指定的元素
                     if (key === 0) {
                         // 1.将元素插入到指定元素的前面
                         $(v).insertBefore(value);
                         // 2.将指定元素删除
                         $(value).remove();
                         res.push(v);
                     } else {
                         // 先拷贝再添加
                         var temp = v.cloneNode(true);
                         // 1.将元素插入到指定元素的前面
                         $(temp).insertBefore(value);
                         // 2.将指定元素删除
                         $(value).remove();
                         res.push(temp);
                     }
                 });
             });
             // 3.返回所有添加的元素
             return $(res);
         }
     })
     sjQuery.prototype.init.prototype = sjQuery.prototype;
     window.sjQuery = window.$ = sjQuery;
 })(window);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值