隔代通信-继承组件全部属性

v-bind="$attrs"

作用:主要用于组件之间的隔代传值,是将调用组件时的组件标签上绑定的非props的属性(class、style除外)向下传递。

使用了v-bind="$attrs"的组件,可以使用从上级组件中获取的值,并且它的下级组件直接下级组件即便没有用v-bind="$attrs"绑定,也可以获取到值。

在子组件中应该添加inheritAttrs:false,避免父作用域的不被认作为props的特性绑定应用到子组件的根元素上,导致在子组件中无法使用vm.$attrs对象获取到非props特性值

**eg:**有父组件A,子组件B,孙组件C,在A组件中传值给C,在C组件中用prop接收

// 层级关系
<App>
	<TheOuter> 
		<TheMiddle> 
			<TheInner>
			</TheInner>
		</TheMiddle>
	</TheOuter>
</App>

|---App.vue
<template>
	<div id="app">
        	<TheOuter id="1" name="zxx" age="23" />
        </div>
</template>

|---App.vue---TheOuter.vue
<template>
  <div>
    <TheMiddle v-bind="$attrs" gender="man"></TheMiddle>
  </div>
</template>
// ----------------------------------
mounted(){
  // console.log(this.$attrs['id']); // 1
  // console.log(this.$attrs['name']); // jack
  // console.log(this.$attrs['age']); // 21
}

|---App.vue---TheOuter.vue---TheMiddle.vue
<template>
  <div>
    <TheInner v-bind="$attrs"></TheInner>
  </div>
</template>
// ----------------------------------
mounted(){
  // prop中变量的使用
  // console.log(this.$attrs['id']); // 1
  // console.log(this.$attrs['name']); // jack
  // console.log(this.$attrs['age']); // 21
  // console.log(this.$attrs['gender']); // man
}

|---App.veu---TheOuter.vue---TheMiddle.vue---TheInner.vue
<template>
  <div>
    <div>hello啊</div>
  </div>
</template>
// ----------------------------------
mounted(){
  // prop中变量的使用
  // console.log(this.$attrs['id']); // 1
  // console.log(this.$attrs['name']); // jack
  // console.log(this.$attrs['age']); // 21
  // console.log(this.$attrs['gender']); // man
}

vue2中的v-bind="$attrs"与vue3中的v-bind="$attrs"区别
  • vue2中$listeners是单独存在的,vue3中$listeners不存在了

  • vue2$attrs不包含class和style属性,vue3中$attrs包含class和style属性

vue2中的v-bind="$attrs"

在vue2中,attrs里面包含了上层组件传递的所有数据(除class和style),当一个组件声明了prop时,attrs里面包含了除去 prop里面的数据剩下的数据,可以结合inheritAttrs: false,可以将传递下来的数据应用于其他元素

vue3中的v-bind="$attrs"
  • vue3中$attrs包含class和style属性

  • <script setup>和普通的<script>可以一起使用

  • 无法在<script setup>中的声明选项中去使用inheritAttrs或者插件的自定义选项

    <script lang="ts">
        export default{
    	inheritAttrs: false,
            customOptions:{}
    }
    </script>
    
    <script lang="ts" setup>
        
    </script>
    

    默认是渲染到子组件的根标签上,通过inheritAttrs:false属性让属性不渲染到根标签上,在子组件的任意标签上添加v-bind=$attrs可以让传递过来的属性渲染到任意标签上。使用defineProps接收后会相应减少对应属性。

inheritAttrs

vue官网对于inheritAttrs的属性解释:默认情况下父作用域的不被认作为props的attribute绑定 (attribute bindings) 将会“回退”且认作为普通的HTML attribute应用到子组件的根标签上。

v-bind="$props"

作用:主要用于组件之间隔代传值。

可以将父组件的所有props下发给它的子组件,子组件需要在其props中定义接收的props。

v-on="$listeners"

$listeners包含了父作用域中的(不含.native修饰符的)v-on事件监听器。他可以通过v-on="$listeners"传入内部组件–在创建更高层次的组件时非常有用。

vue2中$listeners是单独存在的,vue3中$listeners被合并到了$attrs中。

理解:

  • 因为$listeners可以接收父组件中(不含.native修饰符的)v-on事件监听器,在进行事件传递的时候非常有用。
  • 对组件进行二次封装时不可能将组件的所有内置组件都抛出来,可以用$listeners进行事件传递。
vue2中的$listeners
第一种

作用:主要用于底层组件向高层组件传递信息

**eg:**有父组件A,子组件B,孙组件C,从C组件传递消息给A组件

// 层级关系
<App>
	<A> 
		<B> 
			<C>
			</C>
		</B>
	</A>
</App>

|---App.vue---A.vue---B.vue---C.vue
<template>
  <div @click="hanleClick">C组件</div>
</template>

<script>
const hanleClick = () => {
  this.$emit("Msg",'123')
}
</script>

|---App.vue---A.vue---B.vue
<template>
    <C v-on="$listeners" />
</template>

|---App.vue---A.vue
<template>
    <B @Msg="msg" />
</template>

<script>
    // 接口
    interface Msg<T>{
        (a:T):any
    }
    // 类型别名
    type Msg<T> = (a:T) => any;

    const msg:Msg = (val:T) => {
        console.log(val)
    }
  • 可以理解成穿透,多层组件监听。
  • 用于多层级组件之间的通信。
  • 高层级向低层级传值v-bind="$attrs"
  • 低层级向高层级传值v-on="$listeners"
第二种(仅限于vue2)

作用:父组件调用子组件方法,给挂载子组件加方法,然后在子组件需要加的方法加v-on="$listeners",就可以访问到子组件添加的对应方法

// 父组件
<template>
      <Search @change="handleChangeClicks"></Search>
</template>
<script>
    methods: {
        handleChangeClicks(val) {
            if (val.length) return;
            this.getPurchaseOrderList();
        },
      }
</script>

// 子组件
<template>
    <b-form-input
      v-model="value"
      v-on="$listeners"
      type="search"
      :placeholder="placeholder"
    ></b-form-input>
</template>

vue3中的$listenersv-bind="$attrs"会接收属性和事件
//子组件
<template>
    <el-button text @click="dialogTableVisible = true"> 打开 </el-button>
    <el-dialog width="600px" v-bind="$attrs" v-model="dialogTableVisible" title="我是标题">
       <div>我值弹窗中的内容</div>
    </el-dialog>
</template>
<script lang="ts">
export default {
    inheritAttrs: false,
}
</script>
<script lang="ts" setup>
import {  ref } from 'vue'
const dialogTableVisible = ref(false)
</script>

ps:我们没有向上抛出任何事件。
但是父组件可以调用 Element Plus 中对话框中的内置方法。
但是父页面中可以 注册 Element Plus 中对话框中的内置方法。
// 父组件
<template>
    <div class="father">
        <TestCom @close="closeHandler" :before-close="beforeclose" title="父组件给的标题" aa="我是aa" bb="我是bb"></TestCom>
    </div>
</template>
<script setup lang="ts">
import { ElMessageBox } from 'element-plus'
import TestCom from "../../components/TestCom.vue"
// Dialog 关闭的回调
const closeHandler = () => { 
    console.log('Dialog 关闭的回调')
}
/* 
before - close 只会在用户点击关闭按钮或者对话框的遮罩区域时被调用。
如果你在 footer 具名插槽里添加了用于关闭 Dialog 的按钮,那么可以在按钮的点击回调函数里加入 before - close 的相关逻辑。
关闭前的回调,会暂停 Dialog 的关闭. 回调函数内执行 done 参数方法的时候才是真正关闭对话框的时候.
*/
const beforeclose = (done: () => void) => {
    ElMessageBox.confirm('Are you sure to close this dialog?')
        .then(() => {
            console.log('用户点击了确定')
            done()
        })
        .catch(() => {
            console.log('用户点击了取消')
        })
}
</script>
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值