vue自定义组件之父子通信和子父通信

81 阅读1分钟

父组件的数据写在标签中,子组件利用props接收,并且可以加上传入的限制。由于:绑定是单向的,所以后续父组件修改变量,子组件中的数据也会相应改变。

<comp-a c="1" d="2"></comp-a>
<comp-b
    :count="count"
    :num="1"
    :str2="'hello'"
    :bool="true"
    :a="null"
    :b="undefined"
    :arr="[1,2,3]"
    :obj="{a:1,b:2}"
    :data-id="100"
    :data-option-id="200"
></comp-b>


 let compB = {
      props: {
        // 对象的键名就是要接受的属性名  => 对应属性名接收数据
        // 对象的健值就是需要接收的数据的类型  => 如果接收的数据不是指定类型会报错
        num: {
          type: Number, // 接收数据的类型
          required: true, // 必填
        },
        str2: String,
        bool: {
          type: Boolean,
          default: false, //默认值
        },
        a: null,
        b: undefined,
        arr: Array,
        obj: Object,
        // "data-id": Number,
        dataId: Number,
        dataOptionId: Number,
        count: {
          // type: Number,
          // 自定义验证函数  => 接收数据后,或先执行验证函数,如果函数返回true -> 验证成功,false->验证失败
          validator: function (value) {
            console.log("value", value);
            if (!value) return false; // 必填

            if (typeof value == "number") {
              // 类型
              if (value >= 0 && value <= 100 && value % 1 == 0) {
                return true;
              } else {
                return false;
              }
            } else {
              return false;
            }
          },
        },
      },

那么问题来了,如果子组件想要修改父元素的数据,如果实现呢?

子父通信

  • 父组件需要提供数据count,以及自定义事件update:count,和对应的事件触发函数。如果子组件用emit触发了事件uodate:count,那么父组件就会自己执行对应的函数
<div id="app">
      <p>{{count}}</p>
      <button @click="count++">父控子</button>
      <comp-a :count1="count" @update:count="updateCountHanlder"></comp-a>
    </div>
  </body>
  <script>
    let compA = {
      props: ["count1"],
      template: `<div class="compA">
        <p>{{count1}}</p>
      <input
        type="button"
        value="子控父"
        @click="$emit('update:count',count1)"
      />
    </div>`,
    };

    let app = new Vue({
      el: "#app",
      data: {
        count: 1,
      },
      methods: {
        updateCountHanlder(val) {
          this.count = val + 1;
        },
      },
      components: {
        "comp-a": compA,
      },
    });
  </script>
</html>



针对于子父通信,我们可以选择sync简写,这个是vue2专用的。

使用时: :参数.sync='变量'

默认绑定自定义事件: @update:参数="(v)=> 变量 = v"

简单来说,加了.sync之后,可以省略 @update:count="updateCountHanlder",因为vue会自动将自定义事件和对应的函数绑定起来,函数的内容默认是将接收的值赋值给父组件的元素,另外自定义事件的名字也是固定的,不可以乱改。

<body>
    <div id="app">
      <p>{{count}}</p>
      <button @click="count++">父控子</button>
      <comp-a :count1.sync="count"></comp-a>
    </div>
  </body>
  <script>
    let compA = {
      props: ["count1"],
      template: `<div class="compA">
        <p>{{count1}}</p>
      <input
        type="button"
        value="子控父"
        @click="$emit('update:count1',count1+1)"
      />
    </div>`,
    };

    let app = new Vue({
      el: "#app",
      data: {
        count: 1,
      },
      methods: {
        // updateCountHanlder(val) {
        //   this.count = val;
        // },
      },
      components: {
        "comp-a": compA,
      },
    });
  </script>
</html>