vue 父子组件传值

比眉伴天荒 2023-01-16 02:43 407阅读 0赞

父子组件传值 最常用的方法(4种)

在这里插入图片描述

1 . 父组件 传递数据 给子组件(props)vue官方文档

特别注意!!特别注意!!特别注意!!
props传值的类型如果是Object类型,如对象,数组等,传递过去的是地址,在子组件中修改这些数据,会连带的把父组件中的值一并修改,强烈建议在子组件中深拷贝之后再使用这些值。然后使用$emit的形式,将修改好的值再传递给父组件,这样数据就会以一种单向的,可预测的形式进行修改(如果不深拷贝,会造成数据被修改后,很难找到修改源头,非常恶心)

父组件
父组件,定义变量testText,将这个变量传递给子组件
:testText表示:子组件那边用testText这个变量接收(这个可以随便怎么命名)
后面这个testText表示:父组件要传给子组件的变量testText

  1. <template>
  2. <div>
  3. parent-one
  4. <childOne :testText="testText"></childOne>
  5. </div>
  6. </template>
  7. <script> import childOne from "../components/child-one"; export default { data() { return { testText: "这是一段传给子组件的文字", }; }, components: { childOne, }, }; </script>

子组件
子组件使用props接收,父组件传递过来的数据
props的使用灵活性非常高

1.可以是数组(多个值,用逗号,隔开)

  1. props: ["testText"],

2.可以是对象(多个值,用逗号,隔开)

  1. props: {
  2. testText: String,
  3. // testText: [String, Array],
  4. // testText: String || Array,
  5. },

3.可以是对象,且对象属性也可以是对象,在对象中定义多种限制属性
type包括String Number Boolean Array Object Date Function Symbol

  1. props: {
  2. testText: {
  3. type: String,
  4. default: "123",
  5. validator: (value) => {
  6. return ["success", "warning", "danger"].indexOf(value) !== -1;
  7. },
  8. },
  9. },
  10. <template>
  11. <div>
  12. { { this.testText}}
  13. </div>
  14. </template>
  15. <script>
  16. export default {
  17. data() {
  18. return { };
  19. },
  20. props: {
  21. testText: {
  22. type: String,
  23. default: "123",
  24. validator: (value) => {
  25. return ["success", "warning", "danger"].indexOf(value) !== -1;
  26. },
  27. },
  28. },
  29. };
  30. </script>

2 . 在父组件中使用 $refs 调用子组件中的方法

步骤
1 . 给子组件定义一个ref属性,并命名
2 . this.$refs.属性名.子组件方法()的形式调用,也可以向子组件函数中传递参数
(需要注意的是,如果子组件使用了v-for,那么this.$refs会得到一个数组)

父组件

  1. <template>
  2. <div>
  3. parent-one
  4. <button @click="handle_parent">触发子组件事件</button>
  5. <childOne ref="childOne"></childOne>
  6. </div>
  7. </template>
  8. <script>
  9. import childOne from "../components/child-one";
  10. export default {
  11. methods: {
  12. handle_parent() {
  13. const arr = [1, 2, 3];
  14. this.$refs.childOne.handle_child_one(arr);
  15. },
  16. },
  17. components: {
  18. childOne,
  19. },
  20. };
  21. </script>

子组件

  1. <template>
  2. <div></div>
  3. </template>
  4. <script>
  5. export default {
  6. methods: {
  7. handle_child_one(value) {
  8. console.log("子组件child_one中的事件被触发了");
  9. },
  10. },
  11. };
  12. </script>

3 . 父组件使用 $children 调用子组件中的方法

注意:this.$children获取的是子组件数组

如果父组件中只定义了一个子组件,那么要使用this.$children[0].子组件方法()调用子组件中的方法
如果父组件中定义了多个子组件,【$children并不保证顺序,也不是响应式的】

而且如果一个父组件中,注册了很多个子组件的话,使用数组下标的方式定位子组件,会造成代码理解成本高,难以维护等问题,所以个人感觉这个方法比较鸡肋

  1. <template>
  2. <div>
  3. parent-one
  4. <button @click="handle_parent">触发子组件事件</button>
  5. <childOne ref="childOne"></childOne>
  6. <childTwo></childTwo>
  7. </div>
  8. </template>
  9. <script>
  10. import childTwo from "../components/child-two";
  11. import childOne from "../components/child-one";
  12. export default {
  13. methods: {
  14. handle_parent() {
  15. this.$children[0].handle_child_one();
  16. },
  17. },
  18. components: {
  19. childTwo,
  20. childOne,
  21. },
  22. };
  23. </script>

4 . 子组件使用 $parent 调用父组件中的函数或者属性

在这里插入图片描述
$children不同,$parent获取的不是数组,而是一个父组件实例
因为:父组件中可以有很多个不同子组件
但是:子组件在同一个父组件中,只能存在一个,或者说一种,无论v-for多少个子组件,这些子组件都还是在同一个父组件中,所以在哪个父组件中引入子组件,$parent直接就指向该父组件
(所以形式上,$parent要比$children好用)

子组件

  1. <template>
  2. <div>
  3. 这是子组件1
  4. <button @click="handle_parent">调用父组件</button>
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. methods: {
  10. handle_parent(){
  11. // 调用父组件中的 apply_children 函数
  12. this.$parent.apply_children()
  13. }
  14. },
  15. };
  16. </script>

而且因为this.$parent是直接获取父组件实例,所以可以通过this.$parent.父组件属性||父组件方法直接修改父组件中data中的值

5 . 子组件使用 $emit 调用父组件中的方法

老生常谈,没啥花里胡哨的,就是一个 子组件 向 父组件 通讯的方法
在这里插入图片描述
有两个参数,一个是 【父组件的函数名】(准确说不是父组件函数名,而是子组件在父组件中定义在子组件身上的函数名,文字比较绕,看代码吧),另一个是要传递给父组件的【参数】,注意看官方文档,函数名是个字符串,记得带上引号

父组件

  1. <template>
  2. <div>
  3. parent-one
  4. // 这个 @apply-children 就是子组件需要触发的事件
  5. <childOne ref="childOne" @apply-children="testchildren"></childOne>
  6. </div>
  7. </template>
  8. <script>
  9. import childOne from "../components/child-one";
  10. export default {
  11. methods: {
  12. testchildren(value) {
  13. console.log("父组件parent-one中的方法被调用了");
  14. console.log("子组件传过来的参数:" + value);
  15. },
  16. },
  17. components: {
  18. childOne,
  19. },
  20. };
  21. </script>

子组件

  1. <template>
  2. <div>
  3. 这是子组件1
  4. <button @click="handle_parent">调用父组件</button>
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. methods: {
  10. handle_parent() {
  11. this.$emit("apply-children",'123');
  12. },
  13. },
  14. };
  15. </script>

























$emit $parent
子组件向父组件通讯 子组件向父组件通讯
父子通讯常用(推荐使用) 访问组件的应急方法(应急使用)
父子通讯常用(推荐使用) 该子组件定义在多个父组件中时,虽然vue知道定义在哪个父组件,但是开发人员不是很清楚,不利于代码的维护,且 访问组件之外的上下文违反了基于模块开发的第一原则,所以我们要尽量避免使用$parent
$emit 需要触发绑定函数,子组件需要绑定一个供触发的函数 不需要任何绑定,本质是直接获取父组件实例,可以直接调用父组件中的函数、属性

6 . 子(孙)组件使用 $attr 获取父(子)组件传递过来的参数

在这里插入图片描述
使用场景:父、子、孙三个组件相继传值,父组件希望把值传给孙子组件,但是又不想向vuex里面添加数据时使用(当然,父子组件传值也是可以用的)

父组件
在父组件中定义两个变量,分别传给子组件,孙子组件

  1. <template>
  2. <div>
  3. parent-one
  4. <childOne :parent_to_child="parent_to_child" :parent_to_grand="parent_to_grand"></childOne>
  5. </div>
  6. </template>
  7. <script>
  8. import childOne from "../components/child-one";
  9. export default {
  10. data() {
  11. return {
  12. parent_to_child: "这是一段父组件传递给子组件的数据",
  13. parent_to_grand: "这是一段父组件传递给子组件的数据",
  14. };
  15. },
  16. components: {
  17. childOne,
  18. },
  19. };
  20. </script>

子组件
在子组件中打印一下this.$attrs

  1. <template>
  2. <div>
  3. 这是子组件1
  4. <grandOne v-bind="$attrs"></grandOne>
  5. </div>
  6. </template>
  7. <script>
  8. import grandOne from "./componentsGrand/grand-one";
  9. export default {
  10. mounted() {
  11. console.log(this.$attrs);
  12. },
  13. components: {
  14. grandOne,
  15. },
  16. };
  17. </script>

在这里插入图片描述
注意:根据官方文档,这里有个注意点用大白话说就是,this.$attrs只包含【父组件传递过来的变量,减去,props的数据】,现在我们给子组件加上props接收一个数据,其他代码不变

  1. export default {
  2. props: ["parent_to_grand"],
  3. mounted() {
  4. console.log(this.$attrs);
  5. },
  6. components: {
  7. grandOne,
  8. },
  9. };

再打印一下this.$attrs,会减去props中接受的属性
在这里插入图片描述
如果希望将参数传递给孙组件,需要在【子组件中的孙组件标签】上加上v-bind="$attrs"

  1. <grandOne v-bind="$attrs"></grandOne>

孙组件 再使用this.$attrs获取 父组件 传递过来的参数,其中会自动过滤掉被 子组件 props 获取过的属性

孙组件

  1. <template>
  2. <div>
  3. 孙子组件1
  4. </div>
  5. </template>
  6. <script>
  7. export default {
  8. data() {
  9. return { };
  10. },
  11. mounted() {
  12. console.log(this.$attrs);
  13. },
  14. };
  15. </script>

发表评论

表情:
评论列表 (有 0 条评论,407人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Vue父子组件

    Vue父子组件传值:有四种方式:props,ref,emit 和模板传递通信slot 通过props来传值: 静态传值就是直接通过props来传递 动态传值是通