VUE组件间传值

一.组件间传值

1.eventbus

// bus.js
import Vue from 'vue'
export default new Vue({})

// component-a.js
import bus from './bus.js'
export default {
  created () {
    bus.$on('event-name', (preload) => {
      // ...
    })
  }
}

// component-b.js
import bus from './bus.js'
export default {
  created () {
    bus.$emit('event-name', preload)
  }
}

  • 优点
    • 解决了多层组件之间繁琐的事件传播。
    • 使用原理十分简单,代码量少。
  • 缺点
    • 由于是都使用一个Vue实例,所以容易出现重复触发的情景,例如:
      1. 多人开发时,A、B两个人定义了同一个事件名。
      2. 两个页面都定义了同一个事件名,并且没有用$off销毁(常出现在路由切换时)。
      3. 在for出来的组件里注册。

2.props和$emit/$on

  • 优点

    • 使用最为简单,也是父子组件传递最常见的方法。
    • Vue为给props提供了类型检查支持。
    • $emit不会修改到别的组件的同名事件,因为他只能触发父级的事件,这里和event-bus不同
  • 缺点

    • 单一组件层级一深需要逐层传递,会有很多不必要的代码量。
    • 不能解决了多组件依赖统同一状态的问题。
<template>
  <div>
    父组件:
    <input type="text" v-model="name">
    <br>
    <br>
    <!-- 引入子组件 -->
    <child :inputName="name"></child>
  </div>
</template>
<script>
  import child from './child'
  export default {
    components: {
      child
    },
    data () {
      return {
        name: ''
      }
    }
  }
</script>

<template>
  <div>
    子组件:
    <span>{{inputName}}</span>
  </div>
</template>
<script>
  export default {
    // 接受父组件的值
    props: {
      inputName: String,
      required: true
    }
  }
</script>

3.slot传值

  • 优点
    • 可以在父组件里自定义插入到子组件里的内容,虽然其他属性也可以,但是我觉得slot更倾向于自定义的条件是来自于父容器中。
    • 复用性好,适合做组件开发。
  • 缺点
    • 和props一样不支持跨层级传递。
<swiper class="swiper" :options="swiperOption" id="cateCard">
  <swiper-slide v-for="(category, index) in categories" :key="index">
    <slot name="items" :category="category.newsList"></slot>
  </swiper-slide>
  <div class="swiper-pagination" slot="pagination"></div>
</swiper>


<m-list-card icon="caidan" title="新闻资讯" :categories="newsCates">
  <template #items="{ category }">
    <div
      class="swiper-centent mt-3 d-flex"
      v-for="(item, index) in category"
      :key="index"
    >
      <sapn>[{{ item.categories }}]</sapn>
      <sapn class="mx-2">|</sapn>
      <sapn class="flex-grow-1">{{ item.title }}</sapn>
      <sapn>{{ item.date }}</sapn>
    </div>
  </template>
</m-list-card>

4.ref

也是父子间传值

// Child.vue
<script setup>
    // 方法一 不适用于Vue3.2版本,该版本 useContext()已废弃
    import { useContext } from "vue"
    const ctx = useContext()
    // 对外暴露属性方法等都可以
    ctx.expose({
        childName: "这是子组件的属性",
        someMethod(){
            console.log("这是子组件的方法")
        }
    })
    
    // 方法二 适用于Vue3.2版本, 不需要引入
    // import { defineExpose } from "vue"
    defineExpose({
        childName: "这是子组件的属性",
        someMethod(){
            console.log("这是子组件的方法")
        }
    })
</script>

// Parent.vue  注意 ref="comp"
<template>
    <child ref="comp"></child>
    <button @click="handlerClick">按钮</button>
</template>
<script setup>
    import child from "./child.vue"
    import { ref } from "vue"
    const comp = ref(null)
    const handlerClick = () => {
        console.log(comp.value.childName) // 获取子组件对外暴露的属性
        comp.value.someMethod() // 调用子组件对外暴露的方法
    }
</script>

5.vueX

  • 优点
    • 解决了多层组件之间繁琐的事件传播。
    • 解决了多组件依赖统同一状态的问题。
    • 单向数据流
    • 为Vue量身定做,学习成本不高
  • 缺点
    • 不能做数据持久化,刷新页面就要重制,要做数据持久化可以考虑使用localstorage。
    • 增加额外的代码体积,简单的业务场景不建议使用。


 

// store/index.js
import { createStore } from "vuex"
export default createStore({
    state:{ count: 1 },
    getters:{
        getCount: state => state.count
    },
    mutations:{
        add(state){
            state.count++
        }
    }
})

// main.js
import { createApp } from "vue"
import App from "./App.vue"
import store from "./store"
createApp(App).use(store).mount("#app")

// Page.vue
// 方法一 直接使用
<template>
    <div>{{ $store.state.count }}</div>
    <button @click="$store.commit('add')">按钮</button>
</template>

// 方法二 获取
<script setup>
    import { useStore, computed } from "vuex"
    const store = useStore()
    console.log(store.state.count) // 1

    const count = computed(()=>store.state.count) // 响应式,会随着vuex数据改变而改变
    console.log(count) // 1 
</script>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值