vue 组件之间的传参及方法传递

1,323 阅读3分钟
  • 父组件可以改变子组件的值,而子组件不能直接改变父组件的值!!

1.父组件->子组件 (用props)

父组件 html部分
    <div class="component-study">
        <h1 style="margin-bottom: 30px">component-study</h1>
        <test-one :one="oneValue"></test-one><!--这里往one组件传了one参数-->
        <test-two :two="twoValue"></test-two><!--这里往two组件传了two参数-->
    </div>
父组件 js部分
    import testOne from "../template/test-1.vue"//引入子组件one
    import testTwo from "../template/test-2.vue"//引入子组件two
    export default {
        name: 'component-study',
        data(){
            return {
                oneValue:'one',//传到组件one的值
                twoValue:'two'//传到组件two的值
            }
        },
        components:{
            "test-one":testOne,
            "test-two":testTwo
        }
    }
子组件 html部分
<template>
    <div class="test-1">
        <div class="title">组件1获取父组件的值:</div>
        <div>{{one}}</div>
    </div>
</template>
子组件 js部分
export default {
        name: '',
        props:['one'],//子组件用props接收到了父组件one参数
        data(){
            return {

            }
        },
        created(){
            console.log(this.one);//one  这就是父组件传的值
        }
    }

2.子组件->父组件 (用emit)

个人认为:子组件先声明一个方法,然后传值到父组件,父组件然后利用这个方法来获取这个值
子组件 js部分
export default {
        name: '',
        props:['one'],
        data(){
            return {
                sendData:'one',
            }
        },
        created(){
            this.$emit('getOneDataName',this.sendData);//利用$emit来传值,getOneDataName是方法名,this.sendData是传的值
        }
    }
父组件 html部分
    <template>
    <div class="component-study">
        <h1 style="margin-bottom: 30px">component-study</h1>
        <test-one @getOneDataName="getOneData" :one="oneValue"></test-one>
        <!--@getOneDataName是子组件声明的方法,记住getOneData没有括号,根据这个方法来获取值-->
    </div>
</template>
父组件 js部分
    export default {
        name: 'component-study',
        data(){
            return {
                oneValue:'one',
                twoValue:'two'
            }
        },
        components:{
            "test-one":testOne,
            "test-two":testTwo
        },
        methods:{
            getOneData(data){//这是子组件声明的方法,这个data就是子组件传过来的值
                console.log(25,data);//one
            }
        },
        created(){
            //this.getOneData;
        }
    }

3.组件(无需关心层级)利用eventBus

  • 除了传参,还可以响应方法。
3-1 先在src目录下新建一个 eventBus.js (其实就是一个vue对象)
import Vue from 'vue'

let eventBus = new Vue()

export default eventBus

/*export default{
  eventBus:new Vue()
}*/

组件A js部分
    import eventBus from '../assets/js/eventBus'//引入刚刚写的组件
    //利用eventBus $emit注册 一个方法
    eventBus.$emit('testFn','666');//第一个参数是方法名,第二个参数是值
组件B js部分
    import eventBus from '../assets/js/eventBus'//引入刚刚写的组件
    //利用eventBus $on获取刚刚注册的方法
    eventBus.$on('testFn',(data)=>{
        console.log(data)//data的值是666
    });

注意点:如果$on多次触发

  • beforeDestroy内销毁下
beforeDestroy () {
      eventBus.$off('testFn')
    },

子组件->父组件 (v-slot)

v-slot 标题3

父组件触发子组件的方法

方法1

  • 父组件

html

<button @click = "fatherFn">点击触发子组件方法</button>  
<testComponents ref="testComponent">
</testComponents>

js

methods:{
    fatherFn(){
        this.$refs.testComponent.$emit('fnTest') //向子组件传递了fnTest方法
      },
}

  • 子组件

js

mounted(){
    this.$on('fnTest', () => {
        console.log('我触发了父组件的事件')
      })
}

方法2,这个更简单

  • 父组件

html

<button @click = "fatherFn">点击触发子组件方法</button>  
<testComponents ref="testComponent">
</testComponents>

js

methods:{
    fatherFn(){
        this.$refs.testComponent.childFn() //直接触发子组件方法
      },
}

  • 子组件

js

methods: {
    childFn() {
        console.log('我是子组件方法')
    }
}

3、爷爷孙子组件传值$attr

参考

vue3 中的传递

A-非单文件组件传递

1、父传子

  • 跟vue2相比差不多,利用props传参
  • 父html
<template>
  <div class="father-com">
    father
    <childCom :fatherValue="fatherValue"></childCom>
  </div>
</template>
  • 父js
<script>
import childCom from './childCom'
export default {
  components: {childCom},
  setup(){
    const fatherValue = '我是父组件的值'
    return {
      fatherValue,
    }
  }
}
</script>

  • 子组件接收js
<script>
export default {
  props: ['fatherValue'],
  setup(props, { emit }){
    console.log(10, props.fatherValue) //获取到父元素的值
  }
}
</script>

2、子元素事件触发父元素emit, 跟vue2差不多

  • 子html
<template>
  <div class="child-com">
    child
    <button @click="childClick">click</button>
  </div>
</template>
  • 子js
<script>
export default {
  props: ['fatherValue'],
  setup(props, { emit }){
    console.log(10, props.fatherValue)

    const childClick = ()=>{
      //向外部抛出
      emit('childClick', '我是子组件的值')
    }

    return {
      childClick
    }
  }
}
</script>

  • 父html
<childCom :fatherValue="fatherValue"
  @childClick="childClick"
></childCom>
  • 父js
setup(){
  const fatherValue = '我是父组件的值'

  // eslint-disable-next-line no-unused-vars
  const childClick = (childValue)=>{ //响应子组件事件
    console.log(18, childValue)
  }

  return {
    fatherValue,
    childClick
  }
}

3、父组件触发子组件事件

  • 获取子元素实例, 直接触发方法
  • 父组件代码
//html
<childCom :fatherValue="fatherValue"
  @childClick="childClick"
          ref="childRef"
></childCom>
//js
const childRef = ref(null)
childRef.value.childFn()

B-单文件组件传递

1、父传子

  • 子组件
<script setup>
import {defineProps} from 'vue'

const props = defineProps(['fatherValue'])
console.log(11, props.fatherValue)

const childClick = ()=>{

}
</script>

2、父触发子组件事件

  • 子元素一定要暴露方法出去,不然访问不到。。
  • 父组件
const childRef = ref(null)

const fatherClick = ()=> {
  console.log(20, childRef)
  childRef.value.childFn()
}
  • 子组件
import {defineProps, defineExpose} from 'vue'
const childFn = ()=>{
  console.log('我是子组件的方法')
}
//暴露出去。。。
defineExpose({
  childFn
})

3、子组件事件触发父组件事件-defineEmits

  • 子组件
<div class="child-com">
  child
  <button @click="childClick">click</button>
</div>


import {defineEmits} from 'vue' // 目前不需要这句了,默认就有
const emit = defineEmits(['refreshFn']) 
const childClick = ()=>{
  console.log('子组件点击')
  emit('refreshFn', true)
}
  • 父组件
<childCom :fatherValue="fatherValue"
          ref="childRef"
          @refreshFn="refreshFn"
></childCom>
<div ref="testDom">test-dom</div>

const refreshFn = (val)=>{
  console.log(27, '父组件内响应事件', val)
}