一、事件处理
1. 语法
Vue模板
v-on:xxx="处理函数"
@xxx(作为绑定事件的简写)="处理函数"
xxx指代的都是事件名
Vue实例
必须使用methods配置对象(配置多个函数方法)
methods中配置函数,都是Vue所管理,this的指向是vm或组件实例对象
不能使用箭头函数,否则this指向不是vm
注意事件处理函数可以分为带参和不带参数,带参如果是事件对象就用“,$”分割
@click="demo"
@click="demo($event)
<div id="root"> <h2>欢迎来到{{name}}</h2> <!-- 简写:v-on: 相当于@ --> <button @click="showInfo1">点我提示信息</button> <!-- ,隔开可以使用$获取事件对象 --> <button @click="showInfo2(66,$event)">点我提示信息</button> </div> </body> <script> Vue.config.production = false; /* 注意绑定事件的执行函数不能直接在script标签内声名(报错) function showInfo() { alert("你好"); } */ const vm = new Vue({ el: "#root", data: { name: "云贵川", }, methods: { showInfo1() { alert("你好"); // console.log(a, b, c, d); // console.log(this === vm); //普通函数此处的this指向的是vm }, // 如果使用箭头函数this会指向window /* showInfo: (e) => { console.log(this); }, */ showInfo2(number, event) { console.log(number, event); alert("同学!!"); }, }, }); </script>
2. 事件修饰符
prevent:阻止默认事件
stop:阻止事件冒泡
once:事件只触发一次(常用)
capture:使用事件的捕获模式
self:只有event.target是当前操作元素时才触发事件
passive:事件的默认行为立即执行(比如滚轮执行无需等待回调执行就会执行事件),无需等待事件回调执行完毕
修饰符可以连续写
<div id="root"> <!-- 阻止默认事件 --> <a href="http://www.baidu.com" @click.prevent="showInfo">点击提示</a> <!-- 阻止事件冒泡:使用在内层事件--> <div class="demo1" @click="showInfo"> <button @click.stop="showInfo">点击提示</button> <a href="http://www.baidu.com" @click.stop.prevent="showInfo">点击提示</a> </div> <!-- 事件只触发一次 --> <button @click.once="showInfo">点击提示</button> <!-- 使用事件的捕获模式:使用在外层事件 --> <div class="box1" @click.capture="showMsg(1)"> div1 <div class="box2" @click="showMsg(2)">div2</div> </div> <!-- 只有event.target是当前操作元素时才触发事件 --> <div class="demo1" @click.self="showInfo"> <button @click="showInfo">点击提示</button> </div> <!-- 事件的默认行为立即执行:优先使用滚动(移动端使用) --> <!-- scroll:(滚动条)滚动到最后位置就会停止 --> <!-- wheel:(滚轮)鼠标滚动轮滚动:会一直触发 --> <ul @wheel.passive="demo" class="list"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul> </div>
<script> Vue.config.production = false; const vm = new Vue({ el: "#root", data: { name: "xue", }, methods: { showInfo(e) { alert("同学你好"); // e.stopPropagation(); //阻止事件冒泡 console.log(e.target); }, showMsg(msg) { console.log(msg); }, demo() { for (let i = 0; i < 10000; i++) { console.log("#"); } console.log("运行结束"); }, }, }); </script>
3. 键盘事件(按下键盘或者键盘弹起执行事件)
回车: => enter
删除: => delete (捕获“删除”和“退格键”)
退出: => esc
空格: => space
换行: => tab (注意使用keydown事件进行配合)
上: => up
下: => down
左: => left
右: => right
Vue未提供别名的按键,可以使用按键原始的key值去绑定,但注意要为kebab-case(横线拼接小写英文命名)
<input type="text" placeholder="按下回车提示输入" @keyup.caps-lock="showInfo" />
系统修饰键:ctrl 、 alt、shift、meta(通过链式指定配合按键) (1)配合keyup使用,按下修饰键的同时,再按下(任意)其他键,最后释放其他键,事件才被触发(不太好:键盘事件弹起就会执行修饰键工作) (2)配合keydown使用,正常触发事件(简便) <input type="text" placeholder="按下回车提示输入" @keyup.ctrl="showInfo" /> <input type="text" placeholder="按下回车提示输入" @keydown.ctrl="showInfo" />
(NO)也可以使用keyCode指定具体的按键值(不推荐键码)
<input type="text" placeholder="按下回车提示输入" @keydown.13="showInfo" />
(NO)Vue.config.keyCodes.自定义键名 = 键码,可以定制按键别名
<input type="text" placeholder="按下回车提示输入" @keydown.13="showInfo" /> <!--以下是在vue中自定义键名--> Vue.config.keyCodes.huiche = 13; //自定义按键别名
二、计算属性
输入并实现插值语法拼接效果
1.使用插值语法进行拼接:优势:缓存优势
<body> <div id="root"> 姓:<input type="text" v-model="firstName" /> <br /> 名:<input type="text" v-model="lastName" /> <br /> <!-- 截取指定位置的字符串拼接 --> 全名:<span>{{firstName.slice(0,3)}}-{{lastName}}</span> </div> </body> <script> Vue.config.production = false; const vm = new Vue({ el: "#root", data: { firstName: "张", lastName: "三", }, }); </script>
2. 使用methods实现拼接(插值语法调用方法需要带())
<div id="root"> 姓:<input type="text" v-model="firstName" /> <br /> 名:<input type="text" v-model="lastName" /> <br /> <!-- 插值语法中使用方法必须使用() --> 全名:<span>{{fullName()}}</span> <br /> <!--调用多少次methods就会执行多少次:没有缓存--> 全名:<span>{{fullName()}}</span> <br /> 全名:<span>{{fullName()}}</span> <br /> 全名:<span>{{fullName()}}</span> </div>
<script> Vue.config.production = false; const vm = new Vue({ el: "#root", data: { firstName: "张", lastName: "三", }, methods: { fullName() { // 以下输出语句证明:data数据修改之后函数重新调用(说明模板重新解析) console.log("@-------------------"); return this.firstName + "-" + this.lastName; }, }, }); </script>
3. 计算属性实现拼接:cumputed注意要有返回值
底部规则使用的还是definedefineproperty中的getter
优势:计算属性中的方法的依赖数据有缓存属性,在执行多次输出相同结果调用时候只需要执行一次计算
<div id="root"> 姓:<input type="text" v-model="firstName" /> <br /> 名:<input type="text" v-model="lastName" /> 全名:<span>{{fullName}}</span><br /> </div>
computed: { // 具有缓存属性,当出现模板中相同代码片段时候直接从缓存处读取 fullName: { // get作用:当有人读取fullName,get就会被调用,并且返回值就是fullName的值 // get什么时候调用 /* 1. 初次读取fullName时候调用 2. 所依赖的数据发生变化 */ // ---------------------- // 注意以下的get和set不可以使用箭头函数,this的指向变成window get() { // console.log(this);//此处的this指向vm console.log("get调用"); return this.firstName + "-" + this.lastName + a; }, // 如果计算属性会被修改就必须存在setter //当fullName被修改时候会被调用 set(value) { console.log("set", value); // 字符产转为数组 const arr = value.split("-"); this.firstName = arr[0]; this.lastName = arr[1]; }, }, },
定义:要用的属性不存在,要通过已有的属性计算得来
原理:底层借用了Object.defineproperty方法提供的getter和setter
get函数什么时候执行
(1)初次读取会执行一次
(2)当数据发生变化时候会被再次调用
优势:与methods实现相比,内部有缓存机制(可复用),效率高,调用方便
备注:
1. 计算属性最终会出现在vm上,直接读取使用即可
2. 如果计算属性要被修改,必须写set函数相应修改,并且set中要应用引起计算时依赖的数据发生改变
如果计算属性确定只读不改:那么久只编译getter
全名:<span>{{fullName}}</span> // computed: { // 简写:没有set 只读不取 // 将原先的函数简写以下格式 // 此处将函数放在vm实例中 fullName() { console.log("get调用"); return this.firstName + "-" + this.lastName; }, },
三、监视属性
实现效果
1. 利用计算属性进行:三元表达式利用方法切换布尔值
<div id="root"> <h2>今天天气很{{info}}</h2> <button @click="changeWeather">切换</button> </div> </body> <script> Vue.config.production = false; const vm = new Vue({ el: "#root", data: { isHot: true, }, // 方法执行取反布尔值 methods: { changeWeather() { this.isHot = !this.isHot; }, }, // 利用三元表达式进行计算并返回结果,也可以将计算表达式直接写入插值语法 computed: { info() { return this.isHot ? "炎热" : "凉爽"; }, }, }); </script>
2.理解:监视属性
watch:{
监视属性:{
innediate:true(默认false):初始化就调用一次
监视回调函数
}
}
<div id="root"> <h2>今天的天气很{{info}}</h2> <button @click="changeWeather">切换天气</button> </div>
watch: { isHot: { immediate: true, //默认fasle,设置为true会初始化时候调用handler // 注意之前没有值就是undefined // handler什么时候调用?当isHot发生变化时候调用 handler(newVlaue, oldValue) { console.log("inHot被修改了", newVlaue, oldValue); }, }, },
//在Vue实例之外配置watch属性 vm.$watch("isHot", { immediate: true, handler(newVlaue, oldValue) { console.log("inHot被修改了", newVlaue, oldValue); }, });
简写监视属性:在没有immedit属性的时候才可以使用
// 简写:绝不允许使用箭头函数(改变了this指向) vm.$watch("isHot", function (newVlaue, oldValue) { console.log("inHot被修改了", newVlaue, oldValue); });
3. 深度监视:监测到data对象中更深层对象的数据
deep:true : 监测深层
"numbers.a" :监测指定深层某个数据
<div id="root"> <h2>今天的天气很{{info}}</h2> <button @click="changeWeather">切换天气</button> <hr /> <h3>a的值是{{numbers.a}}</h3> <button @click="numbers.a++">点击让我+1</button> <h3>b的值是{{numbers.b}}</h3> <button @click="numbers.b++">点击让我+1</button> <!-- 此处使用新的对象:就更改了原先的地址值 --> <button @click="numbers = {a:666,b:888}">彻底替换number</button> </div>
<script> Vue.config.production = false; const vm = new Vue({ el: "#root", data: { isHot: true, numbers: { a: 1, b: 1, }, }, computed: { info() { return this.isHot ? "炎热" : "寒冷"; }, }, methods: { changeWeather() { this.isHot = !this.isHot; }, }, watch: { isHot: { handler(newVlaue, oldValue) { console.log("inHot被修改了", newVlaue, oldValue); }, }, // 以下是多级结构进行监视 // 注意存在多个属性:所有的属性都添加到下main(太麻烦) "numbers.a": { handler() { console.log("a发生改变"); }, }, "numbers.b": { handler() { console.log("b发生改变"); }, }, // 此处检测的是整个对象(一个地址):但是添加deep属性就不一样了 numbers: { deep: true, handler() { console.log("numbers改变了"); }, }, }, }); </script>
4. 对比计算属性和监视属性
computed能完成的功能watch都可以完成
watch能完成的功能(主要优势异步任务),computed不一定能完成
注意:
所有被Vue管理的函数,最好写成普通函数,这样this的指向才是vm或者组件实例对象。
所有不被Vue管理的函数(定时器回调函数,ajax回调函数,promise的回调函数),最好写成箭头函数,这样this的指向才是vm或组件实例对象
<div id="root"> 姓:<input type="text" v-model="firstName" /> <br /> 名:<input type="text" v-model="lastName" /> <br /> 全名:<span>{{fullName}}</span> </div> </body> <script> Vue.config.production = false; const vm = new Vue({ el: "#root", data: { firstName: "张", lastName: "三", fullName: "张-三", }, // 监视属性:拼接字符 // 既需要监视姓也需要监视名(繁琐) // 优势:可以开启异步任务(计算属性不可以添加异步任务) // 注意:添加定时器时候回调函数应该是箭头函数:普通函数this指向window,箭头函数会向上找this,指向的是vm watch: { firstName(val) { setTimeout(() => { console.log(this); this.fullName = val + "-" + this.lastName; }, 1000); }, lastName(val) { this.fullName = this.lastName + "-" + val; }, }, }); </script>