vue组件通信---父传子props、父传孙

props

一、概括

组件间通信基本原则:
1) 不要在子组件中直接修改父组件的状态数据

2) 数据在哪, 更新数据的行为(函数)就应该定义在哪

在通信中,无论是子组件向父组件传值还是父组件向子组件传值,他们都有一个共同点就是有中间介质,子向父的介质是自定义事件,父向子的介质是props中的属性。抓准这两点对于父子通信就好理解了。

所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。

额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。

注意:

1) 此方式用于父组件向子组件传递数据

2) 所有标签属性都会成为组件对象的属性, 模板页面可以直接引用

二、案例

案例:

第一步:在父组件中引入子组件

第二步:在父组件中的子标签定义属性变量

第三步:在子组件中定义props属性接收传来的值

第四步:在子组件中直接使用传来的值
parent.vue

<template>
    <div class="props-parent">
        <h1>父亲</h1>
        <input type="text" v-model.trim="msg" placeholder="请输入要传得值"> 
        <!--第二步 
            定义传递的变量msgg -->
        <child :msgg='msg'></child>
    </div>
</template>
<script>
/** 
 * 第一步
*/
import child from './child';//引入子组件并在components注册
export default {
    data() {
        return {
            msg:''
        }
    },
    components:{
        child
    }
}
</script>

child.vue

<template>
    <div class="props-child">
        <h1>孩子</h1>
        <!-- 第四步 -->
        <p>父组件传来的值为:{{msgg}}</p>
    </div>
</template>
<script>
export default {
    data() {
        return {

        }
    },
    /** 
     * 第三步
     * 定义props属性接收传来的值
    */
    // props: ['msg'],//方式一
    props:{//方式二,一旦这样定义必须传值过来
        // msgg: String,//定义数据类型
        // msgg: [String,Number],//多个可能的类型
        msgg:{
            type: String, //必填
            required: true,//必填
            default: 'muzidigbig' //默认值
        }
    }
}

</script>

方式二:this.$refs调用子组件的方法进行通讯

parent.vue

<template>
  <div class="fatherToChild">
    <h3>方式二:父组件调用子组件的方法进行传值</h3>
    <!--用ref给子组件起个名字-->
    <child ref="child"></child>
    <button @click.stop="clickFather">点击父组件</button>
  </div>
</template>
<script>
import child from "../../../components/child";
export default {
  name: "fatherToChild",
  components: {
    child
  },
  data() {
    return {
      msg: { id: 1, name: "muzidigbig", age: 23, sex: "男" }
    };
  },
  methods: {
    clickFather() {
      //调用子组件的方法,child是上边ref起的名字,emitEvent是子组件的方法。
      this.$refs.child.emitEvent(this.msg);
    }
  }
};
</script>

 child.vue

<template>
  <div class="child">
    <p v-if="msg1.id">{{msg1}}</p>
  </div>
</template>
<script>
export default {
  name: "child",
  data() {
    return {
      msg1: {}
    };
  },
  methods: {
    emitEvent(msg1) {
      this.msg1 = msg1;
      console.log(msg1); //接收的数据--------->我是父组件中的数据
    }
  }
};
</script>

 

provide和inject

一、概括

通常,当我们需要将数据从父组件传递到子组件时,我们使用 props。想象一下这样的结构:你有一些深嵌套的组件,而你只需要来自深嵌套子组件中父组件的某些内容。在这种情况下,你仍然需要将 prop 传递到整个组件链中,这可能会很烦人。对于这种情况,我们可以使用 provide 和 inject 对。父组件可以作为其所有子组件的依赖项提供程序,而不管组件层次结构有多深。这个特性有两个部分:父组件有一个 provide 选项来提供数据,子组件有一个 inject 选项来开始使用这个数据。

上面这段话出自官方,内容也比较好理解,就是通常数据传递一层,我们使用prop就可以很好的解决,如果传递多层,再使用prop就不是很好的方案,这时需要provide和inject

二、案例

 parent.vue

<template>
  <div class="provide-inject">
    <h3>provide-inject</h3>
    <div>
      <label for="name">姓名:</label>
      <input type="text" name="" v-model="name" placeholder="请输入名字" />
      <p>{{ name }}</p>
      <!-- 父传子 -->
      <inject :propName="name"></inject>
    </div>
  </div>
</template>

<script>
import Inject from "./components/inject.vue";

export default {
  components: {
    Inject,
  },
  data() {
    return {
      name: "木子",
    };
  },
  // 父组件中返回要传给下级的数据
  provide() {
    return {
      name: this.name,
    };
  },
};
</script>
<style scoped>
.provide-inject {
  background: pink;
}
</style>

 inject.vue    子

<template>
  <div>
    <p>props:--{{ propName }}</p>
    <inject01></inject01>
  </div>
</template>
<script>
import Inject01 from "./inject-01.vue";

export default {
  name: "inject",
  props: ["propName"],
  components: {
    Inject01,
  },
  data() {
    return {};
  },
};
</script>

inject.vue   孙

<template>
  <div>
    <p>inject-01:--{{ name }}</p>
  </div>
</template>
<script>
export default {
  name: "inject-01",
  //引用vue name
  inject: ["name"],
  data() {
    return {};
  },
};
</script>

实际上,你可以把依赖注入看作一部分“大范围有效的 prop”,除了:
祖先组件不需要知道哪些后代组件使用它提供的属性
后代组件不需要知道被注入的属性来自哪里

提示:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。

总结:

官方其实不推荐在应用程序代码中直接使用,因为数据追踪比较困难,不知道那一层级声明了 provide 又或是哪些层级使用了 inject 。造成比较大的维护成本。因此,除组件库或高阶插件外,Vue建议用Vuex解决或其他办法处理。
 

  • 5
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值