$attrs/$listeners的使用场景 -- vue组件通信系列

简介: $attrs/$listeners的使用场景 -- vue组件通信系列

$attrs/$listeners的使用场景 -- vue组件通信系列


vue组件的数据通信方式很多,本篇着重讲$attrs/$listeners,神助是v-bind="$attrs"/v-on="$listeners

$attrs/$listeners的常用场景:封装第三方组件或者表单组件,从而减少组件处理成本。

$attrs

使用组件的时候,vue内部会将组件上面的属性,自动会合并到组件内部根元素上面。

<template lang="pug">
  list-item(a="a" b="b" c="c" style="color:red")
</template>
<!-- ListItem组件 -->
<template lang="pug">
  section(title="hello") 我是组件内部
</template>

渲染的时候会这样

<section title="hi" a="a" b="b" c="c">组件内部</section>

但这里限制在组件根元素上,若,组件内部其他元素也需要使用属性呢,此时就用到$attrs。

<template lang="pug">
section(title="hi") 组件内部
  //- { "a": "a", "b": "b", "c": "c" }
  div {{$attrs}}
</template>

这里如果不希望根元素继承那些属性,可以在组件内部配置inheritAttrs: false

$listeners

同理,对于事件,如果组件上面的事件是native模式,组件内部的最外层元素也会自动绑定该事件。

<template lang="pug">
  list-item(@click.native="()=>{ title = 1}")
</template>
<!-- ListItem组件 -->
<template lang="pug">
  section 我是组件内部
</template>

渲染的时候,事件就会自动绑定到最外层元素上面

<section @click="()=>{ title = 1}">组件内部</section>

但这里任然限制在组件根元素上,若,组件内部其他元素也需要绑定事件呢,此时就用到$listeners,其是非native事件的合集。

网络异常,图片无法展示
|

<template lang="pug">
//- 父组件
div
  span {{title}}
  list-item(
    @click="()=>{ title = '点了 内部绑定事件的元素'}"
    @mousedown="()=>{ title = 'mousedown'}"
    @click.native="()=>{ title='点了 内部根元素'}")
</template>
<script>
import ListItem from "@/components/ListItem";
export default {
  name: "List",
  components: { ListItem },
  data() {
    return {
      title: "点击组件的不同元素修改标题"
    };
  }
};
</script>
<template lang="pug">
section(title="hi") 组件根元素
  div(@click.stop="$listeners.click") 组件绑定事件的元素
</template>
<script>
export default {
  name: "ListItem",
  mounted() {
    // {click:fn,mousedown:fn}
    console.log("$listeners", this.$listeners);
  }
};
</script>

使用场景:封装第三方组件、表单组件

封装第三方组件、或者表单组件的的时候使用,往往结合v-bind="$attrs"/v-on="$listeners",这样就不用考虑用户给组件传入什么属性或者事件了。

比如希望封装baidu-map组件,而baidu-map上面的属性和事件直接用他们自己库的。

<template lang="pug">
  enforced-map(:title="title" @resizeMap="...")
</template>
<!-- EnforcedMap.vue  -->
<template lang="pug">
div
  baidu-map(v-bind="$attrs" v-on="$listeners")
</template>

封装表单组件的时候,inputListeners之类的计算属性通常非常有用。

始终牢记,子组件想要改变父组件的数据,需要$emit哈。

网络异常,图片无法展示
|

<template lang="pug">
//- 父组件
div
  enhanced-input(v-model="title" label='标题')
  div {{title}}
</template>
<script>
import EnhancedInput from "@/components/ListItem";
export default {
  name: "List",
  components: { EnhancedInput },
  data() {
    return {
      title: "初始值"
    };
  }
};
</script>

组件内部如下:

<template lang="pug">
label {{label}}
  //- 这里记得绑定value的值,这样才能显示初始值
  input(v-bind="$attrs",:value="value",v-on="inputListeners")
</template>
<script>
export default {
  name: "enhanced-input",
  inheritAttrs: false,
  props: ["label", "value"],
  mounted() {},
  computed: {
    inputListeners() {
      const newListeners = {
        // 我们从父级添加所有的监听器
        ...this.$listeners,
        // 然后我们添加自定义监听器,或覆写一些监听器的行为
        // 这里确保组件配合 `v-model` 的工作
        input: event => this.$emit("input", event.target.value)
      };
      return newListeners;
    }
  }
};
</script>


目录
相关文章
|
1天前
|
JavaScript 程序员 网络架构
vue路由从入门到进阶 --- 声明式导航详细教程
vue路由从入门到进阶 --- 声明式导航详细教程
vue路由从入门到进阶 --- 声明式导航详细教程
|
1天前
|
资源调度 JavaScript UED
vue路由的基础知识总结,vueRouter插件的安装与使用
vue路由的基础知识总结,vueRouter插件的安装与使用
|
2天前
|
JavaScript 前端开发 安全
Vue响应式设计
【5月更文挑战第30天】Vue响应式设计
20 1
|
2天前
|
编解码 JavaScript API
Vue在移动端的表现如何?
【5月更文挑战第30天】Vue在移动端的表现如何?
8 2
|
2天前
|
JavaScript
Vue常用知识点总结
Vue常用知识点总结
10 0
|
3天前
|
JavaScript Java 测试技术
基于vue和微信小程序的校园自助打印系统+springboot+vue.js附带文章和源代码设计说明文档ppt
基于vue和微信小程序的校园自助打印系统+springboot+vue.js附带文章和源代码设计说明文档ppt
23 7
|
3天前
|
JSON JavaScript 前端开发
|
3天前
|
JavaScript 前端开发 Java
开发语言漫谈-Vue
Vue严格说来不是一门语言
|
5天前
|
JavaScript 前端开发 C++
【Vue】Vue快速入门、Vue常用指令、Vue的生命周期
【Vue】Vue快速入门、Vue常用指令、Vue的生命周期
13 2
|
7天前
|
存储 缓存 JavaScript
谈谈你对vue的了解
谈谈你对vue的了解
17 3