精华内容
下载资源
问答
  • 钩子函数和回调函数

    2021-03-13 12:53:39
    一般认为,钩子函数就是回调函数的一种,其实还是有差异的,差异地方就是:触发的时机不同。先说钩子函数:钩子(Hook)概念源于Windows的消息处理机制,通过设置钩子,应用程序对所有消息事件进行拦截,然后执行钩子...

    一般认为,钩子函数就是回调函数的一种,其实还是有差异的,差异地方就是:触发的时机不同。

    先说钩子函数:

    钩子(Hook)概念源于Windows的消息处理机制,通过设置钩子,应用程序对所有消息事件进行拦截,然后执行钩子函数。

    let btn = document.getElementById("btn");

    btn.onclick = () => {

    console.log("i'm a hook");

    }

    上面的例子,在按钮点击时候立即执行钩子函数。而看下面的例子:

    btn.addEventListener("click",() =>{

    console.log(this.onclick);//undefined

    });

    给btn绑定了一个监听器,只有消息捕获完成之后才能触发回调函数。

    很明显的差别就是:钩子函数在捕获消息的第一时间就执行,而回调函数是捕获结束时,最后一个被执行的。

    回调函数其实是调用者将回调函数的指针传递给了调用函数,当调用函数执行完毕后,通过函数指针来调用回调函数。而钩子函数在消息刚发出,没到达目的窗口前就先捕获了该消息,先得到控制权执行钩子函数,所以他可以加工改变该消息,当然也可以不作为,还可以强行结束该消息。

    其实钩子来源于英文词Hook,在windows系统中,一切皆消息,比如按了一下键盘,也是一个消息,Hook的意思是勾住,也就是在消息过去之前,可以先把消息勾住,不让其传递,你可以优先处理,也即这项技术就是提供了一个入口,能够针对不同的消息或者API在执行前,先执行你的操作,你的操作也称为「钩子函数」,所以,有的时候程序员在讨论的时候,也经常会说,可以先hook住,在处理,也即在执行某某操作之前,优先处理一下

    好啦,这就是Hook的思想和原理

    展开全文
  • 所有的生命周期钩子自动绑定this上下文到实例中,因此你可以访问数据,对属性方法进行运算。但是不能使用箭头函数来定义一个生命周期方法(例如created: () => this.fetchTodos())。这是因为箭头函数绑定了父上...

    官方文档对于Vue的生命周期讲的很简单,可能这部分也不算重点讲解内容吧,但是为了便于理解,这里还是针对以下这三个问题给出了一些综合性的理解。

    一、Vue生命周期

    所有的生命周期钩子自动绑定this上下文到实例中,因此你可以访问数据,对属性和方法进行运算。但是不能使用箭头函数来定义一个生命周期方法(例如created: () => this.fetchTodos())。这是因为箭头函数绑定了父上下文,因此this与你期待的 Vue 实例不同,this.fetchTodos的行为未定义。一个经典的Vue生命周期流程图如下:

    Vue生命周期图

    
             beforeCreate: function () {
                console.group('beforeCreate 创建前状态===============》');
                 console.log("%c%s", "color:red", "el     : " + this.$el); //undefined
                 console.log("%c%s", "color:red", "data   : " + this.$data); //undefined
                 console.log("%c%s", "color:red", "message: " + this.message)
             },
             created: function () {
                 console.group('created 创建完毕状态===============》');
                 console.log("%c%s", "color:red", "el     : " + this.$el); //undefined
                 console.log("%c%s", "color:red", "data   : " + this.$data); //已被初始化
                 console.log("%c%s", "color:red", "message: " + this.message); //已被初始化
             },
             beforeMount: function () {
                 console.group('beforeMount 挂载前状态===============》');
                 console.log("%c%s", "color:red", "el     : " + (this.$el)); //已被初始化
                 console.log(this.$el);
                 console.log("%c%s", "color:red", "data   : " + this.$data); //已被初始化
                 console.log("%c%s", "color:red", "message: " + this.message); //已被初始化
             },
             mounted: function () {
                 console.group('mounted 挂载结束状态===============》');
                console.log("%c%s", "color:red", "el     : " + this.$el); //已被初始化
                 console.log(this.$el);
                 console.log("%c%s", "color:red", "data   : " + this.$data); //已被初始化
                 console.log("%c%s", "color:red", "message: " + this.message); //已被初始化
             },
            beforeUpdate: function () {
                 console.group('beforeUpdate 更新前状态===============》');
                 console.log("%c%s", "color:red", "el     : " + this.$el);
                 console.log(this.$el);
                 console.log("%c%s", "color:red", "data   : " + this.$data);
                 console.log("%c%s", "color:red", "message: " + this.message);
             },
             updated: function () {
                 console.group('updated 更新完成状态===============》');
                console.log("%c%s", "color:red", "el     : " + this.$el);
                 console.log(this.$el);
                 console.log("%c%s", "color:red", "data   : " + this.$data);
                console.log("%c%s", "color:red", "message: " + this.message);
            },
             beforeDestroy: function () {
                 console.group('beforeDestroy 销毁前状态===============》');
                 console.log("%c%s", "color:red", "el     : " + this.$el);
                 console.log(this.$el);
                 console.log("%c%s", "color:red", "data   : " + this.$data);
                 console.log("%c%s", "color:red", "message: " + this.message);
             },
             destroyed: function () {
                 console.group('destroyed 销毁完成状态===============》');
                 console.log("%c%s", "color:red", "el     : " + this.$el);
                 console.log(this.$el);
                 console.log("%c%s", "color:red", "data   : " + this.$data);
                 console.log("%c%s", "color:red", "message: " + this.message)
             }
    
    

    分析:

    1. beforeCreate
      官方说明:在实例初始化之后,数据观测(data observer) 和 event/watcher 事件配置之前被调用。
      解释:这个时期,this变量还不能使用,在data下的数据,和methods下的方法,watcher中的事件都不能获得到;

       beforeCreate() {
         console.log(this.page); // undefined
         console.log{this.showPage); // undefined
       },
       data() {
         return {
           page: 123
         }
       },
       methods: {
         showPage() {
           console.log(this.page);
         }
       }
      
    2. created
      官方说明:实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测(data observer),属性和方法的运算, watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
      解释说明: 这个时候可以操作vue实例中的数据和各种方法,但是还不能对"dom"节点进行操作;

       created() {
         console.log(this.page); // 123
         console.log{this.showPage); // ...
         $('select').select2(); // jQuery插件需要操作相关dom,不会起作用
       },
       data() {
         return {
           page: 123
         }
       },
       methods: {
         showPage() {
           console.log(this.page);
         }
       }
      
    3. beforeMounte
      官方说明:在挂载开始之前被调用:相关的 render 函数首次被调用。

    4. mounted
      官方说明:el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果root实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。
      解释说明:挂载完毕,这时dom节点被渲染到文档内,一些需要dom的操作在此时才能正常进行

       mounted() {
         $('select').select2(); // jQuery插件可以正常使用
       },
      

    这时初始化插件没有问题,插件能正常运行,但是这并不代表万事大吉;下面思考一个问题:

    select2

    图中的selectoption都是通过异步请求得到的,然后通过v-for渲染进去,到此一切看起来很正常。还有一个需求是当页面刷新后要保留上次一查询的条件。我通过vue-router来给select指定一个默认选项;

      <template v-for='(item, index) in agentList.name' >
         <option v-if='item == name' :key='index' selected :value="item">{{item}}</option>
          <option v-else :key='index' :value="item">{{item}}</option>
       </template>
    

    那么问题就来了,option的获得是一个异步请求,那这个请求完成的时刻和mounted的顺序是什么?如果mounted在请求成功之前执行,那将很遗憾——默认选项会设置失败

    option有默认效果的是130,select中的值还是保持全部

    option有默认效果的是130,select中的值还是保持全部

    什么时候执行$('select').select2(),是解决这个问题的关键。mounted的确是在请求成功之前执行的,所以这时的办法就是将$('select').select2()的执行放到请求成功的回调里执行:

      $.getJSON(urls.agentAndCity, {pageType: this.pageType}, (res) => {
        const a = this.agentList,
        d = res.data;
        a.id = d.orgIds;
        a.name = d.orgNames;
        a.city = d.cityMap;
        $('select').select2();
      });
    

    本以为这样就完美解决了,但是发现还是会出现和上图一样的效果;如何是好?这时轮到vm.$nextTick登场了:将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。
    官方示例代码:

        new Vue({
          // ...
          methods: {
          // ...
          example: function () {
          // 修改数据
          this.message = 'changed'
          // DOM 还没有更新
            this.$nextTick(function () {
              // DOM 现在更新了
              // `this` 绑定到当前实例
              this.doSomethingElse()
            })
          }
        }
      })
    

    所以解决办法如下:

    $.getJSON(urls.agentAndCity, {pageType: this.pageType}, (res) => {
        const a = this.agentList,
        d = res.data;
        a.id = d.orgIds;
        a.name = d.orgNames;
        a.city = d.cityMap;
        this.$nextTick(() => {
          $('select').select2();
        });
      });
    

    最后我们可以这样理解这个Vue生命周期的概念,如下整理生命周期流程图所示:

    Vue生命周期

    二、钩子函数

    在一个有序的步骤中的特殊位置(挂载点),插入自定义的内容,这就叫"钩子"。钩子(Hook)概念源于Windows的消息处理机制,通过设置钩子,应用程序对所有消息事件进行拦截,然后执行钩子函数。 

    let btn = document.getElementById("btn");
    btn.onclick = () => {
        console.log("i'm a hook");
    }

     上面的例子,在按钮点击时候立即执行钩子函数。

    三、回调函数

    一般认为,钩子函数就是回调函数的一种,其实还是有差异的,差异地方就是:触发的时机不同。看下面的例子:

    btn.addEventListener("click",() =>{
        console.log(this.onclick);//undefined
    });

    给btn绑定了一个监听器,只有消息捕获完成之后才能触发回调函数。

    所以很明显的差别就是:钩子函数在捕获消息的第一时间就执行,而回调函数是捕获结束时,最后一个被执行的。

    回调函数其实是调用者将回调函数的指针传递给了调用函数,当调用函数执行完毕后,通过函数指针来调用回调函数。而钩子函数在消息刚发出,没到达目的窗口前就先捕获了该消息,先得到控制权执行钩子函数,所以他可以加工改变该消息,当然也可以不作为,还可以强行结束该消息。

    展开全文
  • 钩子函数和回调函数的区别 钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以...

    钩子函数和回调函数的区别
    钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。
    回调函数其实就是调用者把回调函数的函数指针传递给调用函数,当调用函数执行完毕时,通过函数指针来调用回调函数。

    展开全文
  • 一般认为,钩子函数就是回调函数的一种,其实还是有差异的,差异地方就是:触发的时机不同。 先说钩子函数: 钩子(Hook)概念源于Windows的消息处理机制,通过设置钩子,应用程序对所有消息事件进行拦截,然后...

    一般认为,钩子函数就是回调函数的一种,其实还是有差异的,差异地方就是:触发的时机不同。

    先说钩子函数:

    钩子(Hook)概念源于Windows的消息处理机制,通过设置钩子,应用程序对所有消息事件进行拦截,然后执行钩子函数。 

    let btn = document.getElementById("btn");
    btn.onclick = () => {
        console.log("i'm a hook");
    }

    上面的例子,在按钮点击时候立即执行钩子函数。而看下面的例子:

    btn.addEventListener("click",() =>{
        console.log(this.onclick);//undefined
    });

    给btn绑定了一个监听器,只有消息捕获完成之后才能触发回调函数。

    很明显的差别就是:钩子函数在捕获消息的第一时间就执行,而回调函数是捕获结束时,最后一个被执行的。

    回调函数其实是调用者将回调函数的指针传递给了调用函数,当调用函数执行完毕后,通过函数指针来调用回调函数。而钩子函数在消息刚发出,没到达目的窗口前就先捕获了该消息,先得到控制权执行钩子函数,所以他可以加工改变该消息,当然也可以不作为,还可以强行结束该消息。

    展开全文
  • 钩子函数和回调函数的区别?

    千次阅读 2018-08-29 10:16:36
    钩子的概念源于Windows的消息处理机制,通过设置钩子,应用程序可以对所有的消息事件进行拦截,然后执行钩子函数,对消息进行想要的处理方式。 接下来是一段js代码,主要用于给btn设置点击的钩子函数。钩子是在捕获...
  • 编程分为两类:系统编程(system programming)应用编程(application programming)。所谓系统编程,简单来说,就是编写库;而应用编程就是利用写好的各种库来编写具某种功用的程序,也就是应用。系统程序员会给自己...
  • 回调函数回调函数是应用...回调函数必须遵守事先规定好的参数格式传递方式,否则DLL一调用它就会引起程序或系统的崩溃。通常情况下,回调函数采用标准WindowsAPI的调用方式,即__stdcall,当然,DLL编制者可以自...
  • 钩子函数回调函数的理解

    千次阅读 2018-08-08 21:30:04
    ----在学习ES6的时候,一直在深思钩子函数的与回调函数的区别:  下面,作以总结  1.钩子函数回调函数都是事件处理函数  2.钩子函数是指windows的消息处理机制下,捕获消息的时候立即执行  3.回调函数并不...
  • 个人感觉这两种函数的界限似乎并没有特别明显,我就遇到过回调函数和钩子函数的注册函数是同一个的情况、(回调函数没有作为调用函数参数传入),这两个的函数的区别,举个例子来说明一下我自己的理解吧: ...
  • 每当特定的消息发出,在没有到达目的窗口前,钩子程序就先捕获该消息,亦即钩子函数先得到控制权。这时钩子函数即可以加工处理(改变)该消息,也可以不作处理而继续传递该消息,还可以强制结束消息的传递。对每种类型...
  • 回调函数 回调函数是调用者将回调函数的指针传递给了调用函数,当调用函数执行完毕或者达到一定的条件后,通过函数指针来调用的函数 钩子函数 钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统。每当...
  • 什么是钩子函数? 先来看一段百科:钩子函数是Windows消息处理机制的一部分,通过设置“钩子”,应用程序可以在系统级对所有消息、事件进行过滤,访问在正常情况下无法访问的消息。钩子的本质是一段用以处理系统消息...
  • 1.钩子函数 是一个函数,在系统消息触发时被系统...2.回调函数 <body> <div id="test"></div> <script type="text/babel"> "use strict"; class Person extends React.Component { st
  • 钩子函数回调函数都是一种事件函数,处理事件的一个普通函数. 不同点 钩子函数是一个有特殊名称的函数(事件函数). 特殊名称体现在函数名上,也就是有固定格式,固定函数名的一个普通函数,这是人为规定的.别人有个钩子...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 32,207
精华内容 12,882
关键字:

钩子函数和回调函数