vue组件传参的八种方式
① props传参
子组件定义 props 有三种方式:
//第一种 数组形式 props:['***','***','***'] //第二种 对象形式 props:{ ***:String, ***:Number } //第三种 嵌套对象方式 props:{ ***:{ type: String, default: 0, required: true, // 返回值不是 true,会警告 validator(val) { return val === 10 } } } 复制代码
父组件传参:
静态属性传参 1. 在不定义 props 类型的情况下 props 接受到的均为 String。 <children xxx="123"></children> 2. 当 props 属性指定为 Boolean 时,并且只有属性 key 没有值 value 时接受到的是 true -- 有只有属性没有值, 这种情况 props 指定类型是 Boolean 则接收到的是 true <children xxx></children> 动态属性传参 1. 需要区分非简写形式传入的值是对象,则会对应 props 中多个值 2. 会保留传入值的类型 3. 如果是表达式则获取到的是表达式的计算结果 //prop 接收到 Number 类型的 123 <children :xxx="123"></children> //prop 接收到 Array 类型的 [1, 2, 3] <children v-bind:xxx="[1, 2, 3]"></children> //prop 会接收到 xxx1 和 xxx2 俩个参数。这种不支持简写形式 <children v-bind="{xxx1: 1, xxx2: 2}"></children> 复制代码
② attrs 和 listeners
$attrs 会获取到 props 中未定义的属性(class 和 style 属性除外),支持响应式 常用的场景有俩种 1.组件嵌套组件时可以使用 $attrs 来支持过多的属性支持。比如 elementUI 的 table 组件。支持的属性十几个,而平常封装的时候用的最多的也就一俩个。 2.属性默认是添加在父组件上的,有时候想把多余的属性添加在子组件上(可以结合 inheritAttrs: false 属性,让父属性不接受多余的属性) $listener 包含了父作用域中的 (不含 `.native` 修饰器的) `v-on` 事件监听器。它可以通过 v-on="$listeners" 传入内部组件——在创建更高层次的组件时非常有用。 简单点讲它是一个对象,里面包含了作用在这个组件上所有的监听器(监听事件),可以通过 v-on="$listeners" 将事件监听指向这个组件内的子元素(包括内部的子组件)。 下面是例子 <div id="app"> <child1 :p-child1="child1" :p-child2="child2" :p-child-attrs="1231" v-on:test1="onTest1" v-on:test2="onTest2"> </child1> </div> Vue.component("Child1", { inheritAttrs: true, props: ["pChild1"], template: ` <div> <p>in child1:</p> <p>props: {{pChild1}}</p> <p>$attrs: {{this.$attrs}}</p> <hr> <child2 v-bind="$attrs" v-on="$listeners"></child2></div>`, mounted: function() { this.$emit("test1"); } }); Vue.component("Child2", { inheritAttrs: true, props: ["pChild2"], template: ` <div> <p>in child->child2:</p> <p>props: {{pChild2}}</p> <p>$attrs: {{this.$attrs}}</p> <button @click="$emit('test2','按钮点击')">触发事件</button> <hr> </div>`, mounted: function() { this.$emit("test2"); } }); const app = new Vue({ el: "#app", data: { child1: "pChild1的值", child2: "pChild2的值" }, methods: { onTest1() { console.log("test1 running..."); }, onTest2(value) { console.log("test2 running..." + value); } } }); 上例中,父组件在`child1`组件中设置两个监听事件`test1`和`test2`,分别在`child1`组件和`child1`组件内部的`child2`组件中执行。还设置了三个属性`p-child1`、`p-child2`、`p-child-attrs`。其中`p-child1`、`p-child2`被对应的组件的`prop`识别。所以:\ `p-child1`组件中`$attrs`为`{ "p-child2": "pChild2的值", "p-child-attrs": 1231 }`;\ `p-child2`组件中`$attrs`为`{ "p-child-attrs": 1231 }`。 再点击`child2`组件中的按钮,触发事件 控制台打印出 test2 running...按钮点击 复制代码
③ $emit 通知
vue 默认有 $on $emit $once $off 几种方法来实现发布订阅模式,这也应用在了组件传参上。在组件上添加的特殊方法 @abc="methods" 就相当于使用了 $on 来监听这个方法。因此组件内可以使用 $emit 来进行通知。 复制代码
④ v-model
// 写法 1 <children v-model="a"></children> { model: { prop: 'value', event: 'update:a', }, methods: { a() { this.$emit('update:a', 1)} } } // 写法 2 <children :a="a" @update:a="a = $event"></children> { props: ['a'] methods: { a() { this.$emit('update:a', 1)} } } // 写法 3 // 1. 事件名必须是 update: + 属性名 // 2. 参数不能是表达式,最好是 data 里面的属性 <children :a.sync="a"></children> { props: ['a'] methods: { a() { this.$emit('update:a', 1)} } } 复制代码
⑤ 插槽
<template> <div> <!--默认插槽--> <slot></slot> <!--另一种默认插槽的写法--> <slot name="default"></slot> <!--具名插槽--> <slot name="footer"></slot> <!--传参插槽--> <slot v-bind:user="user" name="header"></slot> </div> </template> 复制代码
⑥ refs root parent children
组件获取组件实例,元素获取元素 根组件 父组件 子组件(所有的子组件,不保证顺序) 复制代码
⑦ project/inject 注入的值是非响应的
// 父组件 提供 project(){ return{ parent:this } } //子组件 注入 inject: ['parent'] inject: { parent: 'parent' } inject: { parent: { from:"parent", default:2 } }
作者:糖小雨
链接:https://juejin.cn/post/7019945353872932878