IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 【JQuery】JQuery绑定事件并传参 -> 正文阅读

[JavaScript知识库]【JQuery】JQuery绑定事件并传参

事情是这样的,因为最近在学习前端的知识,学完了需要巩固下知识,所以在网上找的题来做。遇到这样的题。(包含遇到问题的详细过程,觉得例子无趣的可直接跳转结论)

在这里插入图片描述

其代码也很简单,设计表格和事件绑定,最近学习了jquery,很快将代码写出来。

说明下,工程上不要使用行间样式和内嵌js代码。应该做到HTML(结构)+CSS(样式)+JavaScript(控制)分离。我是为了图方便一页代码描述完问题才这样写的。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<style>
    td{
        width: 25%;
    }
</style>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
<body>

<table border="1" cellpadding="0" cellspacing="0" style="width: 100%;">
    <tr>
        <td>物品</td>
        <td>数量</td>
        <td>金额</td>
        <td>备注</td>
    </tr>
    <tr>
        <td><span id="clothSpan" style="cursor: pointer">+</span>&emsp;<span>服装</span></td>
        <td>100件</td>
        <td>12000元</td>
        <td></td>
    </tr>
    <tr style="display: none">
        <td></td>
        <td colspan="3" style="width: 75%">
            <div>
                <table border="1" style="position: relative;width: 500px;height: 100px;left: 30%;margin-top: 25px">
                    <tr>
                        <td>明细</td>
                        <td>数量</td>
                        <td>单价</td>
                        <td>备注</td>
                    </tr>
                    <tr>
                        <td>外套</td>
                        <td>10</td>
                        <td>300</td>
                        <td></td>
                    </tr>
                    <tr>
                        <td>裤子</td>
                        <td>90</td>
                        <td>100</td>
                        <td></td>
                    </tr>
                </table>
            </div>
        </td>
    </tr>
    <tr>
        <td><span id="fruitSpan" style="cursor: pointer">+</span>&emsp;<span>水果</span></td>
        <td>100KG</td>
        <td>290元</td>
        <td></td>
    </tr>

    <tr style="display: none">
        <td></td>
        <td colspan="3" style="width: 75%">
            <table border="1" style="position: relative;width: 500px;height: 100px;left: 30%;margin-top: 25px">
                <tr>
                    <td>明细</td>
                    <td>重量</td>
                    <td>单价</td>
                    <td>备注</td>
                </tr>
                <tr>
                    <td>西瓜</td>
                    <td>10</td>
                    <td>20</td>
                    <td></td>
                </tr>
                <tr>
                    <td>柚子</td>
                    <td>9</td>
                    <td>10</td>
                    <td></td>
                </tr>
            </table>
        </td>
    </tr>
</table>

</body>

<script>

    $("#clothSpan").click(function () {
        var tr = this.parentElement.parentElement;
        //this指的是谁调用的这个函数,由jquery前面选择器我们知道是id为clothSpan的控件
        //找它的父亲元素(td)的父亲元素(tr)
        var nextTr = tr.nextElementSibling;
        //找上面那个tr的下一个tr元素(被隐藏的)
        //这样我们由一个span标签控件的到了我们需要操作的tr控件
        //下面就是逻辑判断,隐藏转显示,显示转隐藏
        if (nextTr.style.display == "none") {
            nextTr.style.display = "table-row";
            tr.cells[0].firstChild.textContent = "-";
        }else{
            nextTr.style.display = "none";
            tr.cells[0].firstChild.textContent = "+";
        }
    });

    $("#fruitSpan").click(function () {
        var tr = this.parentElement.parentElement;
        var nextTr = tr.nextElementSibling;
        if (nextTr.style.display == "none") {
            nextTr.style.display = "table-row";
            tr.cells[0].firstChild.textContent = "-";
        }else{
            nextTr.style.display = "none";
            tr.cells[0].firstChild.textContent = "+";
        }
    });

</script>
</html>

可以看到,两个按钮的逻辑操作代码是一模一样的,这破坏了我们代码复用原则,所以为了提高代码利用率我们做如下更改。

<script>

    var showElement = function(spanElement){
        // var tr = this.parentElement.parentElement;
        //因为我们将它独立提出来提高代码重用性,用到jquery绑定,而只是将函数名赋值过去,谁调用的在这里根本不知道,
        // 所以我们知道需要此时是哪个控件绑定此函数,传参过来
        var tr = spanElement.parentElement.parentElement;
        var nextTr = tr.nextElementSibling;
        if (nextTr.style.display == "none") {
            nextTr.style.display = "table-row";
            tr.cells[0].firstChild.textContent = "-";
        }else{
            nextTr.style.display = "none";
            tr.cells[0].firstChild.textContent = "+";
        }
    };
    $("#clothSpan").click(showElement(document.getElementById("clothSpan")));
    $("#fruitSpan").click(showElement(document.getElementById("fruitSpan")));
</script>

问题出现

上述代码中,因为我们不知道该代码中this指向谁,所以需要将调用该方法的控件对象经过参数传递过来。

按理来说,逻辑应该没问题的,对于初学jquery的我,还沾沾自喜就认为jquery就这。但运行后结果出现了大问题,隐藏表格直接展开了,并且在点击缩小按钮根本没反应。我还仔细的过了以一遍代码和变量追踪,始终没发现逻辑上有任何错误,在这里烦恼了半个小时。最终在网上查阅相关资料和再看jquery和js的基础知识才找到问题所在。

问题分析

问题就出现在$("#clothSpan").click(showElement(document.getElementById("xxx")))这里。

仔细阅读JavaScript基础,发现一旦函数带了()就代表运行,也就是说一旦js遇到函数名+(),它就会去执行这个函数。

所以我们上述的showElement方法仅在绑定的时候运行了一次,然后我们将showElement返回值(无返回值undefined)绑定给控件的点击事件上,然后不论你后面怎么点击都没有用,因为点击事件没绑定上正确的函数。

那么,参数在jquery中华到底应该怎么正确地传递呢?

解决方法

<script>
    var showElement = function(event){
        console.log(event);                 //这个event是Jquery的event,包含了很多
        console.log(event.data.spanElement);//我们参数的值就按键值对放在event.data里
        console.log(event.data.aaa);
        console.log(event.data.bbb);
        var tr = event.data.spanElement.parentElement.parentElement;
        var nextTr = tr.nextElementSibling;
        if (nextTr.style.display === "none") {
            nextTr.style.display = "table-row";
            tr.cells[0].firstChild.textContent = "-";
        }else{
            nextTr.style.display = "none";
            tr.cells[0].firstChild.textContent = "+";
        }
    };

    var arg1 = {
        spanElement : document.getElementById("clothSpan"),
        aaa : 1,
        bbb : "qwe"
    }
    $("#clothSpan").click(arg1, showElement);

    var arg2 = {
        spanElement : document.getElementById("fruitSpan"),
    }
    $("#fruitSpan").click(arg2, showElement);

    //click(data,fn)中的data其实是json对象,取的时候,只能通过当前的事件源来取,
    // data是默认放在event中的,所以这里的data是eventdata,引用的时候也使用event.data.name,
    // 也就是说JQuery中的所有触发时间的方法,需要传递参数都可以通过eventdata对象来传递参数:
</script>

我们可以查看jquery源码里的click函数。click(data,fn)中的data其实是json对象,取的时候,只能通过当前的事件源来取,data是默认放在event中的,所以这里的data是event.data,引用的时候也使用event.data.xxx。这样jquery中函数传参问题得到了解决。

例如

$("select#test").change({msg: "ok"}, function(event) { 
myHandler(event.data.msg); 
}); 

结论

  1. JavaScript中函数名+()就代表着函数运行,所以绑定函数的时候一定不要加(),否则会将返回值进行绑定。直接将函数名看作一个对象,看作一个指向函数的指针,直接用就是了,加()就是无参运行。
  2. JQuery中绑定事件带有参数的函数时,可以借助自带的event,待绑定函数声明时参数带有event,其中传参时参数以json对象(键值对)的格式存在。函数内引用的时候通过event.data.xxx引用。形如$("选择器").click(以json对象形式存在的参数, 待绑定函数名称);

纠正一个错误

上述问题中,发现一个理解上的小错误。在次说明下。

其实上述问题可以不用通过传参解决,直接$("#clothSpan").click(showElement);就解决了,上述之所以传参是我以为,该方法不知道谁调用它,所以需要将调用它的控件对象传递过去,其实不用!

方法无论如何不会自己运行的,一定有调用(call)它,它才能运行,否则根本不会运行,就像工具一样只有有人用它它才能动起来,否则放在那里永远都不可能动起来,所以函数里this是存在的,追溯到最后都没人调用它就是window调用它。是我搞错了,不用传参,直接传递方法名过去,也能获得到this,函数没有人调用怎么能运行起来吗?jquery前面都已经选择定位到那一个了。

同时,这个错误让我更加坚定了JS中函数名是指向函数的指针,传递函数不带(),带()就是无参运行!

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-08-10 13:19:49  更:2021-08-10 13:21:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 0:32:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码