Vue.js note4(事件对象$event&事件修饰符&vue的计算属性)

1、事件对象

  • 语法:<div @click=‘fn($event)’></div>中,$event为事件对象(固定写法)
  • 作用:记录事件相关的信息

比如下面的这个例子,我使用 $ event,当点击某个项的时候,打印输出事件源$event.target。(这个颜色的变化,是我为了让结果更清晰)

<div id="demoSky">
	<ul>
	    <li v-for="(item,index) in arr" @click="fun($event,item)" :class="item.bool?'changeColor':''">{{item.type}}</li>
	</ul>
</div>
<script>
	new Vue({
	     el: "#demoSky",
	     data: {
	         arr:[
	             {type:"游乐场",bool:false},
	             {type:"动物园",bool:false},
	             {type:"摩天楼",bool:false},
	         ],
	     },
	     methods:{
	       fun(e,item){
	           console.log(e.target);//e.target 事件源 
	           item.bool=!item.bool;
	       }
	     }
	 })
</script>

在这里插入图片描述
然后还需要注意一点:

Vue 对函数调用做了封装,加与不加括号的区别在于事件对象参数 event 的处理。
(1)不加括号时,函数第一个参数为 event;
(2)加了括号后,需要手动传入 $event 才能获得事件对象。

不加括号,说明只存引用,等用到的时候,再去找到执行。

《学习笔记:js里调用函数时,函数名带括号与不带括号的区别》:
https://blog.csdn.net/Miss_Audrey/article/details/54846893?utm_source=app

2、事件修饰符

  • 概念:v-on指令提供了事件修饰符来处理DOM事件细节
(一)按键修饰符
  • 主要有:.up .down .ctrl .enter .space
  • 语 法:@click.修饰符='fn()',比如 @keydown.ctrl=“fun($event)”,意为只有按下Ctrl按键的时候被触发。
<div id="demoSky">
   <input type="text" name="" id="" @keydown.space="fun($event)">
</div>
<script>
    new Vue({
        el: "#demoSky",
        data: {},
        methods:{
            fun(e){
              console.log("点击空格键:",e.target);
            }
        }
    })
</script>

在这里插入图片描述

(二)【扩展】事件修饰符
  • prevent:阻止事件的默认行为 (比如submit提交表单时)
  • stop 修饰符:阻止事件冒泡 (常用)
  • capture:与事件冒泡的方向相反,事件捕获由外到内
  • self:只会触发自己范围内的事件,不包含子元素
  • once:只会触发一次
  • 注意:修饰符可以串联使用

如下面,父亲包着儿子节点,然后父亲和儿子节点都绑定了事件,当点击儿子时,根据冒泡机制,先执行儿子的处理函数,然后执行父亲的。

<div id="demoSky">
    <div id="father" @click="fun('father')">父亲
        <div id="son"  @click="fun('son')">儿子</div>
    </div>
</div>
<script>
    new Vue({
        el:"#demoSky",
        data:{},
        methods:{
          fun(i){
              console.log(i);
          }
        }
    })
</script>

在这里插入图片描述
但现在我想点击哪个就只触发哪个,那么怎么做呢?大家应该想到了阻止事件冒泡这个方法。
原生JS的阻止冒泡使用的是:e.stopPropagation();;但在vue里面,可以简单使用事件修饰符stop来阻止事件冒泡。

修改事件绑定,给事件加上stop阻止冒泡修饰符:

<div id="son"  @click.stop="fun('son')">儿子</div>

结果就是当点击儿子的时候,只打印了“son”。


3、计算属性

(一)为什么要用计算属性

直白来讲,让一条数据在view层不同的位置显示不同的形态,在视图模板内使用表达式感觉非常方便,但设计它们的初衷是用于简单运算。

当在模板中放入太多的处理逻辑,会让模板过重且难以维护,比如 <p>{{text.toUpperCase().substr(2,1)}}</p>,一两个还好,如果全部的标签都这样来处理逻辑,代码可读性会变差,视图看起来也会特别复杂。

所以,可以把view层中的数据处理逻辑,放到计算属性中进行。

那么,使用计算属性的好处就显而易见了:可以使代码简洁,逻辑清晰

另外,计算属性还有一个特别优秀的地方:节省能耗。因为如果它监控的数据没有改变,多次调用计算属性,会从缓存里面读取数据。

(二)计算属性的概念

顾名思义,首先它是一种属性,其次它有“计算”这个特殊性质。每次取得它的值得时候,它并不像普通属性那样直接返回结果,而是经过一系列的计算之后再返回结果。同时只要在它的当中里引用了 data 中的某个属性,当这个属性发生变化时,计算属性仿佛可以嗅探到这个变化,并自动重新执行。

(三)计算属性–语法

computed是vue中与data同级的一个属性,然后记得最后一定要把结果return出来。

computed: {
    需要返回的数据-变量名: function () {
        return 处理操作
    }
}
(四)计算属性–使用

截取数据,并把数据转换成大写的小栗子。

<div id="demoSky">
    <p>原始数据:{{text}}</p>
    <p>截取数据:{{text.substr(3,7)}}---从第3个开始截取,截取7个字符</p>
    <p>大写数据:{{text.substr(6,6).toUpperCase()}}</p>
    ------------------------------------计算属性-------------------------------<br>    
    <p>截取数据:{{textSub1}}</p>
    <p>大写数据:{{textSub2}}</p>
</div>
<script>
    new Vue({
        el:"#demoSky",
        data:{
            text:"12345678abcd",
        },
        computed:{
            textSub1(){
                return this.text.substr(3,7);
            },
            textSub2(){
                return this.text.substr(6,6).toUpperCase();
            },
        }
    })
</script>

在这里插入图片描述

提个问题: 如果data中的变量名与computed中的变量名相同了的话,会怎样?
验证:在vue实例的模型数据data里面新增一条数据 textSub1:“textSub1”,查看页面上的变化。
在这里插入图片描述
发现data里的数据优先。


(五)计算属性VS方法

将计算属性跟我们在methods里写的方法进行对比,会发现他们所实现的功能很相似,都是处理逻辑。既然计算属性能完成的,方法也能完成,那么为什么还要使用计算属性?或者说,计算属性和方法有什么区别呢?

上面的例子也可以使用方法来完成:

<p>截取并大写数据:{{textSubFun1()}}</p>

// vue的methods属性里:
methods:{
    textSubFun1(){
        return this.text.toUpperCase().substr(2,2);
    }
}

计算属性与方法的区别:

  • 计算属性是基于依赖进行缓存的。计算属性只有在它的相关依赖发生改变时才会重新求值。
  • 方法绑定的数据只要被调用,调一次,执行 一次;调n次,执行n次。
  • 计算属性,调n次,不一定执行n次。
  • 计算属性中,只有当它监控的属性发生了变化,它才会重新计算;否则,会直接从缓存里面读取数据。所以相对于方法,计算属性在特定场合下能节省资源性能。

4、侦听/监听 watch

watch:可以监听模型数据,当模型数据改变的时候就会触发。

watch:{
    监听的data数据(newval,oldval){
        console.log(newval+"---"+oldval)
    }
}

PS:watch初始化的时候不会运行,只有数据被改变之后才会运行。

(一)什么时候使用watch

当需要在数据变化时执行异步开销较大的操作时,watch这个方式是最有用的。

(二)计算属性与侦听器watch的区别

当watch监听的值发生改变就会被调用,watch可以在数据变化时做一些异步处理或者开销大的操作。
而计算属性是计算依赖的值,当依赖的值发生改变才会触发。


5、虚拟 dom 与 diff 算法

(一)什么是虚拟DOM:

所谓的虚拟 dom,也就是我们常说的虚拟节点,它是通过JS的Object对象模拟DOM中的节点,然后再通过特定的render(渲染)方法将其渲染成真实的DOM的节点。

(一)为什么使用虚拟DOM

使用JQuery的时候,会大量操作DOM,那么DOM元素的变化自然会引起页面的回流或者重绘,页面的DOM重绘自然会导致页面性能下降。那么如何尽可能的去减少DOM的操作是框架需要考虑的一个重要问题!

(一)真实DOM和虚拟DOM的区别
  • 虚拟DOM不会进行排版与重绘操作
  • 真实DOM频繁排版与重绘的效率是相当低
  • 虚拟DOM进行频繁修改,然后一次性比较并修改真实DOM中需要改的部分,最后并在真实DOM中进行排版与重绘,减少过多DOM节点排版与重绘损耗
  • 虚拟DOM有效降低页面的重绘与排版,因为最后与真实DOM比较差异,可以只渲染局部
(一)DOM Diff

虚拟DOM,是一种为了尽可能减少页面DOM频繁操作DOM的方式,那么在虚拟DOM中,通过什么方式才能做到呢?

就是Diff算法。

(一)DOM Diff原理

逐步解析newdom的节点,找到它在olddom中的位置,如果找到了就移动对应的DOM元素,如果没找到说明是新增节点,则新建一个节点插入。遍历完成之后如果oldVdom中还有没处理过的节点,则说明这些节点在newVdom中被删除了,删除它们即可。

大师兄说: diff算法,同级比较和差异更新。同级比较就是DOM很少有跨层级移动;DOM的数据结构是一棵多叉树,同级比较将DOM更新所需要的时间复杂度从On3降到了O(n),这是一个巨幅的性能提升,尤其在处理复杂规模的DOM变换场景下有显著优势。差异更新,就是利用虚拟DOM,在变化的时候不直接更新,而是比较虚拟DOM的属性,只更新有差异的部分,减少回流。


综合练习:ToDoList 练习

在这里插入图片描述

要求:
1、实现 “添加新任务” 的功能

  • 使用 v-model 指令对用户输入内容进行双向绑定
  • 点击 “添加” 按钮,将输入的内容添加进任务数组

2、实现 “可勾选已完成任务” 的功能

  • 使用 v-model 指令对任务的勾选状态进行记录
  • 使用 v-bind 指令对任务进行 class 绑定
  • 将已勾选的选项设置为置灰状态

3、实现顶部数量信息展示

  • 任务总数为数组的长度
  • 遍历数组,查看待办事项状态,计算 “未完成” 任务数量
  • 点击 “完成” ,将删除所有已完成任务

4、实现 “任务编辑” 功能

  • 在 HTML 结构中添加表单元素
  • 使用 v-model 指令对用户输入内容进行双向绑定
  • 通过 v-show 指令控制表单与span标签的显示与隐藏(或者用 v-if 与 f-else)
  • 已完成任务不可进行修改

链接我的博客:Vue.js note3(指令混合练习todolist)中的第二个例子

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值