[toc]
>[success] # v-on 知识点
1. 用`v-on`指令监听 DOM 事件,`v-on`中要处理的逻辑比较复杂,因此不支持直接在`v-on`中直接写js代码,例如下面直接使用alert 方法,如果这么写必须是在`vue`实例对象的`method`中有定义alter方法才行,否则不支js 自带一些默认方法直接调用
~~~html
<button v-on:click="alert('a')">v-on按钮</button>
~~~
2. 事件处理器的值可以有两种表现形式,**内联事件处理器** 和 **方法事件处理器**
* **内联事件处理器**,事件被触发时执行的内联 JavaScript 语句(最通俗理解,调用方法时候有括号,直接使用以声明属性)实际上是将其执行的是一段 `js `代码
~~~html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div id="app">
{{count}}
<button @click="count++">内联</button>
<button @click="add()">内联</button>
<button @click="addStep(2)">内联</button>
<button @click="addStep(2);add()">内联</button>
</div>
<!-- 通过cdn 引入 -->
<script src="https://unpkg.com/vue@next"></script>
<script>
const app = Vue.createApp({
data() {
return {
count: 1,
}
},
methods: {
add() {
this.count++
},
addStep(num) {
this.count += num
},
},
})
app.mount('#app')
</script>
</body>
</html>
~~~
* **方法事件处理器**,一个指向组件上定义的方法的属性名或是路径(简单理解直接方法名字)
~~~html
<!-- `greet` 是上面定义过的方法名 -->
<button @click="greet">Greet</button>
~~~
~~~
data() {
return {
name: 'Vue.js'
}
},
methods: {
greet(event) {
// 方法中的 `this` 指向当前活跃的组件实例
alert(`Hello ${this.name}!`)
// `event` 是 DOM 原生事件
if (event) {
alert(event.target.tagName)
}
}
}
~~~
二者检测形式:` v-on` 的值是否是合法的 `JavaScript `标识符或属性访问路径来断定是何种形式的事件处理器。举例来说,**foo、foo.bar 和 foo['bar'] 会被视为方法事件处理器**,而 **foo() 和 count++ 会被视为内联事件处理器** 。
>[info] ## 常见使用
~~~html
<!-- 动态事件 -->
<button v-on:[event]="doThis"></button>
<!-- 动态事件缩写 -->
<button @[event]="doThis"></button>
<!-- 对象语法 -->
<button v-on="{ mousedown: doThis, mouseup: doThat }"></button>
<!-- 一个事件绑定多个方法 -->
<button @click="one($event), two($event)">Submit</button>
~~~
>[danger] ##### 关于event
* 在正常使用js 绑定事件时候,都会获取到`event`对象
~~~
<button>获取evnet</button>
document.querySelector('button').onclick = function (event) {
console.log(event) // 打印出 event 对象
}
~~~
* 在 `vue` 中使用 也可以将么`event`对象会传递进来,在**内联事件处理器**和**方法事件处理器** 传递形式不同
~~~ html
<!-- 1.默认传递event对象 -->
<button @click="btn1Click">按钮1</button>
<!-- 2.自己的参数和event对象 -->
<!-- 在模板中想要明确的获取event对象: $event -->
<button @click="btn3Click('zzz', $event)">按钮3</button>
~~~
~~~
methods: {
// 1.默认参数: event对象
// 总结: 如果在绑定事件的时候, 没有传递任何的参数, 那么event对象会被默认传递进来
btn1Click(event) {
console.log('btn1Click:', event)
},
// 2.明确参数+event对象
btn3Click(name, event) {
console.log('btn3Click:', name, event)
},
},
~~~
>[info] ## 事件修饰符
1. `.stop` - 调用 `event.stopPropagation()` 阻止事件冒泡
2. `.prevent` - 调用 `event.preventDefault()`。阻止默认事件从里到外
3. `.capture` - 添加事件侦听器时使用 `capture `模式。实现捕获触发事件的机制从外到里
4. `.self` - 只当事件是从侦听器绑定的元素本身触发时才触发回调。只会阻止自己身上的行为
5. `.{keyAlias}` - 仅当事件是从特定键触发时才触发回调。(键盘简写)
6. `.once` - 只触发一次回调。
7. `.left` - 只当点击鼠标左键时触发。
8. `.right` - 只当点击鼠标右键时触发。
9. `.middle` - 只当点击鼠标中键时触发。
10. `.passive` - { passive: true } 模式添加侦听器
>[danger] ##### 阻止事件冒泡 -- stop
1. 多个元素嵌套,有层次关系,这些元素都注册了相同的事件,如果里面的元素事件触发了,外面的元素的该事件自动的触发了,注意相同事件(都是点击事件,中点击叫做事件)
2. 事件冒泡从里向外
3. 阻止事件冒泡使用stop
~~~ html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.inner {
width: 200px;
height: 200px;
background-color: darkseagreen;
}
</style>
</head>
<body>
<div id="app">
<div class="inner" id="app" @click="divClick">
<input type="button" value="点击" @click.stop="inputClick" />
</div>
</div>
<!-- 引入vue cdn -->
<script src="https://unpkg.com/vue@next"></script>
<script>
const vm = Vue.createApp({
methods: {
divClick() {
console.log('最外层div')
},
inputClick() {
console.log('最内层div')
},
},
}).mount('#app')
</script>
</body>
</html>
~~~
* 点击按钮效果:
~~~
最内层div
~~~
* 如果没有增加stop
~~~
最内层div
最外层div
~~~
>[danger] ##### 实现捕获触发事件的机制 -- capture
1. 冒泡是从向外依次触发,使用`capture`,就变成了从 **先显示外面,在显示里面**
~~~ html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.inner {
width: 200px;
height: 200px;
background-color: darkseagreen;
}
</style>
</head>
<body>
<div id="app">
<div class="inner" id="app" @click.capture="divClick">
<input type="button" value="点击" @click="inputClick" />
</div>
</div>
<!-- 引入vue cdn -->
<script src="https://unpkg.com/vue@next"></script>
<script>
const vm = Vue.createApp({
methods: {
divClick() {
console.log('最外层div')
},
inputClick() {
console.log('最内层div')
},
},
}).mount('#app')
</script>
</body>
</html>
~~~
* 打印结果
~~~
最外层div
最内层div
~~~
>[danger] ##### .self -- 组织自己的事件行为
1. 只会阻止自己身上的行为 ,像下面的案例当有多层嵌套的时候,只会阻止有self 冒泡行为
2. 官网的第一个提示:使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用` @click.prevent.self`会阻止元素本身及其子元素的点击的默认行为,而 `@click.self.prevent` 只会阻止对元素自身的点击的默认行为。
~~~ html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.inner {
width: 200px;
height: 200px;
background-color: darkseagreen;
}
</style>
</head>
<body>
<div id="app">
<div class="outer" @click="div2Handler">
<div class="inner" @click.self="div1Handler">
<input type="button" value="戳他" @click="btnHandler" />
</div>
</div>
</div>
<!-- 引入vue cdn -->
<script src="https://unpkg.com/vue@next"></script>
<script>
const vm = Vue.createApp({
methods: {
div1Handler() {
console.log('这是触发了 inner div 的点击事件')
},
btnHandler() {
console.log('这是触发了 btn 按钮 的点击事件')
},
div2Handler() {
console.log('这是触发了 outer div 的点击事件')
},
},
}).mount('#app')
</script>
</body>
</html>
~~~
* 打印结果
~~~
这是触发了 btn 按钮 的点击事件
这是触发了 outer div 的点击事件
~~~
>[danger] ##### 阻止默认事件 -- prevent
1. 例如a标签默认事件就是点击跳转页面,为了**阻止a标签的默认事件触发我们绑定的事件**,可以使用prevent
2. 图片的默认事件**禁止拖拽**,如果想给图片设置拖拽效果的话记得做阻止默认行为
~~~ html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style></style>
</head>
<body>
<div id="app">
<a href="www.baidu.com" @click.prevent.once="linkClick">百度</a>
</div>
<!-- 引入vue cdn -->
<script src="https://unpkg.com/vue@next"></script>
<script>
const vm = Vue.createApp({
methods: {
linkClick: function () {
alert(1)
},
},
}).mount('#app')
</script>
</body>
</html>
~~~
* 运行的效果
~~~
1.a标签不会页面跳转,反而点击后会弹出弹窗显示1,当下次点击时候会跳转a 标签地址
~~~
>[danger] ##### 阻止默认事件 -- passive
1 . `passive`主要用在移动端的scroll事件,来提高浏览器响应速度,提升用户体验。因为passive=true等于提前告诉了浏览器,`touchstart`和`touchmove`不会阻止默认事件,手刚开始触摸,浏览器就可以立刻给与响应;否则,手触摸屏幕了,但要等待`touchstart`和`touchmove`的结果,多了这一步,响应时间就长了,用户体验也就差了。
~~~
<!-- 滚动事件的默认行为 (即滚动行为) 将会立即触发, -->
<!-- 而不会等待 `onScroll` 完成, -->
<!-- 以防止其中包含 `event.preventDefault()` 的情况 -->
<div @scroll.passive="onScroll">...</div>
~~~
>[danger] ##### 特定按键 .{keyAlias}
[按键别名](https://v3.cn.vuejs.org/guide/events.html#%E6%8C%89%E9%94%AE%E5%88%AB%E5%90%8D)
>[info] ## 官方文档位置
[官方文档](https://cn.vuejs.org/guide/essentials/event-handling.html#listening-to-events)
[官网事件地址](https://v3.cn.vuejs.org/api/directives.html#v-on)
- 官网给的工具
- 声明vue2 和 vue3
- 指令速览
- Mustache -- 语法
- v-once -- 只渲染一次
- v-text -- 插入文本
- v-html -- 渲染html
- v-pre -- 显示原始的Mustache标签
- v-cloak -- 遮盖
- v-memo(新)-- 缓存指定值
- v-if/v-show -- 条件渲染
- v-for -- 循环
- v-bind -- 知识
- v-bind -- 修饰符
- v-on -- 点击事件
- v-model -- 双向绑定
- 其他基础知识速览
- 快速使用
- 常识知识点
- key -- 作用 (后续要更新)
- computed -- 计算属性
- watch -- 侦听
- 防抖和节流
- vue3 -- 生命周期
- vue-cli 和 vite 项目搭建方法
- vite -- 导入动态图片
- 组件
- 单文件组件 -- SFC
- 组件通信 -- porp
- 组件通信 -- $emit
- 组件通信 -- Provide / Inject
- 组件通信 -- 全局事件总线mitt库
- 插槽 -- slot
- 整体使用案例
- 动态组件 -- is
- keep-alive
- 分包 -- 异步组价
- mixin -- 混入
- v-model-- 组件
- 使用计算属性
- v-model -- 自定义修饰符
- Suspense -- 实验属性
- Teleport -- 指定挂载
- 组件实例 -- $ 属性
- Option API VS Composition API
- Setup -- 组合API 入口
- api -- reactive
- api -- ref
- 使用ref 和 reactive 场景
- api -- toRefs 和 toRef
- api -- readonly
- 判断性 -- API
- 功能性 -- API
- api -- computed
- api -- $ref 使用
- api -- 生命周期
- Provide 和 Inject
- watch
- watchEffect
- watch vs. watchEffect
- 简单使用composition Api
- 响应性语法糖
- css -- 功能
- 修改css -- :deep() 和 var
- Vue3.2 -- 语法
- ts -- vscode 配置
- attrs/emit/props/expose/slots -- 使用
- props -- defineProps
- props -- defineProps Ts
- emit -- defineEmits
- emit -- defineEmits Ts
- $ref -- defineExpose
- slots/attrs -- useSlots() 和 useAttrs()
- 自定义指令
- Vue -- 插件
- Vue2.x 和 Vue3.x 不同点
- $children -- 移除
- v-for 和 ref
- attribute 强制行为
- 按键修饰符
- v-if 和 v-for 优先级
- 组件使用 v-model -- 非兼容
- 组件
- h -- 函数
- jsx -- 编写
- Vue -- Router
- 了解路由和vue搭配
- vueRouter -- 简单实现
- 安装即使用
- 路由懒加载
- router-view
- router-link
- 路由匹配规则
- 404 页面配置
- 路由嵌套
- 路由组件传参
- 路由重定向和别名
- 路由跳转方法
- 命名路由
- 命名视图
- Composition API
- 路由守卫
- 路由元信息
- 路由其他方法 -- 添加/删除/获取
- 服务器配置映射
- 其他
- Vuex -- 状态管理
- Option Api -- VUEX
- composition API -- VUEX
- module -- VUEX
- 刷新后vuex 数据同步
- 小技巧
- Pinia -- 状态管理
- 开始使用
- pinia -- state
- pinia -- getter
- pinia -- action
- pinia -- 插件 ??
- Vue 源码解读
- 开发感悟
- 练手项目