blog-hexo/source/_posts/front-end/jquery.md
2023-12-26 12:54:52 +08:00

456 lines
9.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: jQuery
categories:
- CS
status: done
abbrlink: 38683
---
# 基础
`window` 对象中挂载了 `$`和`jQuery`
```js
window.jQuery();
window.$ = window.jQuery;
```
# 模块化
## 原始写法
只要把不同的函数(以及记录状态的变量)简单地放在一起,就算是一个模块。
> 缺点很明显:"污染"了全局变量,无法保证不与其他模块发生变量名冲突,而且模块成员之间看不出直接关系。
```js
function m1() {
//...
}
function m2() {
//...
}
```
## 对象写法
把模块写成一个对象
> 写法会暴露所有模块成员,内部状态可以被外部改写。
```js
var module1 = new Object({
_count: 0,
m1: function () {
//...
},
m2: function () {
//...
},
});
// 使用
module1.m1();
```
## IIFE 立即执行函数写法[推荐]
> 外部代码无法读取内部的成员变量
```js
var module1 = (function () {
var _count = 0;
var m1 = function () {
//...
};
var m2 = function () {
//...
};
return {
m1: m1,
m2: m2,
};
})();
console.info(module1._count); //undefined
```
## (宽)放大模式
如果一个模块很大,必须分成几个部分,或者一个模块需要继承另一个模块,这时就有必要采用"放大模式"
```js
var module1 = (function (mod) {
mod.m3 = function () {
//...
};
return mod;
})(module1);
```
mod 可能存在异步,不知道内部哪个部分会先加载,如果采用上面的写法,第一个执行的部分有可能加载一个不存在空对象,这时就要采用"宽放大模式"。
```js
var module1 = (function (mod) {
//...
return mod;
})(window.module1 || {});
```
## 输入全局变量[推荐]
为了在模块内部调用全局变量,必须显式地将其他变量输入模块
```js
var module1 = (function ($, YAHOO) {
//...
})(jQuery, YAHOO);
```
# 链式操作
```js
$('div').find('#child').addClass('red')
// end() 函数返回上一级
$('div').find('#child').addClass('red').end().addClass'yellow'
```
# 选择器
## 筛选器
```js
// $('li').first()
$("li:first"); //第一个元素
// $('li').last()
$("li:last"); //最后一个元素
$("tr:even"); //索引为偶数的元素,从 0 开始
$("tr:odd"); //索引为奇数的元素,从 0 开始
// $("tr").eq(1)
$("tr:eq(1)"); //给定索引值的元素
$("tr:gt(0)"); //大于给定索引值的元素
$("tr:lt(2)"); //小于给定索引值的元素
$(":focus"); //当前获取焦点的元素
$(":animated"); //正在执行动画效果的元素
```
## 内容选择器
```js
$("div:contains('nick')"); //包含nick文本的元素
$("td:empty"); //不包含子元素或者文本的空元素
$("div:has(p)"); //含有选择器所匹配的元素
$("td:parent"); //含有子元素或者文本的元素
```
## 表单选择器
```js
$(":input"); //匹配所有 input, textarea, select 和 button 元素
$(":text"); //所有的单行文本框
$(":password"); //所有密码框
$(":radio"); //所有单选按钮
$(":checkbox"); //所有复选框
$(":submit"); //所有提交按钮
$(":reset"); //所有重置按钮
$(":button"); //所有button按钮
$(":file"); //所有文件域
$("input:radio[name=sex]:checked"); //所有name 尾input选中的元素
$("select option:selected"); //select中所有选中的option元素
```
## 查找
```js
$("#xxx"); //返回 一个 jquery 对象
$("#xxx").find(".xxx"); //查找#xxx里的.xxx元素
$("#xxx").parent(); //获取父类
$("#xxx").parents("xxx"); //获取xxx祖先
$("#xxx").children(); //获取子类
$("#xxx").siblings(); //获取同一父类的其他元素
$("#xxx").next(); //获取下一个元素
$("#xxx").prev(); //获取上一个元素
```
## 属性操作
```js
$("img").attr("src"); //返回文档中所有图像的src属性值
$("img").attr("src", "test.jpg"); //设置所有图像的src属性
$("img").removeAttr("src"); //将文档中图像的src属性删除
$("input[type='checkbox']").prop("checked", true); //选中复选框
$("input[type='checkbox']").prop("checked", false);
$("img").removeProp("src"); //删除img的src属性
```
## css 操作
```js
$("p").addClass("selected"); //为p元素加上 'selected' 类
$("p").removeClass("selected"); //从p元素中删除 'selected' 类
$("p").toggleClass("selected"); //如果存在就删除,否则就添加
$("p").css("color"); //访问查看p元素的color属性
$("p").css("color", "red"); //设置p元素的color属性为red
$("p").css({ color: "red", background: "yellow" }); // 设置多个属性
```
## 文档处理
内部插入
```js
$("p").append("<b>nick</b>"); //每个p元素内后面追加内容
$("p").appendTo("div"); //p元素追加到div内后
$("p").prepend("<b>Hello</b>"); //每个p元素内前面追加内容
$("p").prependTo("div"); //p元素追加到div内前
```
外部插入
```js
$("p").after("<b>nick</b>"); //每个p元素同级之后插入内容
$("p").before("<b>nick</b>"); //在每个p元素同级之前插入内容
$("p").insertAfter("#test"); //所有p元素插入到id为test元素的后面
$("p").insertBefore("#test"); //所有p元素插入到id为test元素的前面
```
## 复制
```js
$("p").clone(); //克隆元素并选中克隆的副本
$("p").clone(true); //布尔值指事件处理函数是否会被复制
```
# attr 和 prop 区别
prop 和 attr 均可获取属性值,但 prop 获取的是 `DOM 对象内置属性`
> !! 例如 inputradioslect 元素,请使用 prop 获取
```html
<img src="https://www.runoob.com/images/pulpit.jpg" />
<p tinyval="12"></p>
```
```js
// 因为页面源代码中没有设置 width 属性
$("img").attr("width"); // undefined
$("img").prop("width"); // 284
// 由于 tinyval 并非 HTML 标准属性
$("p").prop("tinyval"); // undefined
$("p").attr("tinyval"); // 12
```
# 事件
## 事件委托
- 可极大减少事件绑定次数,提高性能
- 可让动态加入的子元素绑定相同的命令
```js
function handleClick(event) {
// this 表示当前单击的元素
alert($(this).html());
}
// 把子级li元素的单击事件委托在父级ul身上
$("ul").delegate("li", "click", handleClick);
```
## 单事件单元素
```js
function handleClick() {}
$xxx.on("click", handleClick);
```
## 单事件多元素
```js
function handleClick() {}
$xxx.on("click", "#aaa, .bbb", handleClick);
```
## 多事件多元素
```js
function handleClick() {}
function handleMounseEnter() {}
$xxx.on(
{
click: handleClick,
mounseenter: handleMounseEnter,
},
"#aaa, .bbb"
);
```
## 一夜情事件
```js
function handleClick() {}
$xxx.one("click", handleClick);
```
# 对象操作
```js
$.trim(); //去除字符串两端的空格
$.each(); //遍历一个数组或对象for循环
$.inArray(); //返回一个值在数组中的索引位置,不存在返回-1
$.grep(); //返回数组中符合某种标准的元素
$.extend(true, {}, a, b); // 深浅拷贝合并 a、b 到 {} 上
$.makeArray(); //将对象转化为数组
$.type(); //判断对象的类别(函数对象、日期对象、数组对象、正则对象等等
$.isArray(); //判断某个参数是否为数组
$.isEmptyObject(); //判断某个对象是否为空(不含有任何属性)
$.isFunction(); //判断某个参数是否为函数
$.isPlainObject(); //判断某个参数是否为用"{}"或"new Object"建立的对象
$.support(); //判断浏览器是否支持某个特性
```
# 禁止右键功能菜单
```js
$(window).on({
contextmenu: function () {
return false;
},
keydown: function (e) {
if (e.ctrlKey || (e.metaKey && (e.keyCode === 67 || e.keyCode === 8)))
return false;
},
});
```
# 自动修改破损图像
```js
$("img").on("error", function () {
$(this).prop("src", "img/broken.png");
});
```
# 模块化 jquery 最佳实践
```js
// xx 视图模块 #xx
(function ($, $view) {
console.log($ + "has been imported");
// 缓存 dom需要用到的 dom提高性能
var $partA = $view.find(".partA"),
$partB = $view.find(".partB");
// 链式表结构,事件委托
$view
.on("focus", "#btnFocusPartA", handleBtnFocusPartA)
.on("click", ".btnClickPartB", handleBtnClickPartB);
// 方法,建议函数式
function handleBtnFocusPartA() {
console.log($partA + "handler");
}
function handleBtnClickPartB(e) {
console.log($partB + "handler", "click 的 e.target" + e.target);
}
})(jQuery || window.jQuery || window.$, $("#viewModule"));
```
更骚的`路由表`的写法,搭配模块化开发更优雅,更方便管理
```js
// xx 视图模块 #xx
(function ($, $view) {
console.log($ + "has been imported");
// 缓存 dom需要用到的 dom提高性能
var $partA = $view.find(".partA"),
$partB = $view.find(".partB");
// $view 视图的事件委托表
var eventTable = [
{
name: "focus",
elem: "#btnFocusPartA",
handler: handleBtnFocusPartA,
},
{
name: "click",
elem: ".btnClickPartB",
handler: handleBtnClickPartB,
},
];
// 注册事件
eventTable.forEach(function (item) {
$view.on(item.name, item.elem, item.handler);
});
// 方法,建议函数式
function handleBtnFocusPartA() {
console.log($partA + "handler");
}
function handleBtnClickPartB(e) {
console.log($partB + "handler", "click 的 e.target" + e.target);
}
})(jQuery || window.jQuery || window.$, $("#viewModule"));
```