Loading... ## 前言 <div class="tip inlineBlock info simple"> 今天学习ajax时有的同学出现了一些这样的错误:从后台拿到的数据生成的html标签显示在页面上,然后给它绑定点击事件,可是事件绑定不上。他使用的是jQuery获取元素,我发现他并没有获取到任何一个元素,这是什么原因呢?让我一起来和大家探讨一下。 </div> ## 进程与线程 1. 进程:**一个在内存中运行的应用程序。每个进程都有自己独立的一块内存空间,一个进程可以有多个线程,比如在windows系统中,一个运行的xx.exe就是一个进程** 2. 线程:是**进程中的一个独立的执行单元**,是**程序执行的一个完整流程**,是**cpu的最小调度单元** 3. 相关知识: * 应用程序必须运行在某个进程的某个线程上 * 一个进程中至少有一个运行的线程:主线程,进程启动后自动创建 * 一个进程中也可以同时运行多个线程,我们会说程序是多线程运行的 * 一个进程内的数据可被其中的多个线程直接共享 * 多个进程之间的数据是不能直接共享的 * 线程池:保存多个线程对象的容器,实现线程对象的反复利用 4. javascript 回调函数在主线程中执行,因为javascript是单线程的(后面会和你扯为什么它要是单线程不设计成多线程) 5. 浏览器是单线程运行的还是多线程运行的?多线程 6. 浏览器是单进程还是多进程的?有单进程的也有多进程的 * 多进程浏览器:chrome和新版IE * 单进程浏览器:火狐浏览器 7. 浏览器内核组成 ![浏览器内核组成](https://www.jbea.cn/usr/uploads/2021/12/545794651.png) ## 定时器引发的思考? 定时器是真的是定时执行的吗?它并不能真正准确的定时,一般都会延迟一点点,也有可能延迟很久 ```javascript var time = Date.now() setTimeout(()=>{ console.log('定时器执行',Date.now() - time) },200) ``` 执行结果如下图所示 ![运行效果](https://www.jbea.cn/usr/uploads/2021/12/2816654075.png) 其实这样子也还好,偏差的并不是太严重,我们再将代码改一下 ```javascript var time = Date.now() setTimeout(()=>{ console.log('定时器执行',Date.now() - time) },200) for(var i = 0;i<1000;i++){ console.log(i); } // 再来执行一遍,会发现延迟会比之前还要久,这是为什么呢? ``` 其实javascript的代码可以分为**初始化代码**和**回调代码**,像上面的代码中都是初始化代码(除了定时器里面的回调函数是回调代码)只有当我们的运行栈中的代码执行完成才会去执行回调代码 ```javascript console.log('Hello') setTimeout(()=>{ console.log('Hello,girls,nice to meet you!') },0) setTimeout(()=>{ console.log('Goodnight~') },2000) alert('Hi') console.log('Hi') /* 请问这段代码的执行顺序是什么呢? * 答案应该是 * 依次输出'Hello',弹出'Hi',输出'Hi','Hello,girls,nice to meet you!' * 最后输出'Goodnight~' * 那么现在问题来了,如果我在浏览器弹出'Hi'时不做任何操作(关闭弹窗)会发生什么, * 会执行后面的那句console.log和那两个定时器吗? * 答案是否定的 */ ``` ![输出结果](https://www.jbea.cn/usr/uploads/2021/12/2871160779.png) **那么知道如何证明js是单线程的吗?** * `setTimeout()`的回调函数是在主线程中执行的 * 只有执行完运行栈中的代码才会执行回调 **为什么js是单线程不设计成多线程?** * 与功能有关 作为浏览器脚本语言它的主要用途就是与用户互动以及操作dom 这决定了它只能是单线程的,否则会带来很严重的同步问题,就<span style='color:#49a5f5'>比如说我有两个线程,第一个线程需要更改标签p的内容 第二个线程需要删除标签p 首先第一个线程获取到了cpu资源 准备更新时 线程2又获取到了cpu资源 将p标签删除了 然后再切换到线程1时会有问题。(可避免操作麻烦,所以js是单线程的)</span> ## 事件循环模型(原理图) ![事件循环模型](https://www.jbea.cn/usr/uploads/2021/12/3953863955.jpg) 画的不好,将就看了... 小菜鸟一枚,欢迎批评指正! ## 最后看个案例 ```javascript $(() = >{ // 向服务器发送请求,获取数据并将数据绑定至对应的表格数据中 $.post("UserServlet", { "method": "list" }, function(data) { // 循环数据,将创建出来的元素添加到页面中 for (var i = 0; i < data.length; i++) { var tr = `<tr><td><a class="del" sc${data[i].id}>删除</a > </td></tr> `; $("#tr_content").append(tr); }; }, "json"); $("a.del").click(() = >{ }); //给页面中的a元素绑定点击事件(省略具体操作) }); ``` 这段代码我相信很多同学都写过,但是我们执行代码的时候发现这个时候的a链接并不能触发我们的点击事件,原因是:**post请求是异步的,绑定click事件执行的时候,页面中的元素都还没有被创建。**所以我们需要对其做出优化: ```javascript $(() = >{ $.post("UserServlet", { "method": "list" }, function(data) { for (var i = 0; i < data.length; i++) { var tr = ` < tr > <td > <a class = "del"sc$ {data[i].id} > 删除 < /a > </td > </tr> `; $("#tr_content").append(tr); } $("a.del").click(() = >{ }); // 🎏 点击事件的绑定写在for循环之后即可 }, "json"); }); ``` ## 总结 > 一句话总结就是 **同步代码执行>异步代码执行 不管这个异步代码执行得有多快都遵守这一原则**,只有同步代码执行完毕才会去执行回调 > > 看完这些大概今天出现的问题就可以迎刃而解了吧?其实就是因为同学操作dom的代码没有写在一个异步任务里面,这样的结果就是你给元素绑定事件的时候 页面上的元素还没有从后台拿出来生成 所以你不可能拿得到这些要操作的元素。解决方案:把操作dom的方法写在ajax回调的里面操作 > > 何英杰同学供稿 最后修改:2022 年 01 月 06 日 © 允许规范转载 赞 4 都滑到这里了,不点赞再走!?
6 条评论
真好呢
666何总牛逼
点我有你想看
OωO大哥牛逼 膜拜
大哥,你自己看看你的ID,和作者的ID,是不是太明显了一点?哈哈哈哈哈
66666666666666