前端组件之间传值的多种方式

本文详细介绍了前端组件间的传值方式,包括props、this.$emit、依赖注入(provide, inject)、事件中心eventBus、使用ref绑定实例以及Vuex。通过实例代码展示了各种方法的使用场景和操作步骤,帮助开发者深入理解并掌握组件通信技巧。" 132386997,19687622,Android操作.xlsx文件:打开与读取,"['Android开发', '文件处理', 'Excel', 'Apache POI']

前端传值的方式:

props,this.$emit,依赖注入(provide,inject),Vue2的事件中心evnetBus,Vuex


提示: props data 有修改都会 引起组件的更新!


前言

提示:这里可以添加本文要记录的大概内容:

1.为什么要通过子组件向父组件传值或者父组件向子组件传值?

    官方的说法:早些时候,我们提到了创建一个博文组件的事情。问题是如果你不能向这个组件传递某一篇博文的标题或内容之类的我们想展示的数据的话,它是没有办法使用的。这也正是 prop 的由来。

    我的理解:状态管理,类似于vuex,子组件通过自定义事件向父组件传值,触发父组件dom元素进行更新,父向子传值也是一样

2.怎么使用,props该放在那个位置

porps:父组件通过props属性向子组件传递数据,定义组件的时候可以定义一个props属性,值可以是一个字符串数组或一个对象。

父组件向子组件传值

提示:以下是本篇文章正文内容,下面案例可供参考

一、porps父向子传值?

子组件的代码
<template>
  <div class="son">
    <h2>这是son组件</h2>
    <h3>传下来的值为: {{num}} -- {{ age }}</h3>

  </div>
</template>

<script>
  export default {
    // 通过定义一个属性,来去接收到父组件传下来的值
    // 数组 对象 
    // props: ['num']
    props: {
      num: Number,
      info: Object,
      age: Number
    },
    data(){
      return {
        count: 100   
      }
    },
  }
</script>

<style scoped>
  .son{
    box-sizing: border-box;
    padding: 20px;
    border: 2px solid blue;
  }
</style>
父组件的代码
<template>
  <div class="home">
    <son :num="20" :info="{name:'young',age:18}" :age="age"></son>

  
  </div>
</template>

<script>

import Son from '@/components/Son.vue'

// 父组件:  home
// 子组件:  son
  
export default {
  name: 'HomeView',
  data(){
    return {
      age: 18
    }
  },
  components: {
    Son
  },
}
</script>


<style scoped>
  .home{
    box-sizing: border-box;
    padding: 30px;
    border: 3px solid yellow;
  }
</style>

二、子向父

子组件的代码
<template>
  <div class="son">
    <h2>这是son组件</h2>
    <h3>向父组件传值</h3>
    <button @click="up">向上传</button>
  </div>
</template>

<script>
  export default {
    data(){
      return {
        count: 100   
      }
    },
    methods:{
      up(){
        // 点击的时候就向上传值
        // 给当前组件定义一个事件叫fromson
        this.$emit('fromson',this.count)
      }
    }
  }
</script>

<style scoped>
  .son{
    box-sizing: border-box;
    padding: 20px;
    border: 2px solid blue;
  }
</style>
父组件的代码
<template>
  <div class="home">
  // 在父组件中接收子组件的方法
    <son @fromson="getsonval" ></son>
  </div>
</template>

<script>

import Son from '@/components/Son.vue'

// 父组件:  home
// 子组件:  son
  
export default {
  name: 'HomeView',
  components: {
    Son
  },
  methods:{
  // 获取到子组件传上来的方法
    getsonval(val){
      console.log(val)
    }
  }
}
</script>


<style scoped>
  .home{
    box-sizing: border-box;
    padding: 30px;
    border: 3px solid yellow;
  }
</style>

三、中间人通信

中间人通信的本质就是,子1传给父,父再传给子2

四、依赖注入(provide(提供),inject(注入))

使用场景:网站风格设计:暗夜模式和白天模式

// 要从父组件传个值 给孙子组件  
// home                age
    // son              |
        // grandson    age

// 可以通过props 层层向下传 
  // 如果是这样穿层级多了,就会比较麻烦,中间少了一层就会导致传值不成功

// 这种方式也叫祖先组件 向 后代组件传值   依赖注入
// provide  定义要向后代组件 传的值
// inject   要接收到 祖先组件 传下来的值
爷爷组件的代码
<template>
  <div class="home">
  
  </div>
</template>

<script>
export default {
  name: 'HomeView',
  provide:{
    value: 999     // 使用provide定义的数据,就可以直接在后代组件中取到
  },
}
</script>


<style scoped>
  .home{
    box-sizing: border-box;
    padding: 30px;
    border: 3px solid yellow;
  }
</style>

孙子组件的代码
<template>
  <div class="grandson">
    <h2>这是grandson组件</h2>
    <h3>通过inject取到祖先组件传下来的值: {{value}}</h3>
  </div>
</template>

<script>
  // props data  有修改都会? 引起组件的更新
  export default {
    inject: ['value']   // 从祖先组件中取到定义的值
  }
</script>

<style scoped>

  .grandson{
    border: 1px solid red;
  }
</style>

五、事件中心eventBus

在vue2中,如果是兄弟组件之间传值,可以事件中心(event bus)去传,但是在vue3就不能使用了 (去除了$on方法);其本质就是订阅发布者模式。(感兴趣的可以去去看我的订阅发布者模式篇。链接:订阅发布者模式

六、使用ref绑定实例

  // $root  获取根实例
  // $parent  获取父实例
  // $refs   获取指定的实例
  // this.$refs 可以拿到组件绑定了ref属性的实例
  // ref如果绑定的是组件,拿到的是组件实例
  // res如果绑定是普通元素,那么拿到是dom对象
子组件的代码
子组件(borther1,borther2),父组件(AboutView)
<template>

  <div class="box">
    <div>brother1-{{num}}</div>

    <button @click="getparent">$parent</button>
    <button @click="getroot">$root</button>

  </div>  
</template>

<script>
  export default {
    data(){
      return {
        num:88
      }
    },  
    methods:{
      getparent(){
        // this.$parent  是拿到的是父组件的实例
        // 拿到的这个实例也可以修改里面的值, 但是不建议这么做!! (数据就不好追踪了)
        console.log(this.$parent.count)
        // this.$parent.count = 999
      },
      getroot(){
        // this.$root获取到根实例  App.vue
        console.log(this.$root)
      }
    }
  }
</script>

<style scoped>
  .box{
    border: 1px solid red;
  }
</style>


<template>
  <div>brother2</div>
</template>
父组件的代码
<template>
  <div class="about">
    <h3>count: {{ count }}</h3>
    <!-- ref绑定是的组件 -->
    // 其中ref绑定的ref="bro1",bro1的名字随自己定义,在方法里面调用的时候保持同名就可以
    <brother1 ref="bro1"></brother1>
    <button @click="getbro1">想获取brother1组件的实例</button>

    <!-- ref绑定的是普通元素 -->
    <div class="box2" ref="box2">box</div>
    <button @click="getdom">想获取某元素</button>
  </div>
</template>

<script>
  import Brother1 from '@/components/Brother1.vue';
  import Brother2 from '@/components/Brother2.vue';
  // 在vue2中,如果是兄弟组件之间传值,可以事件中心(event bus)去传
  // 但是在vue3就不能使用了 (去除了$on方法)

  // $root  获取根实例
  // $parent  获取父实例
  // $refs   获取指定的实例
  export default {
    data(){
      return {
        count: 888
      }
    },
    methods:{
      getbro1(){
        // console.log(Brother1)
        // console.log(this.$root)

        // this.$refs 可以拿到组件绑定了ref属性的实例
        // ref如果绑定的是组件,拿到的是组件实例
        // res如果绑定是普通元素,那么拿到是dom对象
        // 其中ref绑定的ref="bro1",bro1的名字随自己定义,在方法里面调用的时候保持同名就可以
        // 在这里保持同名即可
        console.log(this.$refs.bro1)
        this.$refs.bro1.num +=1
        ![控制台打印](https://img-blog.csdnimg.cn/320b874c6b624a25916da70f792b0cec.png#pic_center)

      },
      getdom(){
        // console.log(this.$refs.box2)
        ![控制台打印](https://img-blog.csdnimg.cn/a92e6f32dc4b4597b42a6cf7c8be746c.png#pic_center)

        this.$refs.box2.style.color = 'blue'
        this.$refs.box2.style.fontSize = '30px'
      }
    },
    components: {
      Brother1,
      Brother2
    }
  }
</script>

<style scoped>
  .box2{
    width: 100px;
    height: 100px;
    border: 5px solid red;
  }
</style>

七、Vuex(Vuex请移步到Vuex篇)

总结

提示:前端传值的方式: props,this.$emit,依赖注入(provide,inject),Vue2的事件中心evnetBus,Vuex

例如:以上就是今天要讲的内容。

<think>好的,用户想了解组件的方法及实现方式。我需要结合提供的引用内容来组织回答。首先,查看用户提供的三个引用,分别来自React和Vue的相关文章。 引用[1]提到React中拆分组件,提高代码可维护性。引用[2]详细列出了Vue的父子、非父子、兄弟组件方法,包括provide/inject和bus总线,还有Vuex和pinia。引用[3]则给出了Vue3中子组件通过事件更新父组件的例子。 用户的问题不限定框架,可能需要涵盖主流框架如React和Vue。需要分点说明不同方式,并给出示例代码。注意用户提到的系统级指令,特别是行内数学公式要用$...$,但这个问题可能不涉及数学公式,所以可能不需要处理这部分。但需要确保回答结构清晰,使用中文,生成相关问题,并在引用处添加标识。 接下来需要组织回答结构,可能分为父子组件、非父子组件、全局状态管理等部分。每个部分下分别说明React和Vue的实现方式,并引用对应的参考资料。例如,在父子组件中,React使用props和回调函数,Vue使用props和自定义事件,如引用[3]中的例子。非父子组件可以提到Vue的provide/inject和事件总线,React的Context API。全局管理工具如Redux、Vuex、Pinia。 需要确保每个方法的实现方式有代码示例,并且正确标注引用来源。例如,当提到Vue3中使用$emit时,引用[3]的例子。提到provide/inject时,引用[2]。生成的相关问题要围绕组件展开,可能涉及不同框架的比较、性能优化、最佳实践等。 检查是否有遗漏的方法,比如兄弟组件Vue中的事件总线,React可能需要使用状态提升或Context。同时注意用户可能对代码示例的格式要求,使用正确的语法,比如Vue中的@input事件和React中的props递。 最后,生成的相关问题需要与组件相关,涵盖不同场景和框架,帮助用户进一步探索。例如,如何选择方式,跨框架方法比较,中的常见问题等。</think>### 组件的方法及实现方式 组件前端框架开发中的核心需求,不同框架提供了多种实现方式。以下是常见方法及具体实现: --- #### 一、父子组件 1. **React** - **父子**:通过`props`递数据 ```jsx // 父组件 <ChildComponent data={value} /> // 子组件 const ChildComponent = ({ data }) => <div>{data}</div>; ``` - **子父**:通过回调函数 ```jsx // 父组件 const handleChildData = (data) => {/* 处理数据 */}; <ChildComponent onDataChange={handleChildData} /> // 子组件 <button onClick={() => onDataChange("子组件数据")}>递</button> ``` 2. **Vue** - **父子**:使用`props` ```vue <!-- 父组件 --> <ChildComponent :value="parentValue" /> <!-- 子组件声明 --> props: ['value'] ``` - **子父**:通过自定义事件`$emit` ```vue <!-- 子组件 --> <input @input="$emit('update:value', $event.target.value)" /> <!-- 父组件监听 --> <ChildComponent @update:value="parentValue = $event" /> ``` 此为Vue 3的典型双向绑定实现[^3]。 --- #### 二、非父子组件 1. **事件总线(Event Bus)** - **Vue实现**:通过全局事件触发器 ```javascript // 创建事件总线(bus.js) import { createApp } from 'vue'; const bus = createApp({}); export default bus; // 组件A发送事件 bus.emit('custom-event', data); // 组件B接收事件 bus.on('custom-event', (data) => { /* 处理 */ }); ``` 适用于兄弟组件或跨层级通信[^2]。 2. **依赖注入(Provide/Inject)** - **Vue深层**: ```javascript // 祖先组件 provide('key', sharedData); // 后代组件 const data = inject('key'); ``` 适合跨多层级组件递数据[^2]。 3. **React Context API** ```jsx // 创建Context const DataContext = React.createContext(); // 父组件提供 <DataContext.Provider value={data}> <ChildComponent /> </DataContext.Provider> // 子组件消费 const data = useContext(DataContext); ``` --- #### 三、全局状态管理 1. **Vuex(Vue专用)** - 集中式存储状态,通过`commit`和`dispatch`修改状态。 ```javascript // 组件中获取状态 this.$store.state.value; // 修改状态 this.$store.commit('mutation', newValue); ``` 2. **Pinia(Vue 3推荐)** - 更轻量且支持TypeScript的状态管理工具。 3. **Redux(React专用)** - 通过`useSelector`和`useDispatch`实现全局状态管理。 --- #### 四、其他场景 - **URL参数**:通过路由参数递(如React Router、Vue Router)。 - **本地存储**:使用`localStorage`或`sessionStorage`暂存数据。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

抬头第一眼,是天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值