vue组件传值之$attrs

1.概述:$attrs用于实现当前组件的父组件,向当前组件的子组件通信(祖-》孙)

2.具体说明:$attrs是一个对象,包含所有父组件传入的标签属性。

注意:$attrs会自动排除props中声明的属性(可以认为声明过的props被子组件自己消费了)

首先,创建父-子-孙之间的组件关系

我们首先来看父子之间的传值:

我们都知道,父传子传值的口诀是:父在子的属性上书写属性名=属性值,子组件使用defineProps接收。

那么我们的父组件的代码如下:【组件关系:爷爷:index.vue,子:brother.vue,孙:grandSon.vue】

index.vue

html 复制代码
<template>  
    <div>  
      <el-card ref="myButton"  @click="handlerClick">Click Me
        <el-card @click="clickSpan">点我</el-card>
        <Children ref="childRef" :fatherToSon="handlerClick"></Children>
        <!-- @myHandler="handlerClick" -->
         <Brother v-model:aaa="name" age="20" :happy="happy" :happyPlus="happyPLus" test="测试数据" v-bind="{x:100,y:200}" />
         <!-- <el-tag type="danger" size="normal"  effect="dark" closable @close="">{{ name }}</el-tag -->
         <el-badge :value="name" :max="99" :is-dot="false" :hidden="false" type="primary">
          
          <el-button size="small">cet</el-button>
         </el-badge>
         <br />
         
         
         爷爷的:{{ happy }}
      </el-card>  
    </div>  
  </template>  
    
  <script lang="ts" setup>  
  import { ref, onMounted, nextTick } from 'vue';  
  import { ElButton } from 'element-plus'; // 确保你已经正确引入了 Element Plus  
  import Children from './child.vue'  
  import Brother from './brother.vue'
  const childRef = ref(null);  
  const name = ref('tomCat')
let happy=ref('哈哈')
const happyPLus=()=>{
    happy.value+='!'
}
      const myButton = ref(null);  
      
      const handlerClick=(value:any)=>{
        console.log("父组件被点击了,子组件传递过来的值为",value);
        console.log(childRef.value);
        console.log(childRef.value?.SonFun());
        console.log(childRef.value?.sonValue);
        
        
        
        
      }
      const clickSpan=()=>{
        console.log("span被点击了");
      }
      // onMounted(() => {  
      //   // 访问 el-button 组件实例  
      //   console.log(myButton.value);  
      //   console.log(24,myButton.value.handleClick);
      //   console.log(25,ref);
        
      //   // 打印所有属性和方法(注意:直接操作实例的属性和方法可能不是最佳实践)  
      //   console.log('Properties:', Object.keys(myButton.value.$props));  
      //   console.log('Methods:', Object.keys(myButton.value.$options.methods));  
      // });  
    
      // 返回 ref 以便在模板中使用  
      
    
   
  </script>

可以看到父给子传递的数据,有静态的,也有动态的,也有使用v-bind=对象的这种方式来传递的,其实这种方式就是等价于:

javascript 复制代码
v-bind="{x:100,y:200}"   ==》 :x=100 :y=200

这样我们就可以看到对应的x和y也被传递过来了,然后我们的关注重点是祖孙传值,而不是父子传值,所以这个brother组件就是一个桥梁,其作用就是不使用父组件的值,直接将父组件传递的值使用$attrs直接传递给孙组件。

brother.vue

html 复制代码
<template>
 <div>
  自定义组件实现v-model
    <!-- <input type="text" :value="aaa" @input="inputChange"/>
    <h3>age:{{ age }}</h3>
    <h3>其他:{{ $attrs }}</h3> -->
    <GrandSon v-bind="$attrs"></GrandSon>
 </div>
</template>

<script setup lang="ts">
import {ref,reactive} from 'vue'
import GrandSon from './grandSon.vue';
// const emit =defineEmits(['update:aaa'])

// defineProps(['aaa','age'])

// const inputChange=({target:{value}})=>{
//     emit('update:aaa',value)

// }
</script>

<style scoped>

</style>

这里我们需要注意的时,当父组件传递给孙组件的值被子组件接收后,如果子组件没有传递出去,那么孙组件就无法使用被子组件占用的值。

孙组件grandSon.vue

html 复制代码
<template>
 <div>
  this is grandson page
<h2>test:{{ test }}</h2>
<h2>age:{{ age }}</h2>
<h2>x:{{ x }}</h2>
<h2>y:{{ y }}</h2>
<h2>孙子的happy:{{ happy }}</h2>

<el-button type="primary" size="default" @click="happyPlus">修改爷爷的happy</el-button>

 </div>
</template>

<script setup lang="ts">
import {ref,reactive} from 'vue'
defineProps(['test','age','x','y','happy','happyPlus'])


</script>

<style scoped>

</style>

来到调试工具,我们就可以看到孙组件接受到了来自爷爷传递过来的值。

然后我们可能会有疑问,既然爷爷可以向孙组件传递数据,那么孙可不可以修改爷爷的数据呢,其实,原理和当时的props是一样的,这种方式虽然不能直接修改爷爷的值,但是可以让爷爷再传递一个方法给孙组件,然后孙组件调用这个方法,完成对爷爷的修改。比如传递过来的函数happyPLus

来到界面,我们点击按钮,就可以修改爷爷的数据

有几个比较细致的点,需要注意一下,就是当父组件给子组件传递数据的时候,子组件可以不全部接受父组件传递过来的数据,

可以看到,接受到的数据被放在props中,没接受的数据放到了attrs之中,同样,刚才已经提到过,如果子组件接收了父组件的数据,那么在孙组件就会看不到数据,正是这个原因

相关推荐
每天都要喝奶茶22 分钟前
vue3uniapp实现自定义拱形底部导航栏,解决首次闪烁问题
前端·vue.js·uni-app
Southern Wind23 分钟前
H5页面在线预览pdf
javascript·pdf
May_Xu_23 分钟前
vue3+less使用主题定制(多主题定制)可切换主题
前端·javascript·vue.js·vue·less·css3
qq_4275060823 分钟前
less解决function中return写法在浏览器被识别成Object导致样式失败的问题
前端·css·less
Elastic 中国社区官方博客29 分钟前
将你的 Kibana Dev Console 请求导出到 Python 和 JavaScript 代码
大数据·开发语言·前端·javascript·python·elasticsearch·ecmascript
Python大数据分析38 分钟前
JetPack Compose安卓开发之底部导航Tabbar
android·vue.js·elementui
闲人陈二狗41 分钟前
vue3中的pinia的使用方法
开发语言·javascript·ecmascript
北京_宏哥1 小时前
《最新出炉》系列入门篇-Python+Playwright自动化测试-41-录制视频
前端·python·测试
小华同学ai1 小时前
jsMind:炸裂项目,用JavaScript构建的思维导图库,GitHub上的热门开源项目
javascript·开源·github
小霖家的混江龙1 小时前
Vite 打包 H5 如何注入版本号
前端·vite