课程大纲
目录
一、事件操作
事件event对象是脚本开发中一个非常重要的对象,Vue中对事件和事件对象进行了良好的支持
(1) 事件绑定
通过 v-on: 事件名称绑定事件操作, 语法上可以优化为 @事件名称 完成事件绑定操作!
(2) 事件对象
事件操作函数不带参数的时候,事件处理函数的第一个形式参数,默认就是事件对象!这里也不需要添加兼容性写法
(3) 带参数的事件对象
事件操作函数如果附带参数的情况下,Vue提供了显式的事件对象:$event,用于事件函数传参
事件绑定和事件对象代码案例:
<div id="app">
<!-- 事件绑定 -->
<button v-on:click="handsEvent_1">点击我试试</button>
<button @click="handsEvent_1">试试就试试</button>
<!-- 事件对象 -->
<!-- 如果不传实参, 函数默认第一个形参就是事件对象 -->
<!-- 如果传入实参, 事件对象形参就要固定写为 $event -->
<div>
<input type="text" @keyup="handleDelEvent($event,10)">
</div>
</div>
<script src="../vue.min.js"></script>
<script>
const vm = new Vue({
el: '#app',
data: {
},
methods: {
handsEvent_1() {
alert('我被点击了')
},
handleDelEvent(e, index) {
console.log('要删除的数据值' + e.target.value);
console.log('要删除的索引' + index);
}
}
})
</script>
(4) 事件修饰符
事件操作过程中,会包含很多事件的附加操作,如阻止默认行为、阻止事件冒泡、事件一次性触发等等,Vue
中提供了对应的事件修饰符,可以在事件绑定时直接完成关联
- .stop : 阻止事件冒泡
- .prevent :阻止默认行为
- .capture : 捕获触发
- .once :一次性触发
- .self : 独立触发
- .passive : 滚动行为
思考;原生JS
中和事件相关的一些兼容性问题,整理出来!
(6) 案例操作
和事件相关的案例代码:
<!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>
<style>
#app{height:2000px;}
.outer{width: 500px; background:orange;padding: 10px;}
.inner{width: 300px; background: red; padding: 10px;}
</style>
</head>
<body>
<div id="app">
<!-- 1、事件绑定,通过v-on指令进行操作 -->
<div>
<button @click="handleEvent">1、事件绑定</button>
</div>
<!-- 2、事件对象,获取鼠标位置-->
<div>
<button @click="handleEvent2">2、直接操作事件对象</button>
</div>
<!-- 3、事件对象,传递参数数据-->
<div>
<h5>3、带参数的情况下传递事件对象</h5>
<input type="text" @keyup="handleDelEvent($event, 10)">
</div>
<!-- 4、事件触发修饰符 -->
<div>
<div class="outer" @click="handleOuter">
<div class="inner" @click="handleInner">
<button @click.stop="handleTarget">点击按钮,阻止冒泡: .stop</button>
</div>
</div>
</div>
<div>
<a href="https://www.baidu.com" @click.prevent="handleMsg">百度一下,阻止默认行为: .prevent</a>
</div>
<div>
<button id="btn" @click.once="handlerOnce">点击我试试,一次性事件: .once</button>
</div>
<div>
<div class="outer" @click.capture="handleOuter">
<div class="inner" @click.capture="handleInner">
<button @click="handleTarget">点击按钮,捕获触发->冒泡触发: .capture</button>
</div>
</div>
</div>
<div>
<div class="outer" @click="handleOuter">
<div class="inner" @click.self="handleInner">
<button @click="handleTarget">点击按钮,事件独立触发: .self</button>
</div>
</div>
</div>
<div>
<div class="outer" @click="handleOuter">
<div class="inner" @click="handleInner">
<a href="https://www.baidu.com" @click.prevent.stop="handleMsg">百度一下 如何阻止冒泡的同时阻止默认行为?</a>
</div>
</div>
</div>
</div>
<button id="btn">点击我试试,一次性事件</button>
<script src="./vue.js"></script>
<script>
// let btn = document.querySelector("#btn")
btn.onclick = function() {
alert("考试结算")
btn.onclick = null;
}
const vm = new Vue({
el: "#app",
methods: {
handleEvent() {
alert("事件被触发了.")
},
handleEvent2(e) {
console.log("事件对象", e)
console.log(e.clientX, e.clientY, "浏览器窗口")
console.log(e.pageX, e.pageY, "网页文档")
console.log(e.screenX, e.screenY, "屏幕窗口")
},
handleDelEvent(e, index) {
console.log("要删除的数据索引:" + index)
console.log("要删除的数据值:" + e.target.value)
},
handleTarget() {
console.log("按钮被点击了")
},
handleInner() {
console.log("inner div 被点击了")
},
handleOuter() {
console.log("outer div 被点击了")
},
handleMsg() {
console.log("该功能正在升级中...")
},
handlerOnce() {
console.log("用户点击了按钮")
}
}
})
</script>
</body>
</html>
二、表单操作
网页中有一个非常重要的组件:表单,完成了用户对数据的输入!
Vue
中提供了一个非常重要的指令:v-model
,用于自动接受用户输入的数据!
代码操作:
<!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">
<form action="">
<div>
<label for="username">账号</label>
<input type="text" v-model="formData.username">
<span>{{ formData.username }}</span>
</div>
<div>
<label for="password">密码</label>
<input type="password" v-model="formData.password">
<span>{{ formData.password }}</span>
</div>
<div>
<label for="age">年龄</label>
<input type="text" v-model="formData.age">
<span>{{ formData.age }}</span>
</div>
<div>
<label for="gender">性别</label>
<input type="radio" name="gender" value="男" v-model="formData.gender">男
<input type="radio" name="gender" value="女" v-model="formData.gender">女
<span>{{ formData.gender }}</span>
</div>
<div>
<label for="fav">爱好</label>
<input type="checkbox" name="fav" value="篮球" v-model="formData.fav">篮球
<input type="checkbox" name="fav" value="旅游" v-model="formData.fav">旅游
<input type="checkbox" name="fav" value="电影" v-model="formData.fav">电影
<input type="checkbox" name="fav" value="阅读" v-model="formData.fav">阅读
<input type="checkbox" name="fav" value="游戏" v-model="formData.fav">游戏
<span>{{formData.fav}}</span>
</div>
<div>
<label for="address">地址</label>
<select v-model="formData.address">
<option value="郑州">郑州</option>
<option value="广州">广州</option>
<option value="兰州">兰州</option>
<option value="苏州">苏州</option>
<option value="杭州">杭州</option>
<option value="柳州">柳州</option>
</select>
<span>{{formData.address}}</span>
</div>
<div>
<label for="introduction">简介</label>
<textarea cols="30" rows="3" v-model="formData.introduction"></textarea>
<span>{{formData.introduction}}</span>
</div>
<div>
<input type="submit" value="提交" @click.prevent="submit">
</div>
</form>
</div>
<script src="./vue.js"></script>
<script>
const vm = new Vue({
el: "#app",
data: {
formData: {
username: '',
password: '',
age: '',
gender: '',
fav: [],
address: '',
introduction: ''
}
},
methods: {
submit() {
console.log("用户准备提交表单,验证数据,发送ajax请求")
console.log(this.formData)
// $.ajax({
// url: "http://localhost:3000/api/login",
// type: "post",
// data: this.formData,
// success: res => {
// if(res.code === 200) {
// }
// }
// })
}
}
})
</script>
</body>
</html>
三、数据双向绑定
(1) 什么是数据双向绑定
所谓数据双向绑定,是出现在前端应用中的一个专业术语,描述了数据在界面和数据处理部分之间的关联关系,数据在视图界面和脚本数据处理部分实现了双向关联,所以称这样的操作模式为数据双向绑定,简称MVVM
代码操作:
<body>
<div id="app">
<input type="text" v-model="name">
<p>用户输入的数据:{{name}}</p>
</div>
<script src="./vue.js"></script>
<script>
const vm = new Vue({
el: "#app",
data: {
name: "DAMU"
}
})
</script>
</body>
备注:表单的操作,也可以添加表单修饰符、按键修饰符
表单修饰符:
-
v-model.trim
:剔除输入数据两侧的空格 -
v-model.number
:将数据转换成数值,如果转换不成功就什么都不做 -
v-model.lazy
:延迟数据同步,失去焦点的时候再完成同步
按键修饰符:
-
@click.enter
:按下回车键 -
@click.esc
:按下esc
键
(2) 数据双向绑定的问题
编写一个添加用户名称的案例,核心操作通过事件函数向数组中添加数据并完成页面上的数据渲染
① 正确的添加和渲染
this.names.push(this.name) // 添加数据【成功】,渲染数据【成功】
② 出现问题的添加
this.names[this.names.length] = this.name // 添加数据【成功】,渲染数据【失败】
总结:渲染失败的问题
Vue
中存在一种机制,可以监听变量中的数据是否发生变化,一旦数据发生变化就需要通知页面进行更新;假设这样的机制监听了数组的push
函数,所以push()
数据时添加和渲染都没有问题;但是没有监听通过下标进行添加数据的操作,所以下标增加数据成功但是无法在页面上完成渲染!
浏览器控制台打开vm
实例,查看names
属性时,发现原型对象上挂载了数组的部分函数(接收vue
实例进行管理和监听的,当数组中的数据经过这些函数完成数据更新,会自动完成数据渲染);这部分函数以外的其他操作方式可能会改变数组数据但是不会引起页面重新渲染!
思考:这样的监听方式(如何监听变量数据的变化),底层是如何实现的?
补充:如果一定要通过索引的方式完成数据的添加Vue2.x
版本中,提供了一个系统函数$set()
可以完成数据的添加和渲染
// 3、使用框架内建函数完成
// this/vm.$set(数组, 索引, 数据)
this.$set(this.names, this.names.length, this.name)
(3) 底层实现原理
Vue
中底层对变量进行了 数据劫持(变量的一种声明方式),就可以监控变量中数据的变化,也是Vue
中数据双向绑定的底层实现原理,如图所示: