uniapp和vue组件之间的传值方法(父子传值,兄弟传值,跨级传值,vuex)

Posted 铁锤妹妹@

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了uniapp和vue组件之间的传值方法(父子传值,兄弟传值,跨级传值,vuex)相关的知识,希望对你有一定的参考价值。

前言

在做vue项目或者uniapp开发微信小程序时,经常会用到组件之间传值,因此想总结记录下。

一、父子传值

  1. 父向子传递:props
  2. 子向父传递:通过 events($emit
  3. 父组件想调用子组件的方法:通过 this.$refs(ref)

a)ref 用在组件可以调用组件的属性方法
b)ref 用在标签可以对标签进行操作
c) ref属性不能用在uniapp的内置组件上面,只能用在自定义组件上面;用在内置组件比如<view>标签,this.$refs.xxx获取dom是undefind

父组件调用子组件的方法

// 父组件
<template>
  <view>
    <view class="index-goods-list-con">
      <WaterfallList
        ref="waterFallCon"
        :status="waterfall.status"
        :list="waterfall.list"
        :reset="waterfall.reset"
        @clickCard="onClickCard"
        @handleGood="handleGood"
        @done="onDone"
      ></WaterfallList>
    </view>
  </view>
</template>

<script>
import WaterfallList from '@/components/waterfall/waterfall-list.vue'
export default 
  data() 
    return 
  ,
  methods: 
    handleDailyBestGood(e, good) 
      // 用$refs赋值调用子组件的handleDailyBestNum方法
      this.$refs.waterFallCon.handleDailyBestNum(good) 
    ,
  ,

</script>

<style></style>
// 子组件
<template></template>
<script>
export default 
  data() 
    return 
        renderBasic: ''    
    
  ,
  methods: 
     //父组件调用的方法
     handleDailyBestNum(good)   
       //good 是父组件弹窗传递过来的值,我们可以打印看看
          console.log(good)
          this.renderBasic = good
    ,
  ,

</script>

二、兄弟传值

借助中间代理, $emit$on
比如在uniapp项目中使用兄弟传值,vue同理 uniapp页面通讯官方文档

a) 说明

b) 使用场景

在商品下单页点击选择优惠券,进入优惠券页面,选择一张适合的,再返回下单页,需要带着优惠券id返回,现在商品 提交订单页和优惠券页面是 跨页面 的。

c) 使用方法

//优惠券页面
 clickCoupon (item) 
      if (this.orderSource) 
      // 触发全局自定义事件,传参id
        uni.$emit('updateData', item.id)  
		uni.navigateBack(
		   delta: 1
		)
      
    ,
 // 从优惠券跳回下单页 
 // 监听全局自定义事件updateData,接收参数id
    uni.$on('updateData', async function (couponId) 
      that.couponId = couponId
    )

d) 注意事项

  • uni.$emituni.$onuni.$onceuni.$off 触发的事件都是 App 全局级别的,跨任意组件,页面,nvue,vue
  • 使用时,注意及时销毁事件监听,比如,页面 onLoad 里边 uni.$on 注册监听,onUnload 里边uni.$off 移除,或者一次性的事件,直接使用 uni.$once 监听。
  • 注意 uni.$on 定义完成后才能接收到 uni.$emit 传递的数据

三、祖孙或者更深嵌套的组件间传值: provide/inject

a) 类型

provide:Object | () => Object
inject:Array<string> |  [key: string]: string | Symbol | Object 

b) 详细

这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。

provide 选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的 property。

inject 选项应该是: 一个字符串数组,或一个对象

提示:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。

c) 使用场景

如果要将祖先组件直接传递给孙子组件,我们要将props逐级传递下去:祖先组件 =》子组件 =》孙子组件,而通过provide/inject,可直接从祖先组件传给孙子组件,即使再嵌套多层也没关系。

d) 使用方法

<template>
  <div>
    <button @click="changeMsg">祖组件触发</button>
    <h1>祖组件</h1>
    <parent></parent>
  </div>
</template>

<script>
import parent from './parent.vue';
export default 
  data()
    return
      obj:
        name:'javascript',
      ,
      developer:'布兰登·艾奇',
      year:1995,
      update:'2021年06月',
    
  ,
  provide()
    return 
      obj: this.obj, // 方式1.传入一个可监听的对象
      developerFn:() => this.developer, // 方式2.通过 computed 来计算注入的值
      // developerFn: this.getDeveloper,  方式3.或者调用一个方法,也能实现响应式 
      year: this.year, // 方式4.直接传值
      app: this, // 方式5. 提供祖先组件的实例 缺点:实例上挂载很多没有必要的东西 比如:props,methods。
    
  ,
  components: 
    parent,
  ,
  methods:
    getShowCartValue() 
       return this.developer
    ,
    changeMsg()
      this.obj.name = 'Vue';
      this.developer = '尤雨溪';
      this.year = 2014;
      this.update = '2021年6月7日';
    ,
  ,

</script>

子组件

<template>
  <div class="wrap">
    <h4>子组件(只做中转)</h4>
    <child></child>
  </div>
</template>

<script>
import child from './child.vue';
export default 
  components:
    child,
  ,

</script>

孙组件

<template>
  <div>
    <h5>孙组件</h5>
    <span>名称:obj.name</span> |
    <span>作者:developer</span> |
    <span>诞生于:year</span> |
    <span>最后更新于:this.app.update</span>
  </div>
</template>
 
<script>
export default 
  computed:
    developer()
      return this.developerFn()
    
  ,
  inject:['obj','developerFn','year','app'],

</script>

未点击按钮,原有状态

当点击按钮触发 changeMsg 方法后,效果如下:

对比一下前后差异:无论点击多少次,孙组件中的诞生于 year 字段永远都是1995 并不会发生变化,通过 方式1、方式2、方式3、方式5传值是可以响应的

正是官网所提到的:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。

注意:
1)另外如果孙子组件更改祖先组件传来的值,会发现祖先组件的值也会跟着变,所以慎用 provide / inject;
2)Vuex 和 provide/inject 最大的区别:Vuex 中的全局状态的每次修改是可以追踪回溯的,而 provide/inject 中变量的修改是无法控制的。换句话说,不知道是哪个组件修改了这个全局状态。

所以对于业务庞大而复杂的,还是建议使用vuex~

四、更复杂的结构:vuex

请移步看我之前写的关于vuex使用总结文章,学习笔记之Vuex总结(Vue状态管理)

参考:
provide、inject例子讲解参考这个

以上是关于uniapp和vue组件之间的传值方法(父子传值,兄弟传值,跨级传值,vuex)的主要内容,如果未能解决你的问题,请参考以下文章

VUE父子组件之间的传值,以及兄弟组件之间的传值

Vue组件之间的传值方法

angular父子组件之间的传值

Vue父子组件之间的传值

Vue父子组件之间的传值

Vue父子组件之间的传值