【Vue】上万个字把事件处理讲解的淋漓尽致(上)

简介: 【Vue】上万个字把事件处理讲解的淋漓尽致(上)

hello,我是小索奇,精心制作的Vue系列教程持续更新哈,想要学习&巩固&避坑就一起学习吧~

事件处理

事件的基本用法

重点内容

  1. 使用v-on:xxx缩写@xxx绑定事件,其中 xxx 是事件名(回顾:v-bind缩写为冒号:)
  2. 事件的回调需要配置在methods对象中,最终会在VM
  3. methods中配置的函数,不要用箭头函数,否则 this 就不是VM了,重点强调!
  4. methods中配置的函数,都是被 Vue所管理的函数,this 的指向是VM(ViewModel-vue实例对象)或组件实例对象
  5. @click="demo"@click="demo($event)"效果一致,前者是默认会传event,省略了而已,后者更加灵活,可以传更多参数
  6. 当我们需要给函数传参时@click='showInfo(666)'怎么获取event
  7. 关于this的详细理解

详细解析

先看这一组代码,哪里有问题

<body>
    <div id="root">
        <h2>这是name:{{name}}</h2>
        <button v-on:click = "showInfo">点击提示信息</button>
    </div>
    <script type="text/JS">
        Vue.config.productionTip = false
        function showInfo(){
            alert('你好哈')
        }
        new Vue({
            el:'#root',
            data:{
                name:'即兴小索奇'
            }
        })
    </script>
</body>

不知道methods的伙伴可能看不出什么问题,但实际的问题是点击按钮没有任何反应

image-20230812205755903

这里定义了一个普通的JS 函数 showInfo(),但没有将它添加到 Vue 实例的 methods 选项中,因此在模板中使用 v-on:click="showInfo" 时无法正确调用该函数我们需要将 showInfo 函数添加到 Vue 实例的 methods 选项中

因为 Vue 实例的 methods 选项专门用于存放可以在模板中调用的方法

当在methods中加上showInfo方法就会成功显示

image-20230812211754411

事件对象

当你在模板中使用事件处理函数时,Vue 会自动将事件对象作为第一个参数传递给该函数因此,你可以在事件处理函数中定义一个参数来接收这个事件对象常见的做法是将这个参数命名为 event,以表示它是一个事件对象

例如,在你的代码中,如果你使用 v-on:click="showInfo" 来绑定事件,那么在 showInfo 函数中,你可以定义一个名为 event 的参数,这样就可以访问到事件对象,从而获取事件的信息(如点击的坐标、触发的元素等)

举个栗子

<body>
    <div id="root">
        <button v-on:click="showInfo">点击提示信息</button>
    </div>
    <script type="text/JS">
        new Vue({
            el: '#root',
            data: {
                name: '即兴小索奇'
            },
            methods: {
                showInfo(event) {
                    console.log(event)
                    console.log(event.target)
                    alert('你好哈,点击坐标:' + event.clientX + ',' + event.clientY + '  ' + event.target.innerText);
                }
            }
        });
    </script>
</body>

image-20230812213221250

在这里这个事件就是button

event.target就是这个事件目标(button)

image-20230812213746135

console.log(event)输出可以看到所有属性及方法

image-20230812213517353

当我们需要给函数传参时@click='showInfo(666)'怎么获取event

当我们需要传参时,会发现event不能输出了,即使设置多个参数也是undefined,这时候我们只要在参数后面加上$(event)关键词即可

  • @click='showInfo(666,$event) 方法中对应两个参数就可以输出event了,这是官方设置的,记住就行
  • 对于event的顺序没有要求,可以把其它参数放在event后面也行

this函数的区分

如果把下面代码中的普通函数改为箭头函数,它的this会如何变化?

<body>
    <div id="root">
        <button v-on:click="showInfo">点击提示信息</button>
    </div>
    <script type="text/JS">
        new Vue({
            el: '#root',
            data: {
                name: '即兴小索奇'
            },
            methods: {
                showInfo:(event)=> {
                    console.log(this) // 箭头函数时输出window
                    console.log(this) // 普通函数时输出vue
                    alert('你好哈,点击坐标:' + event.clientX + ',' + event.clientY + '  ' + event.target.innerText);
                }
            }
        });
    </script>
</body>
  • 当showInfo为普通函数时,显示的是Vue对象
  • 当showInfo为箭头函数时,显示的是Window对象

在普通函数中,this 的值是在函数被调用时确定的,它可以根据调用的方式(比如函数被作为对象的方法调用、作为构造函数调用等)而发生改变

而在箭头函数中,this 的值是由外围(定义箭头函数的上下文)的上下文确定的,它继承自最近的非箭头函数父级换句话说,箭头函数的 this 始终指向定义箭头函数的代码块所在的上下文,而不是调用箭头函数的方式

这种行为对于在回调函数中捕获外部上下文非常有用,但也可能导致在某些情况下出现意外的结果所以,大家在使用箭头函数时,需要特别注意 this 的行为哈

注意

  • 在被Vue管理的函数中(在Vue实例对象里面)最好都写成普通函数,不要写箭头函数!

让我们首先来看看普通函数中的 this

函数作为独立函数调用: 当函数作为独立的函数调用时,this 会指向全局对象(在浏览器中通常是 window 对象,Node.js 中是 global 对象)

 function normalFunction() {
    console.log(this); // 在浏览器中输出 window(全局对象)
}
normalFunction();

函数作为对象方法调用: 当函数作为对象的方法调用时,this 会指向调用该方法的对象

 const obj = {
    name: 'John',
    greet: function() {
        console.log(this.name);
    }
};
obj.greet(); // 输出 "John"

函数作为构造函数调用: 当函数用作构造函数创建新对象时,this 会指向正在创建的新对象

 function Person(name) {
    this.name = name;
}
const person = new Person('Alice');
console.log(person.name); // 输出 "Alice"

而在箭头函数中,this 的行为有所不同:

箭头函数中的 this 箭头函数的 this 始终由外围(定义箭头函数的上下文)的上下文决定,它不会因为函数被调用的方式而改变

 const arrowFunction = () => {
    console.log(this); // 这里的 this 是外围上下文中的 this
};
arrowFunction(); // 输出的 this 取决于外围上下文

这种行为使得箭头函数在某些情况下非常有用,例如在回调函数中,你可以捕获外部函数的上下文,避免了在回调中使用 thatself 来保存上下文

总结来说,普通函数中的 this 在调用时会根据调用方式和上下文而变化,而箭头函数中的 this 始终继承自外围上下文,不会随着调用方式的改变而改变

拓展一下

在箭头函数中,this 的取值是由箭头函数所在代码块的上下文决定的换句话说,箭头函数的 this 继承自最近的非箭头函数父级的 this

这意味着,如果箭头函数直接位于全局作用域中,那么它的 this 就会继承自全局对象(例如,在浏览器环境中,就是 window 对象)

让我们来看一个示例:

const arrowFunction = () => {
    console.log(this);
};
arrowFunction(); // 输出的 this 取决于全局上下文,通常是 window 或 global 对象(取决于环境)

在浏览器环境中运行上述代码,arrowFunctionthis 将指向全局对象 window

然而,如果箭头函数嵌套在其他函数或对象方法中,它的 this 将继承自外围上下文:

function outerFunction() {
    const innerArrow = () => {
        console.log(this);
    };
    innerArrow();
}
outerFunction(); // 输出的 this 取决于 outerFunction 的上下文

在这个示例中,innerArrowthis 将继承自 outerFunction 的上下文

我们可以在不同的上下文中尝试运行这些示例代码,并查看输出的 this 值,以更好地理解箭头函数的 this 行为

这里的this也就是输出全局对象window

  <script type="text/JS">
        new Vue({
            el: '#root',
            data: {
                name: '小索奇'
            },
            methods: {
                showInfo: () => {
                    console.log(this); // 输出全局对象 window,因为箭头函数没有外围上下文
                }
            }
        });
    </script>

索奇问答

这里可能又会有人问了

A:什么是外围上下文?

Q:在JS 中,每个函数都有一个自己的执行上下文(execution context),其中包含函数的作用域、参数、变量等信息函数的执行上下文在函数被调用时创建,随后被推入执行上下文栈(execution context stack)中,函数执行完毕后从栈中弹出

代码举例

假设有一个函数 outer 包含一个函数 inner,在 inner 函数中,outer 就是 inner 函数的外围上下文

function outer() {
 // 我是外围
    const outerVar = 'I am outer'; 
    function inner() {
        console.log(outerVar); // 访问外围上下文中的变量
    }
    inner();
}
outer(); // 输出 "I am outer"

在这个例子中,inner 函数的外围上下文是包含它的 outer 函数的执行上下文因此,inner 函数可以访问 outer 函数中的变量 outerVar

另一个例子是使用事件处理函数时:

<!DOCTYPE html>
<html>
<head>
    <title>Outer Context</title>
</head>
<body>
    <button id="myButton">Click Me</button>
    <script>
        const button = document.getElementById('myButton');
        button.addEventListener('click', function() {
            console.log(this); // 这里的 this 是事件目标,即按钮元素
            console.log('Button clicked!');
        });
    </script>
</body>
</html>

当按钮被点击时,事件处理函数中的 this 指向事件目标,即按钮元素这是因为事件处理函数的外围上下文是事件目标的上下文

全局作用域中的外围上下文: 在全局作用域中,外围上下文就是全局上下文~

console.log(this === window); // 在浏览器环境中输出 true,因为 this 在全局作用域中指向全局对象 window

外围上下文就是包裹当前代码块的上一层环境,它决定了代码中的 this、变量访问等行为

不同的this

  • 这里再精简一下this,既然说了,一下子多拓展一点
相关文章
|
7天前
|
JavaScript 前端开发
如何在 Vue 项目中配置 Tree Shaking?
通过以上针对 Webpack 或 Rollup 的配置方法,就可以在 Vue 项目中有效地启用 Tree Shaking,从而优化项目的打包体积,提高项目的性能和加载速度。在实际配置过程中,需要根据项目的具体情况和需求,对配置进行适当的调整和优化。
|
7天前
|
存储 缓存 JavaScript
在 Vue 中使用 computed 和 watch 时,性能问题探讨
本文探讨了在 Vue.js 中使用 computed 计算属性和 watch 监听器时可能遇到的性能问题,并提供了优化建议,帮助开发者提高应用性能。
|
7天前
|
存储 缓存 JavaScript
如何在大型 Vue 应用中有效地管理计算属性和侦听器
在大型 Vue 应用中,合理管理计算属性和侦听器是优化性能和维护性的关键。本文介绍了如何通过模块化、状态管理和避免冗余计算等方法,有效提升应用的响应性和可维护性。
|
7天前
|
存储 缓存 JavaScript
Vue 中 computed 和 watch 的差异
Vue 中的 `computed` 和 `watch` 都用于处理数据变化,但使用场景不同。`computed` 用于计算属性,依赖于其他数据自动更新;`watch` 用于监听数据变化,执行异步或复杂操作。
|
6天前
|
JavaScript 前端开发 UED
vue学习第二章
欢迎来到我的博客!我是一名自学了2年半前端的大一学生,熟悉JavaScript与Vue,目前正在向全栈方向发展。如果你从我的博客中有所收获,欢迎关注我,我将持续更新更多优质文章。你的支持是我最大的动力!🎉🎉🎉
|
8天前
|
存储 JavaScript 开发者
Vue 组件间通信的最佳实践
本文总结了 Vue.js 中组件间通信的多种方法,包括 props、事件、Vuex 状态管理等,帮助开发者选择最适合项目需求的通信方式,提高开发效率和代码可维护性。
|
6天前
|
JavaScript 前端开发 开发者
vue学习第一章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript和Vue的大一学生。自学前端2年半,熟悉JavaScript与Vue,正向全栈方向发展。博客内容涵盖Vue基础、列表展示及计数器案例等,希望能对你有所帮助。关注我,持续更新中!🎉🎉🎉
|
8天前
|
存储 JavaScript
Vue 组件间如何通信
Vue组件间通信是指在Vue应用中,不同组件之间传递数据和事件的方法。常用的方式有:props、自定义事件、$emit、$attrs、$refs、provide/inject、Vuex等。掌握这些方法可以实现父子组件、兄弟组件及跨级组件间的高效通信。
|
13天前
|
JavaScript
Vue基础知识总结 4:vue组件化开发
Vue基础知识总结 4:vue组件化开发
|
13天前
|
存储 JavaScript
Vue 状态管理工具vuex
Vue 状态管理工具vuex