大家好,又见面了,我是你们的朋友全栈君。
父子组件传值 最常用的方法(4种)
1 . 父组件 传递数据 给子组件(props)vue官方文档
特别注意!!特别注意!!特别注意!!
props传值的类型如果是Object
类型,如对象,数组等,传递过去的是地址,在子组件中修改这些数据,会连带的把父组件中的值一并修改,强烈建议在子组件中深拷贝之后再使用这些值。然后使用$emit
的形式,将修改好的值再传递给父组件,这样数据就会以一种单向的,可预测的形式进行修改(如果不深拷贝,会造成数据被修改后,很难找到修改源头,非常恶心)
父组件
父组件,定义变量testText
,将这个变量传递给子组件
:testText
表示:子组件那边用testText
这个变量接收(这个可以随便怎么命名)
后面这个testText
表示:父组件要传给子组件的变量testText
<template>
<div>
parent-one
<childOne :testText="testText"></childOne>
</div>
</template>
<script> import childOne from "../components/child-one"; export default {
data() {
return {
testText: "这是一段传给子组件的文字", }; }, components: {
childOne, }, }; </script>
子组件
子组件使用props
接收,父组件传递过来的数据
props
的使用灵活性非常高
1.可以是数组(多个值,用逗号,
隔开)
props: ["testText"],
2.可以是对象(多个值,用逗号,
隔开)
props: {
testText: String,
// testText: [String, Array],
// testText: String || Array,
},
3.可以是对象,且对象属性也可以是对象,在对象中定义多种限制属性
type包括String
Number
Boolean
Array
Object
Date
Function
Symbol
props: {
testText: {
type: String,
default: "123",
validator: (value) => {
return ["success", "warning", "danger"].indexOf(value) !== -1;
},
},
},
<template>
<div>
{
{
this.testText}}
</div>
</template>
<script>
export default {
data() {
return {
};
},
props: {
testText: {
type: String,
default: "123",
validator: (value) => {
return ["success", "warning", "danger"].indexOf(value) !== -1;
},
},
},
};
</script>
2 . 在父组件中使用 $refs
调用子组件中的方法
步骤
1 . 给子组件定义一个ref
属性,并命名
2 . this.$refs.属性名.子组件方法()
的形式调用,也可以向子组件函数中传递参数
(需要注意的是,如果子组件使用了v-for,那么this.$refs
会得到一个数组)
父组件
<template>
<div>
parent-one
<button @click="handle_parent">触发子组件事件</button>
<childOne ref="childOne"></childOne>
</div>
</template>
<script>
import childOne from "../components/child-one";
export default {
methods: {
handle_parent() {
const arr = [1, 2, 3];
this.$refs.childOne.handle_child_one(arr);
},
},
components: {
childOne,
},
};
</script>
子组件
<template>
<div></div>
</template>
<script>
export default {
methods: {
handle_child_one(value) {
console.log("子组件child_one中的事件被触发了");
},
},
};
</script>
3 . 父组件使用 $children 调用子组件中的方法
注意:this.$children
获取的是子组件数组
如果父组件中只定义了一个子组件,那么要使用this.$children[0].子组件方法()
调用子组件中的方法
如果父组件中定义了多个子组件,【$children
并不保证顺序,也不是响应式的】
而且如果一个父组件中,注册了很多个子组件的话,使用数组下标的方式定位子组件,会造成代码理解成本高,难以维护等问题,所以个人感觉这个方法比较鸡肋
<template>
<div>
parent-one
<button @click="handle_parent">触发子组件事件</button>
<childOne ref="childOne"></childOne>
<childTwo></childTwo>
</div>
</template>
<script>
import childTwo from "../components/child-two";
import childOne from "../components/child-one";
export default {
methods: {
handle_parent() {
this.$children[0].handle_child_one();
},
},
components: {
childTwo,
childOne,
},
};
</script>
4 . 子组件使用 $parent 调用父组件中的函数或者属性
和$children
不同,$parent
获取的不是数组,而是一个父组件实例
因为:父组件中可以有很多个不同子组件
但是:子组件在同一个父组件中,只能存在一个,或者说一种,无论v-for
多少个子组件,这些子组件都还是在同一个父组件中,所以在哪个父组件中引入子组件,$parent
直接就指向该父组件
(所以形式上,$parent
要比$children
好用)
子组件
<template>
<div>
这是子组件1
<button @click="handle_parent">调用父组件</button>
</div>
</template>
<script>
export default {
methods: {
handle_parent(){
// 调用父组件中的 apply_children 函数
this.$parent.apply_children()
}
},
};
</script>
而且因为this.$parent
是直接获取父组件实例,所以可以通过this.$parent.父组件属性||父组件方法
直接修改父组件中data
中的值
5 . 子组件使用 $emit 调用父组件中的方法
老生常谈,没啥花里胡哨的,就是一个 子组件 向 父组件 通讯的方法
有两个参数,一个是 【父组件的函数名】
(准确说不是父组件函数名,而是子组件在父组件中定义在子组件身上的函数名,文字比较绕,看代码吧),另一个是要传递给父组件的【参数】
,注意看官方文档,函数名是个字符串,记得带上引号
父组件
<template>
<div>
parent-one
// 这个 @apply-children 就是子组件需要触发的事件
<childOne ref="childOne" @apply-children="testchildren"></childOne>
</div>
</template>
<script>
import childOne from "../components/child-one";
export default {
methods: {
testchildren(value) {
console.log("父组件parent-one中的方法被调用了");
console.log("子组件传过来的参数:" + value);
},
},
components: {
childOne,
},
};
</script>
子组件
<template>
<div>
这是子组件1
<button @click="handle_parent">调用父组件</button>
</div>
</template>
<script>
export default {
methods: {
handle_parent() {
this.$emit("apply-children",'123');
},
},
};
</script>
$emit | $parent |
---|---|
子组件向父组件通讯 | 子组件向父组件通讯 |
父子通讯常用(推荐使用) | 访问组件的应急方法(应急使用) |
父子通讯常用(推荐使用) | 该子组件定义在多个父组件中时,虽然vue知道定义在哪个父组件,但是开发人员不是很清楚,不利于代码的维护,且 访问组件之外的上下文违反了基于模块开发的第一原则,所以我们要尽量避免使用$parent |
$emit 需要触发绑定函数,子组件需要绑定一个供触发的函数 | 不需要任何绑定,本质是直接获取父组件实例,可以直接调用父组件中的函数、属性 |
6 . 子(孙)组件使用 $attr 获取父(子)组件传递过来的参数
使用场景:父、子、孙三个组件相继传值,父组件希望把值传给孙子组件,但是又不想向vuex
里面添加数据时使用(当然,父子组件传值也是可以用的)
父组件
在父组件中定义两个变量,分别传给子组件,孙子组件
<template>
<div>
parent-one
<childOne :parent_to_child="parent_to_child" :parent_to_grand="parent_to_grand"></childOne>
</div>
</template>
<script>
import childOne from "../components/child-one";
export default {
data() {
return {
parent_to_child: "这是一段父组件传递给子组件的数据",
parent_to_grand: "这是一段父组件传递给子组件的数据",
};
},
components: {
childOne,
},
};
</script>
子组件
在子组件中打印一下this.$attrs
<template>
<div>
这是子组件1
<grandOne v-bind="$attrs"></grandOne>
</div>
</template>
<script>
import grandOne from "./componentsGrand/grand-one";
export default {
mounted() {
console.log(this.$attrs);
},
components: {
grandOne,
},
};
</script>
注意:根据官方文档,这里有个注意点用大白话说就是,this.$attrs
只包含【父组件传递过来的变量,减去,props
的数据】,现在我们给子组件加上props
接收一个数据,其他代码不变
export default {
props: ["parent_to_grand"],
mounted() {
console.log(this.$attrs);
},
components: {
grandOne,
},
};
再打印一下this.$attrs
,会减去props
中接受的属性
如果希望将参数传递给孙组件,需要在【子组件中的孙组件标签】上加上v-bind="$attrs"
<grandOne v-bind="$attrs"></grandOne>
孙组件 再使用this.$attrs
获取 父组件 传递过来的参数,其中会自动过滤掉被 子组件 props
获取过的属性
孙组件
<template>
<div>
孙子组件1
</div>
</template>
<script>
export default {
data() {
return {
};
},
mounted() {
console.log(this.$attrs);
},
};
</script>
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/145426.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...