Vue中如何更好地封装组件?

  • 子组件接受父组件传递的事件

1.子组件使用@事件名="$emit('父组件中传递的事件名',想给父组件传递的参数(可选))"
@click="$emit('click')"
2.子组件使用
v-on="$listeners"

 父组件:

<template><div id="app"><myComponents :msg="form.msg" @click="a"/></div>
</template><script>
import myComponents from "./components/myComponents";export default {name: 'App',components: {myComponents},data(){return {form:{msg: "10"}}},methods:{a(){console.log('哈哈哈')},}
}
</script><style></style>

 子组件:

<template><div><!-- 子组件接收父组件传来的参数--><!-- v-on="$listeners" 和 @click="$emit('click')" 效果一样  两者选一即可--><h1 v-on="$listeners" @click="$emit('click')">{{ msg }}</h1></div>
</template><script>
export default {name: 'my-Components',props: {msg: {type: String,default: "18"}},created() {console.log(this.$listeners)  //一个对象,里面包含父组件传递过来的所有事件},methods: {}
}
</script>
<style scoped>
</style>
  • 父组件传值给子组件

1.子组件使用props声明想要的属性,再将该属性动态绑定给子组件
props: {msg: {type: String,default: "18"},
},
     然后子组件中绑定数据即可
    父组件使用prop声明,就可以传递给子组件

:prop="msg"

 <Head1 :name="form.name"/>

2.子组件使用$attrs,这个组件包含了被传入,但没有声明的prop

 子组件:

<template><div><!-- 子组件接收父组件传来的参数--><h1>{{ msg }}</h1></div>
</template><script>
export default {name: 'my-Components',
//不声明msg// props: {//   msg: {//     type: String,//     default: "18"//   },// },created() {console.log(this.$attrs)   //一个对象,包含父组件中被传入,但没有声明的prop},methods: {}
}
</script><style scoped>
</style>

打印结果: 

 此时h1标签上就有msg属性:

<template><div><!-- 子组件接收父组件传来的参数--><h1 v-bind="$attrs"> {{this.$attrs.msg}}</h1></div>
</template>

页面显示结果:

 

 需要注意的一点是:Vue会将被传入,但未声明的prop作为html属性,绑定到组件的根元素上:

可以设置属性 inheritattrs为false,将这些默认行为去掉,来解决这个问题。

<template><div><!-- 子组件接收父组件传来的参数--><h1 v-bind="$attrs"> {{this.$attrs.msg}}</h1></div>
</template><script>
export default {name: 'my-Components',inheritAttrs:false,
}
</script><style scoped>
</style>

  • 对外暴露子组件插槽

1.直接向子组件转发插槽,使用父组件的 $slots 
该组件包含了传递给父组件的非作用域插槽
使用$scopeSlots可传递给父组件的作用域插槽,这个组件包含了组件接受的所有插槽

子组件:

<template>
<el-input
v-model="innerVal"
v-bind-"$attrs
@input="$emit('input", $event)"v-on-"$listeners//子组件中写两个插槽
<template #append>
<slot name="append"></slot></template>
<template #prepend>
<slot name="prepend"></slot></template>
</el-input>
</template>

 打印this.$slots

  • props validator

一般我们会用对象的形式声明prop,可以在对象中指定prop的默认值,也可以指定类型,对prop进行验证。
一个更灵活的的方式是,传入并编写一个验证函数,prop会作为参数传入该函数,函数返回fals时,会抛出控制台警告,这种方式特别适合验证枚举值,

 子组件:

<template><div><!-- 子组件接收父组件传来的参数--><h1 v-on="$listeners" @click="$emit('click')" v-bind="$attrs"> {{this.$attrs.msg}}</h1></div>
</template><script>
export default {name: 'my-Components',inheritAttrs:false,props:{numberIs:{default: '1',//当传入的prop值不是1,2,3时,控制台会抛出警告validator: prop => ['1', '2', '3'].includes(prop)}},
}
</script>
<style scoped>
</style>

 父组件:

<template><div id="app"><!--  传入numberIs的值为4  --><myComponents :msg="form.msg" @click="a" numberIs="4"/></div>
</template><script>
import myComponents from "./components/myComponents";export default {name: 'App',components: {myComponents},data() {return {form: {msg: "10"},}},methods: {a() {console.log('哈哈哈')},}
}
</script><style></style>

$refs用于父组件获取整个子组件实例,然后可以使用子组件的方法和属性(暴露子组件方法)

父组件:

<template><div id="app"><!--  ref相当于给当前子组件设置了一个id,可以使用refs根据ref的值获取该组件  --><myComponents :msg="form.msg" @click="a" numberIs="1" ref="bb"/></div>
</template><script>
import myComponents from "./components/myComponents";export default {name: 'App',components: {myComponents},data() {return {form: {msg: "10"},}},methods: {a() {//获取ref值为bb的子组件,并调用该子组件上的show方法this.$refs.bb.show()},}
}
</script><style></style>

子组件:

<template><div><!-- 子组件接收父组件传来的参数--><h1 v-on="$listeners"  v-bind="$attrs"> {{this.$attrs.msg}}</h1></div>
</template><script>
export default {name: 'my-Components',inheritAttrs:false,props:{numberIs:{default: '1',//当传入的prop值不是1,2,3时,控制台会抛出警告validator: prop => ['1', '2', '3'].includes(prop)}},created() {},methods: {show(){console.log('1111')}}
}
</script><!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
</style>

打印 this.$refs 显示为:

 

 点击之后,控制台输出:

但在封装子组件后,如果不对子组件的方法进行暴露,调用时,我们往往需要通过ref先获取父组件实例,再获取子组件实例,这种方式导致组件代码难以维护:

//获取父组件bb之后,再获取子组件aa,最后使用aa中的show方法
this.$refs.bb.$refs.aa.show()

我们可以再父组件中提供与子组件同名的方法, 对外暴露,让使用者只通过父组件就可以进行调用:

子组件中:

methods:{show() {this.$refs.aa.show()}
}

父组件中:

methos: {show() {this.$refs.bb.show()}
}

总结:

1. $attrs 简化多层组件之间props传值;
2. $listeners 简化多层组件之间事件传递;
3. $Slots 更多拓展自定义组件传值,包括自定义html元素,及对象;
4. props validator 增强组件传值稳健性,可自定义业务代码效验参数;
5. $refs 对外提供API 增强组件灵活度和可控性; 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/35718.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MyBatis的XML映射文件

Mybatis的开发有两种方式&#xff1a; 注解 XML配置文件 通过XML配置文件的形式来配置SQL语句&#xff0c;这份儿XML配置文件在MyBatis当中也称为XML映射文件。 导学&#xff1a;在MyBatis当中如何来定义一份儿XML映射文件&#xff1f; 在MyBatis当中&#xff0c;定义XML…

使用 HTML、CSS 和 JavaScript 创建多步骤表单

使用 HTML、CSS 和 JavaScript 创建多步骤表单 为了处理又长又复杂的表单&#xff0c;我们需要将它们分成多个步骤。通过一次只在屏幕上显示一些输入&#xff0c;表单会感觉更容易理解&#xff0c;并防止用户感到被大量的表单字段淹没。 在本文中&#xff0c;我将逐步指导如何…

基础堆排序(Java 实例代码)

目录 基础堆排序 一、概念及其介绍 二、适用说明 三、过程图示 四、Java 实例代码 src/runoob/heap/Heapify.java 文件代码&#xff1a; 基础堆排序 一、概念及其介绍 堆排序&#xff08;Heapsort&#xff09;是指利用堆这种数据结构所设计的一种排序算法。 堆是一个近…

Linux_5_Shell脚本编程

目录 1 基础1.1 程序组成1.2 程序编程风格1.3 编程语言1.4 编程逻辑处理方式 2 shell 脚本语言的基本结构2.1 shell脚本的用途2.2 shell脚本基本结构2.3 创建shell脚本过程2.4 脚本注释规范2.5 第一个脚本2.6 脚本调试2.7 变量2.7.1 变量2.7.2 变量类型2.7.3 编程语言分类2.7.4…

【MAC】 M2 brew安装 docker 运行失败 解决

MAC 安装 brew install --cask docker 之后一直显示docker: Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?. 网上看了一些文章 发现 这个不适用于M2 所以要从官网上下载 docker 安装成功

C++ 动态规划经典案例解析之最长公共子序列(LCS)_窥探递归和动态规划的一致性

1. 前言 动态规划处理字符相关案例中&#xff0c;求最长公共子序列以及求最短编辑距离&#xff0c;算是经典中的经典案例。 讲解此类问题的算法在网上一抓应用一大把&#xff0c;即便如此&#xff0c;还是忍不住有写此文的想法。毕竟理解、看懂都不算是真正掌握&#xff0c;唯…

多线程与并发编程面试题总结

多线程与并发编程 多线程 线程和进程的区别&#xff1f; 从操作系统层面上来讲&#xff1a;进程(process)在计算机里有单独的地址空间&#xff0c;而线程只有单独的堆栈和局部内存空间&#xff0c;线程之间是共享地址空间的&#xff0c;正是由于这个特性&#xff0c;对于同…

vscode debug python 带参数

两种方法 第一种&#xff1a; 1&#xff0c;侧边栏选择运行和调试 2&#xff0c;请先创建一个launch.json文件 3&#xff0c;并选择配置文件为python文件 此时你的工作目录下会多一个目录.vscode和该目录下一个launch.json文件&#xff0c;该文件则配置了你的debug配置。在…

【报错】ModuleNotFoundError: No module named ‘websocket‘

1 报错 ModuleNotFoundError: No module named websocket 2 解决方法 pip install websocket 1 报错 AttributeError: module websocket has no attribute enableTrace 2 分析 一般是由于websocket的依赖包没有安装造成的。websocket.enableTrace()方法是在websocket-cli…

C语言第十课----------------扫雷----------数组的经典练手题

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; &#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382;…

React构建的JS优化思路

背景 之前个人博客搭建时&#xff0c;发现页面加载要5s才能完成并显示 问题 React生成的JS有1.4M&#xff0c;对于个人博客服务器的带宽来说&#xff0c;压力较大&#xff0c;因此耗费了5S的时间 优化思路 解决React生成的JS大小&#xff0c;因为我用的是react-router-dom…

prometheus告警发送组件部署

一、前言 要实现Prometheus的告警发送需要通过alertmanager组件&#xff0c;当prometheus触发告警策略时&#xff0c;会将告警信息发送给alertmanager&#xff0c;然后alertmanager根据配置的策略发送到邮件或者钉钉中&#xff0c;发送到钉钉需要安装额外的prometheus-webhook…

模拟实现消息队列(以 RabbitMQ 为蓝本)

目录 1. 需求分析1.1 介绍一些核心概念核心概念1核心概念2 1.2 消息队列服务器&#xff08;Broker Server&#xff09;要提供的核心 API1.3 交换机类型1.3.1 类型介绍1.3.2 转发规则&#xff1a; 1.4 持久化1.5 关于网络通信1.5.1 客户端与服务器提供的对应方法1.5.2 客户端额外…

【LangChain概念】了解语言链️:第2部分

一、说明 在LangChain的帮助下创建LLM应用程序可以帮助我们轻松地链接所有内容。LangChain 是一个创新的框架&#xff0c;它正在彻底改变我们开发由语言模型驱动的应用程序的方式。通过结合先进的原则&#xff0c;LangChain正在重新定义通过传统API可以实现的极限。 在上一篇博…

一文读懂!一年耗能堪比2个三峡电站的大数据中心,背后竟隐藏着这些秘密......

全国大数据中心1年的能耗规模相当于2个三峡电站一整年的发电量&#xff0c;这是为什么&#xff1f; 大数据中心每耗费1度电&#xff0c;只有一半用在了“计算”上面&#xff0c;其他的都应用在散热、照明等方面到底是怎么回事&#xff1f; 为什么说在算力上每投入1元&#xff0…

【二】数据库系统

数据库系统的分层抽象DBMS 数据的三个层次从 数据 到 数据的结构----模式数据库系统的三级模式&#xff08;三级视图&#xff09;数据库系统的两层映像数据库系统的两个独立性数据库系统的标准结构 数据模型从 模式 到 模式的结构----数据模型三大经典数据模型 数据库的演变与发…

【系统软件03】centos7安装和使用node-v18.16.0(centos7升级glibc 2.28)

【系统软件03】centos7安装和使用node-v18.16.0&#xff08;centos7升级glibc 2.28&#xff09; 前言&#xff1a;本文是解决node 18.16.0的依赖问题&#xff0c;具体的node安装流程&#xff0c;可以参考我的另外一篇文章。一、下载node v18.16.0二、下载glibc2.28&#xff08;…

uniapp使用阿里矢量库

然后解压复制全部到你的项目文件 最后只要这几个 然后引入 最后在你需要的页面使用

JavaWeb中Json传参的条件

JavaWeb中我们常用json进行参数传递 对应的注释为RequestBody 但是json传参是有条件的 最主要是你指定的实体类和对应的json参数能否匹配 1.属性和对应的json参数名称对应 2.对应实体类实现了Serializable接口&#xff0c;可以进行序列化和反序列化&#xff0c;这个才是实体类转…

Ajax同源策略及跨域问题

Ajax同源策略及跨域问题 同源策略ajax跨域问题什么是跨域&#xff1f;为什么不允许跨域&#xff1f;跨域解决方案1、CORS2、express自带的中间件cors3、JSONP原生JSONPjQuery发送JSONP 4、使用vscode的Live Server插件 同源策略 同源策略&#xff08;Same-Origin Policy&#…