超详细的vue组件之间通讯的8种方式

1. 父组件向子组件传值(props)

<!-- 父组件 -->
<template>
  <div class="section">
    <child :msg="list"></child>
  </div>
</template>

<script>
  import child from './child.vue'
  export default {
    name: 'HelloWorld',
    components: { comArticle },
    data() {
      return {
        msg: '酥脆角'
      }
    }
  }
</script>
<!-- 子组件 child.vue -->
<template>
  <div>
    {{ msg }}
  </div>
</template>

<script>
export default {
  props: {
      msg: String
  }
}
</script>

注意:

prop 只可以从上一级组件传递到下一级组件(父子组件),即所谓的单向数据流。而且 prop 只读,不可被修改,所有修改都会失效并警告。

  1. 不应该在一个子组件内部改变 prop,这样会破坏单向的数据绑定,导致数据流难以理解。如果有这样的需要,可以通过 data 属性接收或使用 computed 属性进行转换。
  2. 如果 props 传递的是引用类型(对象或者数组),在子组件中改变这个对象或数组,父组件的状态会也会做相应的更新,利用这一点就能够实现父子组件数据的“双向绑定”,虽然这样实现能够节省代码,但会牺牲数据流向的简洁性,最好不要这样去做。
  3. 想要实现父子组件的数据“双向绑定”,可以使用 v-model 或 .sync。

2. 子组件向父组件传值($emit)

子组件向父组件传值需要用到一个方法 $emit,通过这个方法就可以实现向父组件传递数据。

**原理:**父组件在子组件通过 v-on 监听函数并接收参数,vue框架就在子组件监听了你 v-on=“fn” 的fn事件函数,在子组件使用 $emit 就能触发了。

实现代码:

<!-- 父组件 -->
<template>
  <div class="section">
    <child :msg="list" @hChang="hChang"></child>
  </div>
</template>

<script>
import child from './child.vue'
export default {
  name: 'HelloWorld',
  components: { comArticle },
  data() {
    return {
      msg: '酥脆角'
    }
  },
  methods:{
      hChang(msg) {
          this.msg = msg
      }
  }
}
</script>
<!-- 子组件 child.vue -->
<template>
  <div>
    {{ msg }}
    <button @click="change">改变字符串</button>
  </div>
</template>

<script>
export default {
  props: {
      msg: String
  },
  methods: {
      change(){
          this.$emit('hChang', '你好, 世界')
      }
  }
}
</script>

3. v-model 指令

v-model 是用来在表单控件或者组件上创建双向绑定的,他的本质是 v-bind 和 v-on 的语法糖,在一个组件上使用 v-model,默认会为组件绑定名为 value 的 prop 和名为 input 的事件。

当我们组件中的某一个 prop 需要实现上面所说的”双向绑定“时,v-model 就能大显身手了。有了它,就不需要自己手动在组件上绑定监听当前实例上的自定义事件,会使代码更简洁。

应用场景:

<!--父组件-->
<template>
    <h-input v-model="hValue"></h-input>
</template>
<script>
    export default {
        data() {
            return {
                input: ''
            }
        },
    }
</script>
<!--子组件 hInput.vue -->
<template>
    <input type="text" :value="hValue"  @input="hInput">
</template>
<script>
    export default {
        data() {
            return {
                hValue:  ''
            }
        },
        props: {
          // 接受来的数据可以是字符串, 也可以是数字类型
            value: [String, Number]
        },
        methods: {
            hInput(e) {
                const value = e.target.value
              // 通过 $emit 来向父组件传数据
                this.$emit('input', value)
            },
        },
}
</script>

通过上述可以看到, v-model=“hValue” 这段代码的本质是 v-bind 和 v-on , 也就是我们简称的语法糖。

原理: 默认为父组件绑定 :value=“hValue” 的属性和 @input=“回调函数” 事件, 子组件需要通过 this.$emit(‘input’, value) 来通知父组件, 从而来实现双向绑定。

4. .sync修饰符

定义:.sync修饰符是可以实现子组件与父组件的双向绑定,并且可以实现子组件同步修改父组件的值。

原理: 一般情况下,想要实现父子组件间值的传递,通常使用的是 props 和自定义事件 $emit 。其中,父组件通过 props 将值传给子组件,子组件再通过 $emit 将值传给父组件,父组件通过事件j监听获取子组件传过来的值。如果想要简化这里的代码,可以使用.sync修饰符,实际上就是一个语法糖。

代码实现:

<template>
  <div class="app">
     {{num}}
    <hr>
    <Child :money.sync="num"/>
    // <Child :money="num" v-on:update:money="num = $event"/>  //两句作用等同
  </div>
</template>
 
<script>
import Child from "./Child.vue"
export default {
  data() {
    return { num: 10000 }
  },
  components: { Child }
}
</script>
<template>
  <div class="child">
    {{money}}
    <button @click="$emit('update:money', money-100)">
    </button>
  </div>
</template>
 
<script>
export default {
  props: ["money"]
}
</script>

上面例子中,父组件传了一个参数 money 给子组件,子组件通过$emit修改 money 后,将值同步到父组件。

v-model 和 .sync 对比

.sync 从功能上看和 v-model 十分相似,都是为了实现数据的“双向绑定”,本质上,也都不是真正的双向绑定,而是语法糖。

相比较之下,.sync 更加灵活,它可以给多个 prop 使用,而 v-model 在一个组件中只能有一个。

从语义上来看,v-model 绑定的值是指这个组件的绑定值,比如 input 组件,select 组件,日期时间选择组件,颜色选择器组件,这些组件所绑定的值使用 v-model 比较合适。其他情况,没有这种语义,个人认为使用 .sync 更好。

5. ref

ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例,可以通过实例直接调用组件的方法或访问数据, 我们看一个ref 来访问组件的例子:

export default {
  data () {
    return {
      name: 'Vue.js'
    }
  },
  methods: {
    sayHello () {
      console.log('hello')
    }
  }
}
<template>
  <component-a ref="child"></component-a>
</template>
<script>
  export default {
    mounted () {
      const comA = this.$refs.child
      console.log(comA.name)  // Vue.js
      child.sayHello()  // hello
    }
  }
</script>

ref 这种方式,就是获取子组件的实例,然后可以直接子组件的方法和访问操作data的数据,就是父组件控制子组件的一种方式,子组件想向父组件传参或操作,只能通过其他的方式了。

6. Vuex

6.1. Vuex介绍

Vuex 是一个用于 Vue.js 应用程序的状态管理库。它可以帮助你在 Vue 应用中集中管理状态,并提供了一种可预测的方式来管理状态的变化,并且解决了多个视图依赖于同一状态和来自不同视图的行为需要变更同一状态的问题,将开发者的精力聚焦于数据的更新而不是数据在组件之间的传递上。

在大型的 Vue.js 应用中,组件之间的数据通信和状态管理可能会变得复杂。Vuex 解决了这个问题,通过引入一个全局的状态存储器(即“store”),使得组件之间可以共享和访问状态。这种集中式的状态管理能够简化组件之间的通信,提高代码的可维护性和可扩展性。

6.2. Vuex 的核心概念包括:

  1. State(状态): 存储应用程序的状态数据,即存储在 Vuex store 中的数据。所有的组件都可以直接访问和使用这些状态数据。

  2. Mutation(突变): 用于修改状态的方法。Mutation 是同步的操作,它定义了一些操作状态的函数,组件通过提交(commit)Mutation 来修改状态。

  3. Action(动作): 类似于 Mutation,但是 Action 可以包含异步操作。它可以用于执行一些异步任务,并在完成任务后提交 Mutation 来修改状态。

  4. Getter(获取器): 用于从状态中派生出一些新的状态。Getter 可以将状态进行加工处理,并返回一个新的值,组件可以通过调用 Getter 来获取这些派生出的状态。

  5. Module(模块): 用于将 Vuex store 分割成模块,每个模块可以拥有自己的 State、Mutation、Action、Getter 等。模块化的方式可以更好地组织和管理大型应用的状态。

通过使用 Vuex,你可以统一管理应用程序的状态,使得状态变化的追踪和调试更加容易。它还提供了一些辅助函数和工具,帮助你更方便地使用和操作状态。Vuex 可以与 Vue.js 无缝集成,使得状态管理变得简单而高效。

7. localStorage / sessionStorage

这种通信比较简单,缺点是数据和状态比较混乱,不太容易维护。

  • 通过 window.localStorage.getItem(key) 获取数据
  • 通过 window.localStorage.setItem(key,value) 存储数据

注意用JSON.parse() / JSON.stringify() 做数据格式转换, localStorage / sessionStorage可以结合vuex, 实现数据的持久保存,同时使用vuex解决数据和状态混乱问题。

8. slot

把子组件的数据通过插槽的方式传给父组件使用,然后再插回来

 Child.vue:
<template>
    <div>
        <slot :user="user"></slot>
    </div>
</template>
export default{
    data(){
        return {
            user:{ name:"oldCode" }
        }
    }
}

 Parent.vue:
<template>
    <div>
        <child v-slot="slotProps">
            {{ slotProps.user.name }}
        </child>
    </div>
</template>
  • 12
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值