23.VUE之组件(绑定原生事件、$listeners、$ref)
目录
(1)组件绑定原生事件
(2)监听器属性ref与$refs注册引用信息属性和对象
组件绑定原生事件
有时,我们想要在一个组件的根元素上直接监听一个原生事件,一般操作步骤如下
1、首先定义一个 child 组件,什么事件都不绑定,代码如下:
步骤:
2、接下来,给 child 组件增加一个 @click 事件,如下所示
3、这个 handleClick 方法是谁的呢?当然是父作用域下的方法,所以接下来在根组件中增加一个方法,代码如下
分析验证:
当点击按钮的时候发现,没有弹框提示,也就是说 handleClick 方法根本没有执行,究其原因,在于此时组件绑定事件等价于自定义事件。
方案:
通过 $emit 事件派发传递给父组件,代码如下所示:
分析验证:
this.$emit方法也可以传递参数,修改代码,如下所示
组件绑定原生事件:
如上代码,在组件上绑定原生事件还需要自定义事件,过于麻烦。这个时候 .native 原生修饰符就派上用场了,代码如下
.native 原生修饰符的官方解释是: 监听组件根元素的原生事件!
接下来再看个案例,给组件根元素添加.native绑定原生事件(onblur失焦事件),即失焦时触发
优化:
为了提高用户体验,我们将根元素改为
验证后发现,此时原生事件不能被正常触发,即使用了.native也无效。
所以根元素为
监听属性 $ listeners :
为了解决这个问题,Vue 提供了一个 listeners属性上。
场景:
当组件的根元素不具备一些DOM事件,但是根元素内部元素具备相对应的DOM事件,那么可以使用$listeners获取父组件传递进来的所有事件函数,再通过v-on="xxxx"绑定到相对应的内部元素上即可。
分析:
因为child组件的外层根元素是一个label元素,所以默认情况下使用v-on:blur是无效的,所以需要配合listeners中不会体现出来的
监听属性$listeners案例 :
目前为止, 组件便是一个完全透明的包裹器了,也就是说它可以完全像一个普通的 元素一样使用了:所有跟它相同的特性和监听器的都可以工作。
小结:
1、组件根元素添加.native表示绑定原生事件
2、在开发里常通过props把构造器中data的值传递给组件,我们只要进行绑定就可以了,就是我们之前所介绍的v-bind:xxx
3、构造器即平时所说的Vue实例
基础扫盲
这里简单介绍几个vue小技巧
1、$ listeners,它是一个对象,里面包含了作用在这个组件上的所有监听器,你就可以配合 v-on="attrs的说明:listeners(自下而上传递数据), $attrs(自上而下多组件传递数据)
$listeners
listeners" 传入内部组件——在创建更高层次的组件时非常有用。
跨级通信方案
使用listeners实现祖孙组件之间的数据传递,也就是多重嵌套组件之间的数据传递
$attrs----向下传递
$listeners----向上传递
跨级组件传值通信
假设第三层组件想和第一层组件进行通信
1、(第一层组件向第三层组件传值)—禁止第一层直接传值到第三层,需要逐层传递,即1→2→3,此时便可以实现跨级组件向下通信
2、(第三层组件向第一层组件传值)—通过触发自定义事件将数据传递至第二层,然后第二层通过事件触发传递至第一层,如此逐层传递,便可以实现跨级组件向上通信
跨级向下通信$attrs:
首先测试下跨级通信中的向下通信
跨级向上通信:
接下来测试下跨级向上通信
跨级向上通信:
接下来添加数据操作,因为单向数据流规定:后代组件不可以直接修改父组件传值,所以需要在后代组件里设置传值缓存,然后再事件回传.
数据传递
简单总结下数据传递方向
之前使用 $attrs 实现数据的向下传递, 但是又怎么实现下层数据或事件的向上交互呢? 这里就要使用到 $listeners
$attrs是向下传递数据, $listeners 是向上传递方法,接受对象里的方法,来触发从父级接受来的函数。
$ ref与$refs
官方文档描述$ref:
$ref用法大概分为两种,普通DOM元素用法和组件用法
(1)普通DOM元素用法
有时Vue项目需要操作DOM节点,所以需要获取DOM。一般来讲,获取DOM元素,需document.querySelector()获取这个dom节点,然后才能进一步操作。
(1)普通DOM元素用法
旧版做法,document.querySelector()获取节点然后操作
新版做法:用ref绑定之后,我们就不需要在获取dom节点了,直接在上面的input上绑定refs.$ref即可调用,这样就可以减少获取dom节点的消耗。
(2)组件component用法
案例:利用组件,实现计数器count效果
1、首先封装个简单的组件,每次点击+1,调用两次
2、接下来,想在HTML模板里获取两个组件次数的和。此时需要在父组件获取子组件的状态变化,即自定义事件,利用发布订阅模式。
最后,获取两个组件实例单独的数据,相加即可
官方文档描述小结:
$ref:注册引用信息属性,用来给元素或子组件注册引用信息。
$refs:一个对象,持有已经注册过ref的所有子组件。
通俗理解:
$ref:注册引用信息属性
$refs:注册引用信息对象
$ ref含义:
被用来给元素或子组件注册引用信息,引用信息将会注册在父组件的$refs对象上。如果在普通的DOM元素上使用,那么指向的就是普通的DOM元素。
$ref 三种用法:
1、ref 加在普通的元素上,用this.ref.name 获取到的是dom元素
2、ref 加在子组件上,用this.ref.name 获取到的是组件实例,可以使用组件的所有方法。
3、利用 v-for 和 ref 获取一组数组或者dom 节点
小结:
1、refs对象上。如果在普通的DOM元素上使用,那么指向的就是普通的DOM元素
2、$refs:一个对象,持有注册过 ref 特性 的所有 DOM 元素和组件实例
注意:refs只会在组件渲染完成之后生效,并且它们不是响应式的。这只意味着一个直接的子组件封装的“逃生舱”——你应该避免在模板或计算属性中访问 $refs 。