百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

Vue2的16种传参通信方式(vue传参数)

bigegpt 2025-04-01 16:05 10 浏览

前言

先直入主题列出有哪些传参方式,下面再通过事例一一讲解。

props(父传子)
$emitv-on (子传父)
EventBus (兄弟传参)
.syncupdate: (父子双向)
v-model (父子双向)
ref
$children$parent
$attrs$listeners (爷孙双向)
provideinject (多层传参)
Vuex (全局)
Vue.prototype (全局)
路由
浏览器缓存 (全局)
window (全局)
$root (顶层)
slot(父传子)

一、props(父传子)

思路简述:父组件直接用冒号:绑定变量,然后子组件通过props接收父组件传过来的内容。

父组件代码:核心代码在第3行,直接用:message="message"传参。



<script>
import child  from './child .vue';
export default {
  components: {
    child 
  },
  data() {
    return {
      message: '这是父组件传过去的'
    };
  }
};
</script>

子组件代码:props接收消息后可以直接使用,如下第3行和第16行中直接使用

注意: props有两种接收方法,如下第9行注释的就是简写用法,此用法不能设置默认值。



<script>
  export default {
    //props:['message'],
    props: {
      message: {
        type: String,
        default: '', // 这里能设置默认值,如果父组件没有传参,默认值会生效
      },
    },
    mounted() {
      console.log(this.message);
    },
  };
</script>

注意: 此传参方式是单向的,即子组件接收到父组件的数据后,是不能直接修改props接收的数据,否则会直接报错。

二、$emit与v-on(子传父)

思路简述: 子组件通过$emit触发父组件的指定方法并且在此方法中携带任意参数,父组件通过在被触发的方法中拿到携带的参数完成子传父。

语法:$emit(方法名,参数)

子组件代码:核心代码在第11行,触发方法并且携带参数。



<script>
  export default {
    methods: {
      sendParent() {
        this.$emit('my-event', '这是传递的参数');
      },
    },
  };
</script>

父组件代码:核心代码在第3行触发事件,获取到子组件的传参。



<script>
  import child from './child.vue';
  export default {
    components: {
      child,
    },
    methods: {
      childEvent(item) {
        console.log('接收到子组件的传参:', item);
      },
    },
  };
</script>

三、EventBus(兄弟传参)

思路简述: 先创建一个全局的事件总线Bus(可以随意命名),并挂载在Vue.prototype上。

然后兄弟组件A通过$emit发送参数,兄弟组件B通过$on接收参数。

  • 有两种使用方法,下面分别讲解。

方法一:直接挂载全局事件总线,全局直接使用不需要额外引入。

先在项目的入口文件中(main.jsmain.ts)创建全局事件Bus并且挂载在Vue.prototype*

import Vue from 'vue';

const Bus = new Vue();

Vue.prototype.$Bus = Bus;

兄弟组件A代码:通过this.$Bus.$emit(方法名,参数)发送参数。



<script>
  export default {
    methods: {
      sendSibling() {
        this.$Bus.$emit('my-event', '参数');
      },
    },
  };
</script>

兄弟组件B代码:通过this.$Bus.$on(对应$emit的方法,本地方法)触发本地的方法,从而接收参数。



<script>
  export default {
    created() {
      this.$Bus.$on('my-event', this.handleMessage);
    },
    beforeDestroy() {
      this.$Bus.$off('my-event', this.handleMessage);
    },
    methods: {
      handleMessage(message) {
        console.log('来自兄弟的参数:', message);
      },
    },
  };
</script>

注意: 如上第10-12行所示,在组件销毁前要在 beforeDestroy 生命周期中使用$off移除移除$on的事件监听器,防止避免内存泄漏影响性能。如下所示

方法二: 不创建全局事件总线,单独开一个文件,哪里需要就哪里引用。

创建一个单独文件命名为Bus.js(可以自由命名)

import Vue from "vue"

export default new Vue()

兄弟组件A代码: 先引入Bus.js文件,然后通过Bus.$emit(方法名,参数)发送参数。



<script>
  import Bus from './Bus.js';
  export default {
    methods: {
      sendSibling() {
        Bus.$emit('my-event', '参数');
      },
    },
  };
</script>

兄弟组件B代码:先引入Bus.js文件,然后通过Bus.$on(对应$emit的方法,本地方法)触发本地的方法,从而接收参数。同样也需要使用$off销毁事件监听。



<script>
  import Bus from './Bus.js';
  export default {
    created() {
      Bus.$on('my-event', this.handleMessage);
    },
    beforeDestroy() {
      Bus.$off('my-event', this.handleMessage);
    },
    methods: {
      handleMessage(message) {
        console.log('来自兄弟的参数:', message);
      },
    },
  };
</script>

四、.sync与update:(父子双向)

思路简述:.sync其实是一个语法糖, 配合子组件用this.$emit('update:绑定的属性名', 方法)修改父组件属性, 能解决props只能单向传递的问题。

父组件代码:核心代码在第3行,比普通的父传子多使用了.sync修饰符。



<script>
import chile from './chile.vue';

export default {
  components: {
    chile
  },
  data() {
    return {
      myData: '父组件数据'
    };
  }
};
</script>

子组件代码:核心代码是第14行,通过this.$emit同步修改父组件内容。



<script>
  export default {
    props: {
      myprop: String,
    },
    methods: {
      updateData() {
        this.$emit('update:myprop', 新内容);
      },
    },
  };
</script>

注意:使用.sync修饰符时,this.$emit里面总是以update:开头,后面接要修改的属性名称。

五、v-model(父子双向)

思路简述:v-model最常用于表单,它其实是一个语法糖,并且和上面.sync有点类似。v-model本质上是v-bind:value@input组件效果。通过v-bind:value绑定数据父传子,通过@input触发对应事件子传父从而实现双向绑定。

父组件代码:直接用v-model绑定要传给子组件的参数,当子组件触发input事件时父组件myData会同步更新。



<script>
import child from './child.vue';

export default {
  components: {
    child
  },
  data() {
    return {
      myData: '天天鸭'
    };
  }
};
</script>

子组件代码:input输入框的内容发生变化时,就会触发@input事件,然后this.$emit同步修改父组件的值



<script>
export default {
  model: {
    prop: 'myProp',
    event: 'input'
  },
  props: {
    myProp: String
  },
  data() {
    return {
      childData: this.myProp
    };
  },
  methods: {
    handleChange(event) {
      this.childData = event.target.value;
      this.$emit('input', this.childData);
    }
  }
};
</script>

注意:在子组件当中,必须要定义model来指定props和事件名称(名称默认为input)。

六、ref

思路讲解: ref主要用来访问子组件的方法和属性,是直接操纵DOM的方式。主要用法是在子组件上绑定一个ref,然后父组件用this.$refs直接访问子组件的方法

父组件代码:子组件上用ref="refChild"绑定一个ref,然后用this.$refs.refChild获取到子组件实例,能获取到子组件属性和操纵子组件方法。



<script>
  import child from './child.vue';
  export default {
    components: {
      child,
    },
    mounted() {
      let childObj = this.$refs.refChild;
      console.log(childObj.name); // 直接获取到子组件的属性内容 打印出来:天天鸭
      childObj.childMethod('参数'); // 触发子组件的方法
    },
  };
</script>

子组件代码:



<script>
  export default {
    data() {
      return {
        name: '天天鸭',
      };
    },
    methods: {
      childMethod(val) {
        console.log(val);
      },
    },
  };
</script>

七、$children与$parent

简述: $children$parentVue用于访问子组件实例和父组件实例的特殊属性。其中$children能获取所有子组件实例但不能获取孙子的,而$parent获取当前组件的父组件实例。

父组件代码: 直接使用this.$children即可获取。

注意: 获取到的实例可能为空,因此需要判空。并且如果有多个子组件时返回的是一个数组,所以需要通过下标确认对应的子组件数据。



<script>
  import child from './child.vue';
  export default {
    components: {
      child,
    },
    methods: {
      getChildMethod() {
       // 判空,然后用下标获取
        if (this.$children.length > 0) {
          this.$children[0].childMethod();  // 使用子组件方法
          this.$children[0].name;    // 使用子组件属性
        }
      },
    },
  };
</script>

子组件代码: 类似地,父组件也是同样用法,但区别是返回的不是数组而且一个对象,能直接使用。



<script>
  export default {
    mounted(){
        this.$parent.parMethod()
        this.$parent.name
    }
  };
</script>

八、$attrs与$listeners(爷孙双向)

简述: $attrs$listeners相当于是使用在父亲组件上的一个中转站。 $attrs用于将props外的数据从爷组件传递给孙组件的,而$listeners用于从孙组件中触发爷组件中事件达到传参效果。

下面把$attrs$listeners分开讲解更易于理解。

$attrs使用流程代码:

(1)爷组件代码: 类似父传子,正常用冒号绑定属性传参。

(2)父组件代码$attrs作用在父组件,意思是把props之外属性全部传递给到孙子。

注意:如果这里父组件用props接收了name属性,那么用$attrs无法传递到孙子组件,因为只能传递props之外属性。

(3)孙组件代码:类似父传子,正常用popos接收爷组件传过来的参数。


<script>
  export default {
    props: {
      name: {
        default: String,
      },
    },
  };
</script>

$listeners使用流程代码:

(1)孙组件代码 直接this.$emit类似子传父



<script>
  export default {
    methods: {
      update() {
        this.$emit('my-event', '孙传给爷的数据');
      },
    },
  };
</script>

(2)父组件代码:$listeners作用在父组件。

(3)爷组件代码: 类似子传父中的父组件,触发对应孙子组件this.$emit中的my-event事件接收到参数。



<script>
  import Parent from './Parent.vue';
  export default {
    components: {
      Parent,
    },
    methods: {
      getMyEvent(val) {
        console.log('爷组件接收到的数据:', val);
      },
    },
  };
</script>

这里感觉算两种(爷传孙与孙传爷)传参方式了,但由于都是类似中转站效果,所以放一起说比较好理解。

九、provide与inject(多层传参)

简述: provideinject无论多少层组件都能传参。顶层组件通过provide传参,下面所有组件都能用inject接收,而且子组件也能通过方法给顶层组件传参。

顶层组件代码: 核心代码在第8行的provide()中,可以传递常量、变量和方法。



<script>
  export default {
    provide() {
      return {
        name: '天天鸭',
        age: this.age,
        myMethod: this.myMethod,
      };
    },
    data() {
      return {
        age: '18',
      };
    },
    methods: {
      myMethod(data) {
        console.log('收到来自某个孙子的数据:', data);
      },
    },
  };
</script>

子孙组件代码:核心代码在第10行接收参数, 除了能接收顶层参数外,还能通过参考第13行的用法,通过顶层给到的方法传参给顶层组件。



<script>
  export default {
    inject: ['name', 'age', 'myMethod'],
    methods: {
      myMethod(data) {
        this.myMethod(data); // 传参给顶层祖先组件
      },
    },
  };
</script>

十、Vuex(全局)

有针对性写过对应的文章,可以直接跳转细看:对比学习vuex和pinia用法

十一、Vue.prototype(全局)

简述:能用Vue.prototype把任何属性和方法挂载在Vue实例了,让所有Vue实例共用。

(1)挂载属性 直接往Vue.prototype挂载即可

Vue.prototype.$testName = '天天鸭';

(2)挂载方法直接往Vue.prototype挂载即可

Vue.prototype.$testMethod = function(val) {
  console.log(val);
};

调用:直接在任何页面用this调用

this.$appName;

this.$testMethod('参数');

十二、浏览器缓存

简述: localStoragesessionStorage:主要是浏览器用来持久化存储的,这算是用的不多,但也是必用的一种通信方式。两者区别如下

sessionStorage(临时存储):最大空间5M,为每一个数据源维持一个存储区域,但只在浏览器打开期间存在,关闭后数据会不会消失,包括页面重新加载。
localStorage(长期存储):最大空间5M,与 sessionStorage 一样,但是哪怕浏览器关闭后,数据依然会一直存在,除非手动删除。

具体用法如下所示:

// 存储
sessionStorage.setItem('key', 'value');
localStorage.setItem('key', 'value');

// 获取
let valueFromSessionStorage = sessionStorage.getItem('key');
let valueFromLocalStorage = localStorage.getItem('key');

// 删除
sessionStorage.removeItem('key');
localStorage.removeItem('key');

// 清空所有
sessionStorage.clear();
localStorage.clear();

注意:存储的数据只能是字符串形式,因此如果要存储对象或者数组,则需要使用JSON.stringify来转换后再存储,读取后用JSON.parse还原。

十三、window(全局)

简述: 直接用语法 window.age = '18' 定义然后全局通用即可。(此方式是存放在内存刷新会清空)

注意:在 Vue 应用中,虽然可以直接将属性挂载到 window 对象上实现全局通用,但并推荐,因为这可能会出现命名冲突、导致代码难以维护

添加属性和方法:直接定义,可以是属性也可以是对象

window.Obj = { test: '挂载对象' }
window.name = '天天鸭'

使用:

console.log( window.Obj); 
console.log( window.name);  

十四、路由

简述: Vue在路由跳转时携带参数其实也很常用的方式,下面汇总一下三种路由传参。

(1)通过 params 传参 跳转页面用法:

this.$router.push({name:"index", params:{id}})

目标页面接收参数:

this.$route.params.id 

(2)通过 query 传参

跳转页面用法:有几种方式

this.$router.push({ name:"index", query:{id}})

this.$router.push({ path:"/index", query:{id}}) 

this.$router.push('/index?name='+obj.name+'&age='+obj.age)

目标页面接收参数:

this.$route.query.id

(3)通过动态路由传参

注意: 如果用动态路由传参需要对路由进行配置;并且参数会在 url 中显示。 如下所示,在path后面要配置:name/:age.

{ 
  path: '/about/:name/:age' ,  
  name: 'About', 
  component() => import('@/views/About.vue') 
}

跳转页面用法:

this.$router.push('/about/'+obj.name+'/'+obj.age) 

目标页面接收参数:

this.$route.params

十五、$root(顶层)

简述: 可以通过 $root 访问到整个 Vue 树的根实例,也就是可以使用 $root 来访问全局的属性或者修改全局的属性。

示例:在main.js文件中定义一个globalName属性,可以全局使用。

import App from './App.vue';
import Vue from 'vue';

new Vue({
  el: '#app',
  render: h => h(App),
  data: {
    globalName: '天天鸭'
  }
});

在下层任意组件使用或者修改内容



<script>
export default {
  mounted() {
    this.$root.globalName = '修改数据';
  },
};
</script>

十六、slot(父传子)

简述: 通过插槽也是可以传递参数,这也是很多人忽略的一种方式。父组件可以通过插槽向子组件传递参数,然后子组件拿到参数进行渲染。

下面主要讲解具名插槽和默认插槽两种使用方式。

(1)具名插槽用法

子组件代码:slot定义一个名叫header的插槽。



<script>
export default {
};
</script>

父组件代码:v-slot:header向子组件的header插槽传递内容。这边传递什么那边就会在对应区域显示什么。



<script>
import child from './child.vue';

export default {
  components: {
    child
  }
};
</script>

(2)无参数传递的默认插槽

子组件代码:slot定义插槽时不需要指定name名称。



<script>
export default {
};
</script>

父组件代码:不需要指定插槽名称,只要在组件中间填写内容就会渲染在默认插槽中。



<script>
import child from './child.vue';

export default {
  components: {
    child
  }
};
</script>

相关推荐

得物可观测平台架构升级:基于GreptimeDB的全新监控体系实践

一、摘要在前端可观测分析场景中,需要实时观测并处理多地、多环境的运行情况,以保障Web应用和移动端的可用性与性能。传统方案往往依赖代理Agent→消息队列→流计算引擎→OLAP存储...

warm-flow新春版:网关直连和流程图重构

本期主要解决了网关直连和流程图重构,可以自此之后可支持各种复杂的网关混合、多网关直连使用。-新增Ruoyi-Vue-Plus优秀开源集成案例更新日志[feat]导入、导出和保存等新增json格式支持...

扣子空间体验报告

在数字化时代,智能工具的应用正不断拓展到我们工作和生活的各个角落。从任务规划到项目执行,再到任务管理,作者深入探讨了这款工具在不同场景下的表现和潜力。通过具体的应用实例,文章展示了扣子空间如何帮助用户...

spider-flow:开源的可视化方式定义爬虫方案

spider-flow简介spider-flow是一个爬虫平台,以可视化推拽方式定义爬取流程,无需代码即可实现一个爬虫服务。spider-flow特性支持css选择器、正则提取支持JSON/XML格式...

solon-flow 你好世界!

solon-flow是一个基础级的流处理引擎(可用于业务规则、决策处理、计算编排、流程审批等......)。提供有“开放式”驱动定制支持,像jdbc有mysql或pgsql等驱动,可...

新一代开源爬虫平台:SpiderFlow

SpiderFlow:新一代爬虫平台,以图形化方式定义爬虫流程,不写代码即可完成爬虫。-精选真开源,释放新价值。概览Spider-Flow是一个开源的、面向所有用户的Web端爬虫构建平台,它使用Ja...

通过 SQL 训练机器学习模型的引擎

关注薪资待遇的同学应该知道,机器学习相关的岗位工资普遍偏高啊。同时随着各种通用机器学习框架的出现,机器学习的门槛也在逐渐降低,训练一个简单的机器学习模型变得不那么难。但是不得不承认对于一些数据相关的工...

鼠须管输入法rime for Mac

鼠须管输入法forMac是一款十分新颖的跨平台输入法软件,全名是中州韵输入法引擎,鼠须管输入法mac版不仅仅是一个输入法,而是一个输入法算法框架。Rime的基础架构十分精良,一套算法支持了拼音、...

Go语言 1.20 版本正式发布:新版详细介绍

Go1.20简介最新的Go版本1.20在Go1.19发布六个月后发布。它的大部分更改都在工具链、运行时和库的实现中。一如既往,该版本保持了Go1的兼容性承诺。我们期望几乎所...

iOS 10平台SpriteKit新特性之Tile Maps(上)

简介苹果公司在WWDC2016大会上向人们展示了一大批新的好东西。其中之一就是SpriteKitTileEditor。这款工具易于上手,而且看起来速度特别快。在本教程中,你将了解关于TileE...

程序员简历例句—范例Java、Python、C++模板

个人简介通用简介:有良好的代码风格,通过添加注释提高代码可读性,注重代码质量,研读过XXX,XXX等多个开源项目源码从而学习增强代码的健壮性与扩展性。具备良好的代码编程习惯及文档编写能力,参与多个高...

Telerik UI for iOS Q3 2015正式发布

近日,TelerikUIforiOS正式发布了Q32015。新版本新增对XCode7、Swift2.0和iOS9的支持,同时还新增了对数轴、不连续的日期时间轴等;改进TKDataPoin...

ios使用ijkplayer+nginx进行视频直播

上两节,我们讲到使用nginx和ngixn的rtmp模块搭建直播的服务器,接着我们讲解了在Android使用ijkplayer来作为我们的视频直播播放器,整个过程中,需要注意的就是ijlplayer编...

IOS技术分享|iOS快速生成开发文档(一)

前言对于开发人员而言,文档的作用不言而喻。文档不仅可以提高软件开发效率,还能便于以后的软件开发、使用和维护。本文主要讲述Objective-C快速生成开发文档工具appledoc。简介apple...

macOS下配置VS Code C++开发环境

本文介绍在苹果macOS操作系统下,配置VisualStudioCode的C/C++开发环境的过程,本环境使用Clang/LLVM编译器和调试器。一、前置条件本文默认前置条件是,您的开发设备已...