...

jQuery 基础复习&整理

jQuery 基础复习&整理

1. 入口函数

Q:$是什么?$()和jQuery()有区别吗?
其实没区别,就是为了区分开来,都属于函数名字。都能直接调用。
Q:JavaScript入口函数是什么?jQuery入口函数是什么?
$(function(){}) 这就是jQuery的入口函数

$(document).ready(function(){}) // 入口函数  
$(function(){})  // 入口函数  

这里有一个感觉,就是写JavaScript的时候多用 obj = function(){} 但是写jQuery的时候都在方法()里面写。比如ready(function(){})
JavaScript是在整个dom加载完,包括图片和文档。但是jQuery则在dom框架加载完就开始执行,所以速度上要比JavaScript快一点。

window.onload = function(){  
  console.log('JS!!!')  
}  
$(document).ready(function(){  
  console.log(' JQ method 1')  
})  
$(function(){  
  console.log('JQ method 2')  
})  
// 有图片和文档等加载的情况下,jQuery是明显快于js的。  

2. DOM对象问题

Q:jQuery对象和JavaScript对象有区别吗?JavaScript能用jQuery的对象吗?jQuery能用JavaScript的对象吗?
jQuery其实就是封装了JavaScript一堆方法的伪数组(没有数组的方法,有自己的方法),是一个对象的集合。里面封装了大量的方法。JavaScript是原生的dom对象,而jQuery对象则是数组对象
不要混用,不是同一个对象,DOM是DOM对象。jQuery是jQuery对象。

var buttonObj = document.getElementById('#button')  
// 一般加上$表示是一个jQuery对象  

JavaScript DOM对象不能调用jQuery对象方法。PS:但是入口函数里可以写JS!(感觉这是废话

console.log($()) // 打印一下就出来了  
console.log(document.getElementById('#button'))  

那怎么才能调用的,进行对象转换。

互相转换问题

jQuery 转换 JavaScript

// jQuery => js jQuery是一个伪数组,index为0的就是一个DOM对象  
var buttonDom = $buttonObj[0] // 方法1 推荐使用  
var buttonDom = $buttonObj.get(0) // 方法2  

JavaScript 转换成 jQuery

// jQuery => JavaScript jQuery是一个伪数组,index为0的就是一个DOM对象  
var buttonDom = $buttonObj[0] // 方法1 推荐使用  
var buttonDom = $buttonObj.get(0) // 方法2  
// JavaScript => jQuery 用$()把DOM对象包装起来,就可得到jQuery对象  
var buttonObj = document.getElementById('#button')  
var $buttonObj = $(buttonObj)  

// 测试一下(记得要加载jQuery)  
var bodyObj = document.querySelector('body')  
var $bodyJqObj = $(bodyObj)  
var bodyJqObjEle = $bodyJqObj[0]  
console.log(bodyObj === bodyJqObjEle) // true  

后面自己在做案例的时候一个心得就是这俩对象拥有的方法不一样,所以在使用的时候,尤其在遍历或者获得一些属性的时候,就需要互相转换。比如播放音乐load() play() 这两个方法在jQuery里并没有,所以需要的就是通过jQuery.get(index),转换成JS对象才能使用。

小案例:隔行变色

$(function(){  
    // Q: 为什么这里的DOM对象可以使用jQuery的方法  
    // A: lis是一个jQuery对象,但是lis[i]是DOM对象  
    let lis = document.getElementsByTagName("li")  
    for(let i = 0;i<lis.length;i++){  
        if (i % 2 == 0) {  
            lis[i].style.backgroundColor = 'green'  
        } else {  
            lis[i].style.backgroundColor = 'purple'  
        }  
    }  
})  

Q:$是什么?能干什么?
$本质上就是一个函数,console.log($)这样就可以查看到了。

  • 参数是一个 function 入口函数
  • 参数是一个字符串,用来找对象
  • 转换 DOM 对象为 jQuery
$(function(){});console.log(typeof $) // 参数是一个function入口函数  
$("#id");$("div");$(".class")  // 参数是一个字符串,用来找对象  
$(document).ready(function(){}) // 转换DOM对象为jQuery对象,$(document)本来并没有ready这个方法哦  

3. 选择器问题

首先要给自己说一下就是选择一个元素的时候并不是只有一种方法,很多选择器都可以指向同一个目标。所以不必纠结正确方法,只要完成目标和目的,我觉得就可以理解。而且基本选择器的写法跟CSS真的有很多不谋而合之处。学好了CSS之后再来看会更加容易。

基本选择器 层级选择器 过滤选择器
筛选选择器(方法)除了它 其他都写在字符串里面
这些在官方文档上都有详细的例子,自己要知道的就是选择器有哪几种种类,这样在遇到问题的时候可以快速定位到就好。
因为自己每一次需要查找的时候都绞尽脑汁,所以差不多就这样做了。其实直接增加一个id属性是最快的。
筛选选择器的问题,筛选选择器和过滤选择器都可以。只不过筛选选择器是方法。
this只是一个DOM对象,但是用$(this)包裹之后就是一个 jQuery 对象了

4. 隐式迭代问题

一次性设置多个属性

// 普通书写方式  
$("li").css("backgroundColor", "red")  
$("li").css("fontSize", "50px")  
$("li").css("color", "green")  
$("li").css("width", "100px")  

// 可以直接修改多个样式写成对象的形式  
$("li").css({  
    backgroundColor: "pink",  
    fontSize: "50px",  
    color: "green",  
    width: "100px"  
})  

设置的时候可以使用隐式迭代这样进行设置,但是获取一个元素属性的时候。不可以一次性获取全部的样式。

console.log($("li").css("backgroundColor")) // rgb(255, 192, 203)  
// 但是如果想直接获取所有li元素的背景颜色,只会输出第一个属性的值  

5. 链式操作问题

$().css().parent() 这样每一次调用返回的都是一个 jQuery 对象,所以可以进行链式操作。
链式操作每一次的返回值都是一个jQuery对象,如果返回的不是,或者那个时候this已经改变了指向,那么就要重新进行。
这里引入一个end()方法。其实使用$(this)增加可读性比较好。

大多数 jQuery 的遍历方法会操作一个 jQuery 对象实例,并生成一个匹配不同 DOM 元素集的新对象。当发生这种情况时,应该会把新的元素集推入维持在对象中的堆栈内。每次成功的筛选方法调用都会把新元素推入堆栈中。如果我们需要老的元素集,可以使用 end() 从堆栈中弹出新集合。

比如下面这个案例。五星案例。

<ul class="comment">  
    <li></li>  
    <li></li>  
  <li></li>  
  <li></li>  
  <li></li>  
</ul>  
<script>  
    $(function(){  
        let = starSolid = "★"  
        let = starHollow = "☆"  
        // $(".comment>li") 表示comment类下面所有li  
        // 鼠标经过,所有前面变成实心  
        $(".comment>li").on("mouseenter", function(){  
            console.log($(this).text(starSolid)) // 下面图片有log  
            console.log($(this).text(starSolid).prevAll())  
            console.log($(this).text(starSolid).prevAll().text(starSolid))   
            $(this).text(starSolid).prevAll().text(starSolid) //这里要注意为什么不继续链式下去了  
            $(this).nextAll().text(starHollow) // 因为这里this并不是指licurrent那个jQ对象了,而是前面所有  
          // 解决这个问题其实还有一个方法。就是使用end()这个方法。  
            $(this).text(starSolid).prevAll().text(starSolid).end().nextAll().text(starHollow)  
        })  
        $(".comment").on("mouseleave", function(){  
            $(this).children().text(starHollow)  
            $("li.current").text(starSolid).prevAll().text(starSolid)  
        })  
        $(".comment>li").on("click", function(){  
            $(this).addClass("current").siblings().removeClass("current")  
        })  
    })  
</script>  

6.设置style类的问题

修改样式的时候不一定这样css一个个进行添加,也可以统一设置成一个类,然后统一进行添加一个类

<style>  
    .small {  
        font-size: 5px;  
    }  
    .big {  
        font-size: 200px;  
    }  
</style>  
<button id="makesmall" type="submit">变小</button>  
<button id="makebig" type="submit">变大</button>  
<div id="div1">1111</div>  
<script>  
    // js原生写法 这样写并不好维护,因为类名如果变了,那么js里也要修改  
    let smallButton = document.getElementById("makesmall")  
    let bigButton = document.getElementById("makebig")  
    let divObj = document.getElementById("div1") //这里用id才行,tagName失败  
    smallButton.onclick = function(){  
        divObj.className = "small"  
    }  
    bigButton.onclick = function(){  
        divObj.className = "big"  
    }  
    // jq  
    $("#makesmall").on("click", function(){  
        $("#div1").addClass("small")  
    })  
    $("#makebig").on("click", function(){  
        $("#div1").addClass("big")  
    })  
    $("#removebig").on("click", function(){  
        $("#div1").removeClass("big")  
    })  
    $("#issmall").on("click", function(){  
        console.log($("#div1").hasClass("small"))  
    })  
    // 写法1 切换  
    $("#shiftclass").on("click", function(){  
        if($("#div1").hasClass("small")){  
            $("#div1").removeClass("small")  
        } else {  
            $("#div1").addClass("small")  
        }  
    })    
    // 写法2 切换 toggleClass  
    $("#shiftclass").on("click", function(){  
        $("#div1").toggleClass("small")  
    })  
</script>  

这个道理和attr也是共通的。
attr表示的是属性操作,是操作标签内的内容。样式可以用css来操作$(obj).css("","")这样写,但是标签内的属性。就必须使用attr了。

<img src="" alt="" title="修改前">  
// 修改title的名字  
$(function(){  
  $("img").attr("title", "修改后")   
  $("img").css("title", "修改后") ×  
})  

一次性设置多个属性

$(function(){  
    $("img").attr({  
        title: "修改后2",  
        alt: "新的alt",  
        test: "自定义属性"  
    })  
})  

先补一个小tips,为了防止冒泡,JQ里面使用 return false 下面也有解释阻止冒泡的方法。

7. 关于prop和attr问题

在一些属性为Boolean值的上面,需要使用prop来进行获取。比如checked,disabled,selected这样的数值。
这里可以有一个案例来实现。并非完全版本的小demo


8. 关于动画animate()

show() hide()
fadeIn() fadeOut() fadeToggle()
slideUp() slideDown() slideToggle() 发现一个坑,就是JQ版本3并不支持这个。
animate()=> 这个函数的参数太多,自己查。
这些动画效果都会有一个动画队列,就是当你触发一个事件之后这个动画事件一直在队列中进行等待。一个接着一个这样按照顺序。
jQuery可以通过在调用动画函数之前利用 stop() 进行终止这个队列
好处:可以使动画有顺序的进行移动
坏处:会有残余
参数问题:https://api.jquery.com/animate/

<button id="start" type="submit">开始</button>  
<button id="stop" type="submit">结束</button>  
<div class="div1"></div>  

$(function(){  
    $("#start").on("click", function(){  
        $(".div1").slideDown(2000).slideUp(2000)  
    })  
    $("#stop").on("click", function(){  
       // 参数1 clearQueue 是否清除动画队列  
             // 参数2 jumpToEnd 是否跳转到当前动画最终效果  
             // 默认是false false  
        $(".div1").stop(true,true)  
    })  
})  

9. 操作节点问题

动态创建节点

<div id="box" >ok</div>  
<script>  
    // 如果要创建一个节点 例如  
    // <a href="https://google.com" target="_blank">HELLO Google</a>  
    $(function(){  
        // JS写法  
        let box = document.getElementById("box")  
        let a = document.createElement("a")  
        box.appendChild(a)  
        a.setAttribute("href", "https://google.com")  
        a.setAttribute("target", "_blank")  
        a.innerHTML = "HELLO Google"  
        // JQ写法1  
        let a = "<a href='https://google.com' target='_blank'>HELLO Google</a>"  
        $("#box").append(a)  
        // JQ写法2  
        $a = $("<a href='https://google.com' target='_blank'>HELLO Google</a>")  
        $("#box").append($a)  
    })  
</script>  

append() 最后面
appendTo()虽然也是最后面,但是就是调用者不一样。
prepend()最前面
prependTo()同上
after()添加到自己后面 作为兄弟元素
before()添加到自己前面 作为兄弟元素

清空节点

html()这个可能会造成内存泄漏,因为html只能清空内容不能清空事件。(占用客户端内存。
empty() 这个就不会。
remove() 可以自己删除自己。自杀。
val("") 这种清空的是内容

克隆的话

$("#id").clone()克隆出来的是深度复制。
falseclone(false)深复制 不会复制事件。
true clone(true) 深复制 会复制事件。

10. 获取属性 val()

attr() val() 其实都可以获取值,但一般会使用val(),操作value属性的方法。

<input type="button" value="hello" id="btn">  
$(function(){  
  console.log($("#btn").val()) // hello  
    console.log($("#btn").attr("value")) // hello  
})  

11. html() PK text()

本质上是JavaScript的 innerHTML 和 innerText 的区别

//<div><h3>>我是h3</h3></div  
$(function(){  
  console.log($("div").html()) // <h3>>我是h3</h3>  
  console.log($("div").text()) // 我是h3  
  $("div").html("<p>我是P文本</p>") // 解释标签  
  $("div").text("<p>我是P文本</p>") // 直接输出 所以可以防止XSS攻击那种  
})  

css 宽高 方法
有参数就是设置,没参数就是获取。

css("width",400)   
width(400) // 效果一样  
innerWidth() // 包括width + padding  
outerWidth() // 包括width + padding + border  
outerWidth(true) // 包括width + padding + border + margin  

12.事件委托

事件委托使用的场景之一就是,动态创建元素。

bind() delegate() on()

bind()现在几乎不用了 动态创建元素无法有事件
delegate() 利用冒泡触发父元素给子元素触发事件 动态创建元素有事件

$("#div").delegate("p", "click", function(){}{console.log(this)// p元素})   

on就是集大成了,现在是统一方案。既可以给自己注册简单事件,也可以委托事件。
到底什么是事件委托呢。本质就是冒泡给父亲,父亲触发给孩子执行的玩意儿。
一个案例实现以下动态创建事件的问题。代码如下。
设置一个table,每添加一条数据就有一个删除键。

// 正常创建元素   
// 会发现新增的行无法进行删除  
$("button").on("click", function(){  
    $(`<tr>  
        <td>新的NEW香蕉</td>  
        <td>新的NEW2公斤</td>  
        <td>新的NEW6元/公斤</td>  
        <td><a href="javascript:void(0);" class="delete">×</a></td>  
    </tr>`).appendTo("tbody")  
})  
$(".delete").on("click", function(){  
    $(this).parent().parent().remove()  
})  

// 动态绑定 注意!这时候不能给 .delete这个类进行绑定,需要给共通的父元素。也就是tbody进行绑定  
$("tbody").on("click", ".delete", function(){  
    //console.log(this) // 会发现这个this <a href="javascript:void(0);" class="delete">×</a>  
    $(this).parent().parent().remove() // 所以跟上面写法一模一样  
})  

事件解绑VS事件触发

on() 相对应 off(),用off()可以直接接触绑定。
也可以直接使用
对象.trigger(事件名)
对象.事件名()

事件对象

// 那个function里面的e  
$("tbody").on("click", ".delete", function(e){  
    console.log(e)  
})  

重点的几个事件对象里面的属性,e.data。这个方法输出的就是在on()触发事件的时候,第三个参数。可以把外面的参数拿进来。

// 由于let是一个全局变量的情况下。那么想把这个age传送到事件的回调函数里面的话。就可以使用e.data进行传递   
$(function(){  
        var age = 18  
    $("div").on("click", function(){  
      console.log(age)  
    })  
    var age = 20  
        $("p").on("click", age, function(e){  
      console.log(e.data) // 这样就可以传送进去了  
    })  
  })  

事件执行顺序

结论;自身事件,委托事件,父元素自身事件。
代码验证。

<button type="submit">点我添加</button>  
<div><p> 我是老P </p></div>  
<script>  
$("button").on("click",function(){  
    $("<p>我是新增的P</p>").appendTo("div")  
})  
$("div").on("click", function(){  
    console.log(this)  
    console.log("我是爸爸")  
})  
$("div").on("click", "p", function(){  
    console.log(this)  
    console.log("P元素委托事件")  
})  
$("p").on("click", function(){  
    console.log(this)  
    console.log("P元素自身事件")  
})  
// 点击新增的p <p>我是新增的P</p> // 元素委托事件 我是爸爸  
// 点击老P P元素自身事件->P元素委托事件->我是爸爸  
</script>  

13. 冒泡和默认行为

冒泡。自己干的老子也要连累触发的东西。
默认行为。标签自带属性。比如a就是点击跳转。

<a href="https://google.com" class="delete">×</a>  
<script>  
$("a").on("click", function(){  
  console.log("click a")  
})  
// 如果这时候进行点击发现还有a标签自带的跳转属性存在,如果想阻止这种默认跳转行为就需要有这几个方法  
$("a").on("click", function(){  
  console.log("click a")  
  e.preventDefault()  
  e.stopPropagation()  
  return false    // 既能阻止冒泡又能阻止默认行为  
})  
</script>  

这些只是常用的用法。节流阀问题。就是设置一个flag,如果一个事件没完成那么下一个就不会立起flag。

关于each()

// 使用JQ的方法进行遍历对每一个li元素进行遍历改变透明度  
// 使用这个可能会有变量污染的问题 其实es6之后let可以避免  
for(var i = 0;i < $("li").length;i++){  
  $("li").eq(i).css("opacity", (i+1)/10)  
}  
// 使用each()  
// @index  下标   
// @element DOM元素  
$("li").each(function(index,element){  
  $(element).css("opacity", (index+1)/10) // 转换成JQ元素  
})  

解决冲突问题

引入不同模块的$问题,万一两个模块都有同一个$可以使用JQ的方法进行释放。

<script src="引入非jq模块"></script>  
<script src="引入jQuery模块"></script>  
console.log($) // 这样后面JQ模块会覆盖掉前面的$  
// 解决方法   
$.noConflict() // 方法1:JQ主动释放$对象 以后$就可以用jQuery代替 这样的情况下入口函数就是jQuery  
let dollar = $.noConflict() // 方法2:赋值给一个替身,这样dollar就是$  
let $$ = $.noConflict() // 这样写也很直观  

14. 关于插件问题

如何使用插件?

仔细阅读插件文档。学好英语!!!

如何自己制作一个插件?

原理就是使用构造函数给jQuery增加一个公共方法。插件的本质不就是自己写一个函数大家都能用吗。。
比如,一个超简单的插件

// 原理  
jQuery.prototype.plugins = function(){  
    console.log("自制插件")  
}  
// 在js里可以查找到 jQuery.fn = jQuery.prototype = {}   
// 简化版本  
$.fn.plugins = function(){  
    console.log("自制插件")  
}  
$(document).plugins()  

实现一个超级简单的插件,调用big()字体就能变大。
平常使用jq的时候就是。
$("p").css("font-size", "100px")

<p>hello</p>  
<script>  
$(function(){  
    $.fn.big = function(size){  
    // 这里this是JQ对象 console.log(this)  
    this.css("font-size", size+"px")  
}  
    $("p").big(200)  
})  
  // 但是这样把big方法导入到新的js发现会无法继续链式调用。  
  // 这时候在方法里要加上return this 把JQ对象推出去  
  $(function(){  
    $.fn.big = function(size){  
        this.css("font-size", size+"px")  
    }  
    return this  
})  
</script>  

此处缺少一个像样的插件demo

共有评论(1)

...
giegie

yes

2021-07-24
登陆即可评论哦