前置

大小 vue 项目都离不开组件通讯, 在这里总结一下vue组件通讯方式并列出, 都是简单的例子. 适合像我这样的小白。如有错误,欢迎指正。

温馨提示: 下文没有列出 vuex, vuex 也是重要的组件通讯方式。

props

  • 最常用的组件通讯方式
  • 值可以是数组或对象,使用对象时可以配置高级选项,如类型检测、自定义验证和设置默认值
  • 方向:父 -> 子

Son.vue

  1. export default {
  2. props: {
  3. text: {
  4. type: String,
  5. required: true,
  6. },
  7. },
  8. mounted() {
  9. console.log(this.text) // 我是父组件提供给子组件的值
  10. },
  11. }

App.vue

  1. <template>
  2. <Son text='我是父组件提供给子组件的值'/>
  3. </template>
  4. <script>
  5. import Son from './components/dispatch/Son'
  6. export default {
  7. name: 'app',
  8. components: {
  9. Son,
  10. }
  11. },
  12. </script>

$refs

  • 常用的方式
  • 返回注册过 ref 特性的所有 DOM 元素和组件实例
  • 可以用来操作 DOM
  • 可以用来传值
  • 方向:子 -> 父

Son.vue

  1. export default {
  2. methods: {
  3. sonFunc() {
  4. console.log('我是子组件的值')
  5. },
  6. },
  7. }

App.vue

  1. <template>
  2. <Son ref="sonref"/>
  3. </template>
  4. <script>
  5. import Son from './components/dispatch/Son'
  6. export default {
  7. name: 'app',
  8. components: {
  9. Son,
  10. },
  11. mounted() {
  12. this.$refs.sonref.sonFunc()
  13. },
  14. }
  15. </script>

控制台打印: 我是子组件的值

$emit

  • $emit 用来触发当前实例上的事件
  • 方向:父 -> 子
  • 参数一:来触发的当前实例上的事件函数
  • 参数二:附加参数,传给监听器回调

Son.vue

  1. export default {
  2. mounted() {
  3. this.$emit('customFunc', '我是子组件传给父组件的值')
  4. },
  5. }

App.vue

  1. <template>
  2. <Son v-on:customFunc="fatherFunc" />
  3. </template>
  4. <script>
  5. import Son from './components/dispatch/Son'
  6. export default {
  7. name: 'app',
  8. components: {
  9. Son,
  10. },
  11. methods: {
  12. fatherFunc(value) {
  13. console.log(value) // 我是子组件传给父组件的值
  14. },
  15. },
  16. }
  17. </script>

@update

  • 需要配合 .sync 使用
  • 与上面的 $emit 写法类似
  • 不同之处在于$emit 的第一个参数不在是当前实例上的事件函数
  • 方向:子 -> 父

Son.vue

  1. export default {
  2. mounted() {
  3. this.$emit("update:text", '我是子组件传给父组件的值')
  4. }
  5. }

App.vue

  1. <template>
  2. <Son :text.sync='text'/>
  3. </template>
  4. <script>
  5. import Son from "./components/dispatch/Son"
  6. export default {
  7. data() {
  8. return {
  9. text: ''
  10. }
  11. },
  12. mounted() {
  13. console.log(this.text); // 我是子组件传给父组件的值
  14. }
  15. }
  16. </script>

接下来看下面的写法,上面这种写法是对如下方式的简写, 或者称之为语法糖。可以不借助 .sync

Son.vue

  1. export default {
  2. mounted () {
  3. this.$emit('update:text','我是子组件传给父组件的值')
  4. }
  5. }

App.vue

  1. <Son @update:text="v => (this.value = v)" />
  2. import Son from "./components/dispatch/Son"
  3. export default {
  4. mounted() {
  5. console.log(this.value) // 我是子组件传给父组件的值
  6. }
  7. }

v-model

  • v-model 常用来给 input 实现双向数据绑定
  • v-model 也可以用来传值
  • 有局限性,只能传 input value
  1. <input v-model="text">

等价于:

  1. <input
  2. v-bind:value="text"
  3. v-on:input="text = $event.target.value"
  4. >

接下来看如何通过 v-model 传值。

Son.vue

  1. <template>
  2. <input
  3. v-bind:value="value"
  4. v-on:input="$emit('input', $event.target.text)"
  5. />
  6. </template>
  7. <script>
  8. export default {
  9. data() {
  10. return {
  11. value: '我是子组件传给父组件的值',
  12. }
  13. }
  14. }
  15. </script>

App.vue

  1. <template>
  2. <Son v-model="text" />
  3. </template>
  4. <script>
  5. import Son from './components/dispatch/Son'
  6. export default {
  7. name: 'app',
  8. components: {
  9. Son,
  10. }
  11. }
  12. </script>

$parent $childred

  • $parent: 父实例,如果当前实例有的话
  • $children: 当前实例的直接子组件
  • $parent $childred 通过封装可以实现不同方向的传值

$children 并不保证顺序,也不是响应式的。可以使用一个数组配合 v-for 来生成子组件,使用 Array 作为真正的来源。

App.vue

  1. export default {
  2. data() {
  3. return {
  4. value: '我是父组件的值',
  5. }
  6. },

Son.vue

  1. export default {
  2. mounted: {
  3. console.log(this.$parent.value) // 我是父组件的值
  4. this.$parent.value = 666
  5. console.log(this.$parent.value) // 666
  6. },
  7. }

简单封装一下即可实现$parent 配合 $emit 实现跨级向上传值。

main.js

  1. Vue.prototype.$dispatch = function(event, value) {
  2. let parent = this.$parent
  3. while (parent) {
  4. parent.$emit(event, value)
  5. parent = parent.$parent
  6. }
  7. }

这样使用: this.$dispatch('event',value)

简单封装一下即可实现$children 配合 $emit 实现向下传值。

  1. Vue.prototype.$broadcast = function(event, value) {
  2. const broadcast = children => {
  3. children.forEach(child => {
  4. child.$emit(event, value)
  5. if (child.$children) {
  6. broadcast(child.$children)
  7. }
  8. })
  9. }
  10. broadcast(this.$children)
  11. }

这样使用: this.$broadcast('event',value)

$attrs

  • 获取父组件通过 v-bind 传过去的所有值
  • class 和 style 除外
  • 可以通过 v-bind="$attrs" 传入内部组件
  • 只能在 <template> 中使用
  • 方向:子 -> 父

App.vue

  1. <template>
  2. <Son :value1="123" :value2="456" />
  3. </template>
  4. import Son from './components/dispatch/Son'
  5. export default {
  6. name: 'app',
  7. components: {
  8. Son,
  9. },
  10. }

Son.vue

  1. <template>
  2. <div>{{$attrs}}</div>
  3. </template>
  4. <script>
  5. export default {
  6. inheritAttrs: false,
  7. }
  8. </script>

$listener

  • 获取父作用域中的 () v-on 事件监听器。
  • 不含 .native 修饰器修饰的时间监听器。
  • 可以通过 v-on="$listeners" 传入内部组件(孙子组件)。
  • 方向:父 -> 子

App.vue

  1. <template>
  2. <Son @customFunc="fatherFunc"/>
  3. </template>
  4. <script>
  5. import Son from './components/dispatch/Son'
  6. export default {
  7. name: 'app',
  8. components: {
  9. Son,
  10. },
  11. methods: {
  12. fatherFunc() {
  13. console.log('666')
  14. },
  15. },
  16. }
  17. </script>

Son.vue

  1. <template>
  2. <button @click="$listeners.customFunc()"></button>
  3. </template>

provide inject

  • provideinject 不推荐直接用于应用程序代码中
  • 与 React 的上下文特性很相似。这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在起上下游关系成立的时间里始终生效
  • provide 选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的属性。在该对象中你可以使用 ES2015 Symbols 作为 key,但是只在原生支持 Symbol 和 Reflect.ownKeys 的环境下可工作
  • provideinject 绑定并不是可响应的。这是 vue 刻意为之
  • 如果你传入了一个可监听的对象,那么其对象的属性还是可响应的

这里有一个简单的示例:

App.vue

  1. <template>
  2. <Son />
  3. </template>
  4. <script>
  5. import Son from './components/dispatch/Son'
  6. export default {
  7. name: 'app',
  8. components: {
  9. Son,
  10. },
  11. provide() {
  12. return {
  13. text: '我是父组件的值',
  14. }
  15. },
  16. }
  17. </script>

Son.vue

  1. export default {
  2. inject: ['text'],
  3. mounted() {
  4. console.log(this.text) // 我是父组件的值
  5. },
  6. }

事件总线

  • EventBus 又称为事件总线
  • 不是一个具体的 API,EventBus 代表一种思路
  • 可以看作 vuex 的究极压缩版

App.vue

  1. <template>
  2. <div>
  3. <Son />
  4. </div>
  5. </template>
  6. <script>
  7. import Son from './components/dispatch/Son'
  8. export default {
  9. name: 'app',
  10. components: {
  11. Son,
  12. },
  13. mounted() {
  14. this.$EventBus.$emit('event', 'app.vue')
  15. },
  16. }
  17. </script>

Son.vue

  1. export default {
  2. mounted() {
  3. this.$EventBus.$on('event', function(v) {
  4. console.log(v)
  5. })
  6. },
  7. }

Observable

  • observable 可以让一个对象可响应
  • vue 内部会用它来处理 data 函数返回的对象
  • 返回的对象可以直接用于渲染函数和计算属性内,并且会在发生改变时触发相应的更新
  • 可以作为最小化的跨组件状态存储器,用于简单的场景

store.js

  1. import Vue from 'vue'
  2. export const store = Vue.observable({ text: '我是store里的' })
  3. export const mutations = {
  4. setText(text) {
  5. store.text = text
  6. },
  7. }

App.vue

  1. import { store, mutations } from '../store'
  2. export default {
  3. mounted() {
  4. console.log(store.text) //我是store里的
  5. mutations.setText('我在App.vue中将你改变')
  6. console.log(store.text) //我在App.vue将你改变
  7. },
  8. }

composition-api

  • composition-api 包含 vue3 的新特性
  • provideinject 可以实现嵌套组件之间的数据传递
  • 这两个函数只能在 setup 函数中使用
  • 父级组件中使用 provide 函数向下传递数据
  • 子级组件中使用 inject 获取上层传递过来的数据
  • 不限层级。

App.vue

  1. <template>
  2. <provideAndInject />
  3. </template>
  4. <script>
  5. import { provide } from "@vue/composition-api"
  6. import provideAndInject from "./components/provideAndInject"
  7. export default {
  8. name: "app",
  9. components: {
  10. provideAndInject
  11. },
  12. setup() {
  13. // provide('数据名称', 要传递的数据)
  14. provide("customVal", "我是父组件向子组件传递的值");
  15. }
  16. };
  17. </script>

Son.vue

  1. <template>
  2. <h3>{{ customVal }}</h3>
  3. </template>
  4. <script>
  5. import { inject } from "@vue/composition-api";
  6. export default {
  7. setup() {
  8. //调用 inject 函数,通过指定的数据名称,获取到父级共享的数据
  9. const customVal = inject("customVal");
  10. return {
  11. customVal
  12. };
  13. }
  14. };
  15. </script>

父组件可以通过 ref 创建响应式数据通过 provide 共享给子组件。

vue 听说你很会传值?的更多相关文章

  1. 【转】Vue组件一-父组件传值给子组件

    Vue组件一-父组件传值给子组件 开始 Vue组件是学习Vue框架最比较难的部分,而这部分难点我认为可以分为三个部分学习,即 组件的传值 - 父组件向子组件中传值 事件回馈 - 子组件向父组件发送消息 ...

  2. vue组件定义方式,vue父子组件间的传值

    vue组件定义方式,vue父子组件间的传值 <!DOCTYPE html> <html lang="zh-cn"> <head> <met ...

  3. 从壹开始前后端分离 [ Vue2.0+.NET Core2.1] 二十║Vue基础终篇:传值+组件+项目说明

    缘起 新的一天又开始啦,大家也应该看到我的标题了,是滴,Vue基础基本就到这里了,咱们回头看看这一路,如果你都看了,并且都会写了,那么现在你就可以自己写一个Demo了,如果再了解一点路由,ajax请求 ...

  4. 浅谈vue父子组件之间的传值

    前言:本章主要说下父子组件的传值,为商品列表组件之间的传值做一个基础预热.Github:https://github.com/Ewall1106/mall(请选择分支chapter23) 1.父组件向 ...

  5. vue 实现子向父传值

    父组件 <template> <div id="app"> <child @onChange='onChildValue'></child ...

  6. vue中非父子组件的传值bus的使用

    非父子之间的组件传值,可以使用vuex.简单的状态管理,也可以用vue bus vue bus可以实现不同组件间.不同页面间的通信,比如我在A页面出发点击事件,要B页面发生变化,使用方法如下: 全局定 ...

  7. Vue.js父子组件如何传值 通俗易懂

    父子组件传值原理图 一般页面的视图App.vue应为这样 一.父组件向子组件传值 1.创建子组件,在src/components/文件夹下新建一个Child.vue 2.Child.vue的中创建pr ...

  8. Vue组件创建和组件传值

    Vue创建组件的方式 使用Vue.Extend()和Vue.component全局注册组件 首先我们定义一个组件并接收 var com1 =Vue.extend({ template:"&l ...

  9. vue几种简单的传值方式

    除了一下的几种方式外,可以参考 https://www.cnblogs.com/hpx2020/p/10936279.html 组件传值的方法: 一.父组件向子组件传递数据(props) 第1:父组件 ...

随机推荐

  1. ASP.NET CORE 启动过程及源码解读

    在这个特殊的春节,大家想必都在家出不了们,远看已经到了回城里上班的日子,但是因为一只蝙蝠的原因导致我们无法回到工作岗位,大家可能有的在家远程办公,有些在家躺着看书,有的是在家打游戏:在这个特殊无聊的日 ...

  2. 在eclipse的Java类文件中,右上角出现大写字母A代表什么

    代表这个文件(类)是一个抽象类abstract的第一个字母:

  3. getBoundingClientRect的实用场景

    在用vue开发项目时候,遇到一个问题,首页有代办列表,是固定定位,滚动时候需要监听距离页面顶部的距离,如果很接近顶部则将代办列表展示,首页隐藏,如果再网上翻动则又回到首页. 因为是是fixed定位,所 ...

  4. Iterator接口(遍历器)和for/of循环

    在javascript中表示“集合”的数据结构,主要有Array,Object,Map,Set. Iterator(遍历器)接口是为各种不同的数据结构提供了统一的访问机制.任何数据结构具有Iterat ...

  5. django使用户名和邮箱都能登录

    为了能够让邮箱也能登录,需要重新定义认证功能,需要把email添加成username用于认证 定义的class继承ModelBackend,使用Q方法并集 然后在settings.py里面添加 这样既 ...

  6. 在 centos6 上安装 LAMP

    LAMP 代表的是 Linux, Apache, MySQL, 以及 PHP.   第一步,安装 Apache 使用 yum 安装 sudo yum install httpd 启动 httpd 服务 ...

  7. Druid 0.17 入门(3)—— 数据接入指南

    在快速开始中,我们演示了接入本地示例数据方式,但Druid其实支持非常丰富的数据接入方式.比如批处理数据的接入和实时流数据的接入.本文我们将介绍这几种数据接入方式. 文件数据接入:从文件中加载批处理数 ...

  8. css 实现九宫格

    1.自己写了一个,写完对比了下别人写的发现自己写的太low.故就不写自己太差劲的了. 别人写的我总结优化了一下,如果不用写内容去掉position,content简单也是可以的. <!DOCTY ...

  9. 强连通分量SCC 2-SAT

    强连通分量SCC 2-SAT 部分资料来自: 1.https://blog.csdn.net/whereisherofrom/article/details/79417926 2.https://ba ...

  10. 解开SQL注入的神秘面纱-来自于宋沄剑的分享

    解开SQL注入的神秘面纱-来自于宋沄剑的分享 https://files.cnblogs.com/files/wxlevel/揭开SQL注入的神秘面纱.pdf