vue 组件间的通信

props && 自定义方法

props 传数据给子组件使用 Vue 中父组件到子组件的通信主要由子组件的 props 属性实现。
这是最简单也是最原始的自定义事件传给自组件修改自己的 data
但是必须结合

  • 使用 $emit 接收执行父组件传方法和 props

parent.vue

<template>
  <div>
    <div>父组件的数据 number :{{ number }}</div>
    <!-- change-number 是子组件接收的事件名, changNumber 是父组件的事件名 -->
    <Son :number="number" @change-number="changeNumber" />
  </div>
</template>
<script>
  export default {
    data() {
      return {
        number: 1000,
      };
    },
    methods: {
      changeNumber(number) {
        this.number = number;
      },
    },
  };
</script>

Son.vue

<template>
  <div>
    <div>子组件展示父组件的数据 number :{{ number }}</div>
    <!-- 自定义事件 -->
    <button @click="$emit('change-number', 2000)">点击修改</button>
  </div>
</template>
<script>
  export default {
    props: {
      number: {
        type: Number,
      },
    },
    methods: {
      // v-model
      handle() {
        this.$emit("input", 1234);
      },
    },
  };
</script>
.sync

parent.vue

<template>
  <div>
    <!-- 简化父组件定义方法传递子组件调用  -->
    <!-- .sync 语法糖 .sync 是修饰符 -->
    <!-- 其实子组件不需要展示 number 的话可以不传 :number="number"  -->
    <!-- 组件名是 update 也可以是 update:number $event 是子组件传过来的参数  -->
    <Son :number="number" @update:number="number = $event" />
    <Son :number="number" @update="number = $event" />
    <!-- .sync 简写的方式 -->
    <Son :number.sync="number" />
    <!-- 传对象 -->
    <Son v-bind.sync="obj" />
  </div>
</template>
<script>
  export default {
    data() {
      return {
        number: 1000,
        obj: {
          a: 100,
          b: 200,
        },
      };
    },
  };
</script>

Son.vue

<template>
  <div>
    <div>子组件展示父组件的数据 number :{{ number }}</div>
    <!-- .sync -->
    <div>子组件展示父组件的数据 obj.a :{{ a }}</div>
    <div>子组件展示父组件的数据 obj.b :{{ b }}</div>

    <!-- .sync 语法糖 -->
    <!-- 传单个值 -->
    <button @click="$emit('update:number', 20)">点击修改</button>
    <button @click="$emit('update', 20)">点击修改</button>
    <!-- 传多个值或者对象 -->
    <button @click="$emit('update:a', 22)">点击修改 a</button>
    <button @click="$emit('update:b', 23)">点击修改 b</button>
  </div>
</template>
<script>
  export default {
    props: {
      number: {
        type: Number,
      },
      a:{
      	type:Number,
      }
      b:{
      	type:Number,
      }
    },
  };
</script>
v-model

parent.vue

<template>
  <div>
    <!-- v-model -->
    <!-- 有区别的就是 子组件接收要使用 value 接收 -->
    <Son :value="number" @input="number = $event" />
    <!-- 简写 -->
    <Son v-model="number" />
  </div>
</template>
<script>
  export default {
    data() {
      return {
        number: 1000,
      };
    },
  };
</script>

Son.vue

<template>
  <div>
    <!-- v-model -->
    <button @click="$emit('input',666)">修改 number</button>
    <button @click="handle">修改 number</button>
  </div>
</template>
<script>
  export default {
    methods: {
      // v-model
      handle() {
        this.$emit("input", 1234);
      },
    },
  };
</script>
$parent

父组件

<script>
  export default {
    data() {
      return {
        number: 1000,
      };
    },
  };
</script>

子组件

<!-- $parent && $children -->
<button @click="$parent.number = 888">点击修改 $parent 888</button>
provide && inject
  • 什么是 provide && inject
    provide/inject 需要一起使用,允许一个祖先组件向其所有子孙后代注入一个依赖 provide,不论组件层次有多深,子组件都能用 inject 接收的到父组件的数据, 并在起上下游关系成立的时间里始终生效。
  • provide 和 inject 只有父子孙组件之间才可以拿到。

总结
provide/inject 提供了一种新的组件间通信的方法。它允许父组件向子孙组件间进行跨层级的数据分发。但是 provide/inject 是非响应式的,如果要子孙组件根据父组件的值进行改变,provide/inject 机制不是一个好的选择。此时可以使用 Vuex 来管理状态。

  1. 在父组件中使用 provide(函数),写下数据
  provide() {
      x: 12,
  },
  1. 在子组件中通过 inject(数组),拿到需要的父组件中的数据,使用数据的时候,等同于 data 里的数据使用方法。
inject: ["x"];
  1. provide 提供的数据是不可响应的
  2. 如果想提供响应数据,可以将数据做成响应的 Vue.abservable 或者 vuex
  3. 当需要提供的数据并不是直接在父组件 data 内写死的,需要在 created 或者 mounted 生命周期钩子内获取,那么直接提供是不行的。
  4. 此时需要提供一个方法,在父组件内定义一个方法,该方法返回需要的数据。然后将此方法当做 provide 提供的。
  5. 我们也可以将修改父组件的方法传递给子组件修改。
// Parent.vue

<div>父组件 provide 数据:{{ Obj.name }}</div>
<button @click="Obj.name = '小琴'">父组件修改</button>
<Son />

  data() {
    return {
      Obj: null,
    };
  }
    created() {
    this.Obj = { name: "小五" };
  },
  methods: {
    // ProObj() {
    //   return this.Obj;
    // },
  }
// 想要把父组件的数据传递必须要写成函数形式
  provide() {
    return {
      x: 12,
    };
  },
  provide() {
    return {
      // getObj: this.ProObj,
      getObj: () => this.Obj,
      setObj: (name) => (this.Obj.name = name),
    };
  },



//子组件 Son.vue

<div>子组件展示父组件的数据 provide {{ getObj().name }}</div>
<button @click="setObj('小义')">子组件修改</button>

// 把从父组件接收过来的值
inject: ["getObj", "setObj"],

这里是引用

$attrs && $listeners
  1. 是什么
  • $attrs 存储传递变量
  • $listeners 存储传递事件
  1. 怎么用
  • 通过父组件传递给子组件,子组件属性方法自动接收

  • $props比较, $props 必须在组件中注册了props才能用拿到值,所以在嵌套层级比较深的组件中$attrs拿值更加便捷

  • 只能父组件传递给子组件,子组件不能修改。

  • 不会传递 props 声明的数据,和不含 .native 事件修饰符的事件。

  • App.vue

<template>
  <div>
    <Parent2
      :age="age"
      :obj="{ name: '小五' }"
      @look="() => console.log(1)"
      @click="handle"
    />
    <button @click="handle">点击</button>
  </div>
</template>

<script>
  import Parent2 from "./components/Parent2";
  export default {
    name: "App",
    components: {
      Parent2,
    },
    data() {
      return {
        age: 1,
      };
    },
    created() {
      this.age = 666;
      console.log("父组件的 age", this.age);
    },
    methods: {
      handle() {
        this.age = 999;
      },
    },
  };
</script>
  • Parent.vue
<template>
  <div>
    <div>父组件</div>
    <Son2 v-bind="$attrs" v-on="$listeners" />
  </div>
</template>

<script>
  import Son2 from "./Son2";
  export default {
    name: "Parent2",
    components: {
      Son2,
    },
    created() {
      // console.log(this);
      console.log(this.$attrs); //存储变量 age:666  obj: {name: "小五"}
      console.log(this.$listeners); // 存储事件 {look: ƒ, click: ƒ}
    },
  };
</script>
  • Son.vue
<template>
  <div>
    <div>子组件</div>
  </div>
</template>

<script>
  export default {
    name: "Son2",
    data() {
      return {
        a: 2,
      };
    },
    created() {
      console.log("子组件的变量", this.$attrs); // age:666  obj: {name: "小五"}
      console.log("子组件事件", this.$listeners); // {look: ƒ, click: ƒ}
      this.$attrs.age = this.a; //改变 $attrs 的值
      console.log(this.a); // 2
      console.log("子组件的变量", this.$attrs); // age:2  obj: {name: "小五"}
    },
  };
</script>

<style></style>
.native

解释:.native是给一个组件的根元素绑定一个原生的事件
例子:

<header @click.native></header>
<Home @click.native></Home>
<router-link @click.native="handle" tag="a" exact to="/?tab=all"></router-link>
<!-- 错误的写法 <header @number.native></header>  必须是原生的事件 click moussenter 等等才行-->

事件修饰符 .native 的作用是给组件的根元素的 dom 节点绑定事件 什么叫根元素(组件下的大儿子。例如: Li.vue 下的 <li></li> )
注释:@moussenter.native="change(0)" 找到 Li 组件的根元素(<li></li>)绑定原生的事件 @moussenter 滑过的时候执行

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值