Hi Mozzie 显示 / 隐藏 左侧导航 [
⌘ K
偏好 ⌘ p
显示 / 隐藏 文章目录 ]

# jQuery

上次更新: 2024-03-15 23:14:48

# 基础

在 `window` 对象中挂载了 `$`和`jQuery`

    window.jQuery();
    window.$ = window.jQuery;

# 模块化

## 原始写法

只要把不同的函数（以及记录状态的变量）简单地放在一起，就算是一个模块。

> 缺点很明显：”污染”了全局变量，无法保证不与其他模块发生变量名冲突，而且模块成员之间看不出直接关系。

    function m1() {
      //...
    }

    function m2() {
      //...
    }

## 对象写法

把模块写成一个对象

> 写法会暴露所有模块成员，内部状态可以被外部改写。

    var module1 = new Object({
      _count: 0,

      m1: function () {
        //...
      },

      m2: function () {
        //...
      },
    });

    // 使用
    module1.m1();

## IIFE 立即执行函数写法[推荐]

> 外部代码无法读取内部的成员变量

    var module1 = (function () {
      var _count = 0;

      var m1 = function () {
        //...
      };

      var m2 = function () {
        //...
      };

      return {
        m1: m1,
        m2: m2,
      };
    })();

    console.info(module1._count); //undefined

## (宽)放大模式

如果一个模块很大，必须分成几个部分，或者一个模块需要继承另一个模块，这时就有必要采用”放大模式”

    var module1 = (function (mod) {
      mod.m3 = function () {
        //...
      };
      return mod;
    })(module1);

mod 可能存在异步，不知道内部哪个部分会先加载，如果采用上面的写法，第一个执行的部分有可能加载一个不存在空对象，这时就要采用”宽放大模式”。

    var module1 = (function (mod) {
      //...
      return mod;
    })(window.module1 || {});

## 输入全局变量[推荐]

为了在模块内部调用全局变量，必须显式地将其他变量输入模块

    var module1 = (function ($, YAHOO) {
      //...
    })(jQuery, YAHOO);

# 链式操作

    $('div').find('#child').addClass('red')
    // end() 函数返回上一级
    $('div').find('#child').addClass('red').end().addClass（'yellow'）

# 选择器

## 筛选器

    // $('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"); //正在执行动画效果的元素

## 内容选择器

    $("div:contains('nick')"); //包含nick文本的元素

    $("td:empty"); //不包含子元素或者文本的空元素

    $("div:has(p)"); //含有选择器所匹配的元素

    $("td:parent"); //含有子元素或者文本的元素

## 表单选择器

    $(":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元素

## 查找

    $("#xxx"); //返回 一个 jquery 对象

    $("#xxx").find(".xxx"); //查找#xxx里的.xxx元素

    $("#xxx").parent(); //获取父类

    $("#xxx").parents("xxx"); //获取xxx祖先

    $("#xxx").children(); //获取子类

    $("#xxx").siblings(); //获取同一父类的其他元素

    $("#xxx").next(); //获取下一个元素

    $("#xxx").prev(); //获取上一个元素

## 属性操作

    $("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 操作

    $("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" }); // 设置多个属性

## 文档处理

内部插入

    $("p").append("<b>nick</b>"); //每个p元素内后面追加内容

    $("p").appendTo("div"); //p元素追加到div内后

    $("p").prepend("<b>Hello</b>"); //每个p元素内前面追加内容

    $("p").prependTo("div"); //p元素追加到div内前

外部插入

    $("p").after("<b>nick</b>"); //每个p元素同级之后插入内容

    $("p").before("<b>nick</b>"); //在每个p元素同级之前插入内容

    $("p").insertAfter("#test"); //所有p元素插入到id为test元素的后面

    $("p").insertBefore("#test"); //所有p元素插入到id为test元素的前面

## 复制

    $("p").clone(); //克隆元素并选中克隆的副本

    $("p").clone(true); //布尔值指事件处理函数是否会被复制

# attr 和 prop 区别

prop 和 attr 均可获取属性值，但 prop 获取的是 `DOM 对象内置属性`。

> !! 例如 input，radio，slect 元素，请使用 prop 获取

    <img src="https://www.runoob.com/images/pulpit.jpg" />
    <p tinyval="12"></p>

    // 因为页面源代码中没有设置 width 属性
    $("img").attr("width"); // undefined
    $("img").prop("width"); // 284

    // 由于 tinyval 并非 HTML 标准属性
    $("p").prop("tinyval"); // undefined
    $("p").attr("tinyval"); // 12

# 事件

## 事件委托

- 可极大减少事件绑定次数，提高性能
- 可让动态加入的子元素绑定相同的命令

    function handleClick(event) {
      // this 表示当前单击的元素
      alert($(this).html());
    }
    // 把子级li元素的单击事件委托在父级ul身上
    $("ul").delegate("li", "click", handleClick);

## 单事件单元素

    function handleClick() {}
    $xxx.on("click", handleClick);

## 单事件多元素

    function handleClick() {}
    $xxx.on("click", "#aaa, .bbb", handleClick);

## 多事件多元素

    function handleClick() {}
    function handleMounseEnter() {}
    $xxx.on(
      {
        click: handleClick,
        mounseenter: handleMounseEnter,
      },
      "#aaa, .bbb"
    );

## 一夜情事件

    function handleClick() {}
    $xxx.one("click", handleClick);

# 对象操作

    $.trim(); //去除字符串两端的空格

    $.each(); //遍历一个数组或对象，for循环

    $.inArray(); //返回一个值在数组中的索引位置，不存在返回-1

    $.grep(); //返回数组中符合某种标准的元素

    $.extend(true, {}, a, b); // 深浅拷贝合并 a、b 到 {} 上

    $.makeArray(); //将对象转化为数组

    $.type(); //判断对象的类别（函数对象、日期对象、数组对象、正则对象等等

    $.isArray(); //判断某个参数是否为数组

    $.isEmptyObject(); //判断某个对象是否为空(不含有任何属性)

    $.isFunction(); //判断某个参数是否为函数

    $.isPlainObject(); //判断某个参数是否为用"{}"或"new Object"建立的对象

    $.support(); //判断浏览器是否支持某个特性

# 禁止右键功能菜单

    $(window).on({
      contextmenu: function () {
        return false;
      },
      keydown: function (e) {
        if (e.ctrlKey || (e.metaKey && (e.keyCode === 67 || e.keyCode === 8)))
          return false;
      },
    });

# 自动修改破损图像

    $("img").on("error", function () {
      $(this).prop("src", "img/broken.png");
    });

# 模块化 jquery 最佳实践

    // 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"));

更骚的`路由表`的写法，搭配模块化开发更优雅，更方便管理

    // 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"));

重拾纯粹的写作

目录

隐藏目录 ]