文章目录
- 一、事件处理
- 1.1 监听事件
- 1.2 事件修饰符
- 1.3 按键修饰符
- 1.4 实例
- 二、表单综合案例
- 三、自定义组件
一、事件处理
1.1 监听事件
我们可以使用 v-on 指令 (简写为 @) 来监听 DOM 事件,并在事件触发时执行对应的 JavaScript。用法:v-on:click="handler"
或 @click="handler"
。
事件处理器 (handler) 的值可以是:
- 内联事件处理器:事件被触发时执行的内联 JavaScript 语句 (与 onclick 类似)。
- 方法事件处理器:一个指向组件上定义的方法的属性名或是路径。
这两种在前面的博客已经有体现
1.2 事件修饰符
在处理事件时调用 event.preventDefault() 或 event.stopPropagation() 是很常见的。尽管我们可以直接在方法内调用,但如果方法能更专注于数据逻辑而不用去处理 DOM 事件的细节会更好。
为解决这一问题,Vue 为 v-on 提供了事件修饰符。修饰符是用 .
表示的指令后缀,包含以下这些:
- .stop
- .prevent
- .self
- .capture
- .once
- .passive
<!-- 单击事件将停止传递 -->
<a @click.stop="doThis"></a><!-- 提交事件将不再重新加载页面 -->
<form @submit.prevent="onSubmit"></form><!-- 修饰语可以使用链式书写 -->
<a @click.stop.prevent="doThat"></a><!-- 也可以只有修饰符 -->
<form @submit.prevent></form><!-- 仅当 event.target 是元素本身时才会触发事件处理器 -->
<!-- 例如:事件处理器不来自子元素 -->
<div @click.self="doThat">...</div>
使用修饰符时需要注意调用顺序,因为相关代码是以相同的顺序生成的。因此使用@click.prevent.self会阻止元素及其子元素的所有点击事件的默认行为,而@click.self.prevent 则只会阻止对元素本身的点击事件的默认行为。
<!-- 添加事件监听器时,使用 `capture` 捕获模式 -->
<!-- 例如:指向内部元素的事件,在被内部元素处理前,先被外部处理 -->
<div @click.capture="doThis">...</div><!-- 点击事件最多被触发一次 -->
<a @click.once="doThis"></a><!-- 滚动事件的默认行为 (scrolling) 将立即发生而非等待 `onScroll` 完成 -->
<!-- 以防其中包含 `event.preventDefault()` -->
<div @scroll.passive="onScroll">...</div>
.capture、.once 和 .passive 修饰符与原生 addEventListener 事件相对应
请勿同时使用 .passive 和 .prevent,因为 .passive 已经向浏览器表明了你不想阻止事件的默认行为。如果你这么做了,则.prevent 会被忽略,并且浏览器会抛出警告。
1.3 按键修饰符
在监听键盘事件时,我们经常需要检查特定的按键。Vue 允许在 v-on 或 @ 监听按键事件时添加按键修饰符。
<!-- 仅在 `key` 为 `Enter` 时调用 `submit` -->
<input @keyup.enter="submit" />
你可以直接使用 KeyboardEvent.key 暴露的按键名称作为修饰符,但需要转为 kebab-case 形式。
<input @keyup.page-down="onPageDown" />
在上面的例子中,仅会在 $event.key 为 ‘PageDown’ 时调用事件处理。
按鍵別名
Vue 为一些常用的按键提供了别名:
- .enter
- .tab
- .delete (捕获“Delete”和“Backspace”两个按键)
- .esc
- .space
- .up
- .down
- .left
- .right
1.4 实例
事件冒泡
是指在计算机编程中的一种事件传递机制。
在事件驱动的编程模型中,当用户与程序交互时,例如点击鼠标或按下键盘,这些操作会触发相应的事件。事件冒泡是指当一个元素上的事件被触发时,它会向上级元素传递,直到根元素,这个过程就像气泡从底部冒到顶部一样。
那有时候我们不需要这种情况发生,该怎么解决呢?用咱们的事件修饰符
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title></title><script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.10/vue.js"></script><style>.red{width: 400px;height: 400px;background-color: red;}.orange{width: 300px;height: 300px;background-color: orange;}.blue{width: 200px;height: 200px;background-color: blue;}.black{width: 100px;height: 100px;background-color: black;}</style></head><body><!-- 定义边界 --><div id="app"><p>冒泡事件</p><div class="red" @click="red"><div class="orange" @click="orange"><div class="blue" @click="blue"><!-- 添加stop修饰符阻止冒泡 --><div class="black" @click.stop="black"></div></div></div></div><p>提交答案</p><!-- 只能点一次 --><button @click.once="dosub">提交</button><p>按键修饰符</p><input v-on:keyup.enter="dosub" /></div></body><script type="text/javascript">// 绑定边界 ES6具体体现new Vue({el: '#app',data() {return {f200: 'f200'};},methods: {red() {alert("red");},orange() {alert("orange");},blue() {alert("blue");},black() {alert("black");},dosub(){alert("提交");}}})</script>
</html>
二、表单综合案例
在前端处理表单时,我们常常需要将表单输入框的内容同步给 JavaScript 中相应的变量。手动连接值绑定和更改事件监听器可能会很麻烦:
<input:value="text"@input="event => text = event.target.value">
v-model 指令帮我们简化了这一步骤:
<input v-model="text">
另外,v-model 还可以用于各种不同类型的输入,<textarea>、<select>
元素。它会根据所使用的元素自动使用对应的 DOM 属性和事件组合:
- 文本类型的
<input>
和<textarea>
元素会绑定 value property 并侦听 input 事件; <input type="checkbox">
和<input type="radio">
会绑定 checked property 并侦听 change 事件;<select>
会绑定 value property 并侦听 change 事件。
<!DOCTYPE html>
<html><head><meta charset="utf-8"><script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script><title>表单</title></head><body><div id="app"><h1>vue表单</h1><label>姓名:</label><input v-model="uname" /><br /><label>密码:</label><input v-model="upwd" type="password" /><br /><!-- 将用户的输入值转为 Number 类型 --><label>年龄:</label><input v-model.number="age" /><br /><label>性别:</label><input type="radio" v-model="sex" name="sex" value="1" />男<input type="radio" v-model="sex" name="sex" value="0" />女<br /><label>爱好:</label><div v-for="h in hobby"><input type="checkbox" v-model="hobbies" v-bind:value="h.id" />{{h.name}}</div><label>类别:</label><select v-model="type"><option value="-1">===请选择===</option><option v-for="t in types" v-bind:value="t.id">{{t.name}}</option></select><br /><label>备注:</label><textarea v-bind:value="mark"></textarea><br />确认<input type="checkbox" v-model="flag" /><input type="submit" v-bind:disabled="show" v-on:click="doSubmit" /></div></body><script type="text/javascript">new Vue({el: '#app',data() {return {uname: null,upwd: null,age: 10,sex: 1,hobby: [{id: 1,name: '唱'}, {id: 2,name: '跳'}, {id: 3,name: 'rap'}, {id: 4,name: '篮球'}],hobbies: [],types: [{id: 1,name: '天帝'}, {id: 2,name: '仙王'}, {id: 3,name: '人皇'}],type: null,mark: '学生备注',flag: false}},computed: {show: function() {return !this.flag;}},methods: {doSubmit: function() {console.log('doSubmit')var obj = {uname: this.uname,upwd: this.upwd,age:this.age+10,sex: this.sex,hobbies:this.hobbies,type: this.type,mark: this.mark,}console.log(obj);}}})</script>
</html>
三、自定义组件
Props
Props是一种特别的 attributes,你可以在组件上声明注册。当一个值被传递给 prop 时,它将成为该组件实例上的一个属性。该属性的值可以像其他组件属性一样,在模板和组件的 this 上下文中访问。
一个组件可以有任意多的 props,默认情况下,所有 prop 都接受任意类型的值。
父传子
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title></title><script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script></head><body><div id="app"><h1>{{msg}}</h1><!-- 使用自定义组件my-button的时候进行传值(相当于jsp标签往助手类中传值的概念) --><my-button m="荒 "@click="nb"></my-button></div></body><script>// 定义全局组件的方式Vue.component('my-button', {props: ['m'],template: '<button v-on:click="doClickMyButton">我是一个自定义组件,被{{m}}点了{{n}}次</button>',data: function() {return {n: 0};},methods: {doClickMyButton: function() {console.log('doClickMyButton方法被调用');this.n++;}}}),new Vue({el: "#app",data(){return{msg:'自定义组件'};}});</script>
</html>
子传父
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title></title><script src="https://cdn.bootcss.com/vue/2.6.10/vue.js"></script></head><body><div id="app"><h1>{{msg}}</h1><!-- 使用自定义组件my-button的时候进行传值(相当于jsp标签往助手类中传值的概念) --><my-button m="荒 " @click='nb'></my-button></div></body><script>// 定义全局组件的方式Vue.component('my-button', {props: ['m'],template: '<button v-on:click="doClickMyButton">我是一个自定义组件,被{{m}}点了{{n}}次</button>',data: function() {return {n: 0};},methods: {doClickMyButton: function() {console.log('doClickMyButton方法被调用');this.n++;this.$emit('click', this.n, '荒', '石昊');}}}),new Vue({el: "#app",data() {return {msg: '自定义组件'};},methods: {nb: function(a, b, c) {console.log('方法被调用');console.log(a, b, c);}}});</script>
</html>