vueJs父子组件通信

父子组件通信

  • 子组件是不能引用父组件或者Vue实例的数据的。
  • 但是,在开发中,往往一些数据确实需要从上层传递到下层:
  • 比如在一个页面中,我们从服务器请求到了很多的数据。
  • 其中一部分数据,并非是我们整个页面的大组件来展示的,而是需要下面的子组件进行展示。
  • 这个时候,并不会让子组件再次发送一个网络请求,而是直接让大组件(父组件)将数据传递给小组件(子组件)。
    如何进行父子组件间的通信呢?Vue官方提到
    • 通过props向子组件传递数据
    • 通过事件向父组件发送消息

06

父组件向子组件传递函数(props)

props的值有两种方式:

  • 方式一:字符串数组,数组中的字符串就是传递时的名称。
  • 方式二:对象,对象可以设置传递时的类型,也可以设置默认值等
  • 具体下面代码展示
<body>
    <div id="app">
      <cpn :cmessage="message" :cmovies="movies"></cpn>
    </div>
    <template id="cpn">
      <div>
        <ul>
          <li v-for="item in cmovies">{{item}}</li>
        </ul>
        <h2>{{cmessage}}</h2>
      </div>
    </template>
    <script src="../vue.js"></script>
    <script>
      // 父传子:props
      const cpn = {
        template: "#cpn",
        props: {
          //1.类型限制
          // 2.提供一些默认值,以及必传值

          cmovies: {
            type: Array,
            default() {
              return [];
            },
          },
          cmessage: {
            type: String,
            default: "aaaaaa",
            required: true,
          },
        },
      };
      const app = new Vue({
        el: "#app",
        data: {
          message: "你好啊",
          movies: ["你好", "海贼王", "悲伤逆流成河"],
        },
        components: {
          cpn,
        },
      });
    </script>
  </body>

props数据验证

在前面,我们的props选项是使用一个数组。
我们说过,除了数组之外,我们也可以使用对象,当需要对props进行类型等验证时,就需要对象写法了。
验证都支持哪些数据类型呢?
String
Number
Boolean
Array
Object
Date
Function
Symbol
当我们有自定义构造函数时,验证也支持自定义的类型

子组件向父组件传递($emit)

props用于父组件向子组件传递数据,还有一种比较常见的是子组件传递数据或事件到父组件中。
我们应该如何处理呢?这个时候,我们需要使用自定义事件来完成。
什么时候需要自定义事件呢?

  • 当子组件需要向父组件传递数据时,就要用到自定义事件了。
  • 我们之前学习的v-on不仅仅可以用于监听DOM事件,也可以用于组件间的自定义事件。
    自定义事件的流程:
    • 在子组件中,通过$emit()来触发事件。
    • 在父组件中,通过v-on来监听子组件事件。
    • 我们来看一个简单的例子:
    • 两个按钮+1和-1,点击后修改counter。
    • 我们整个操作的过程还是在子组件中完成,但是之后的展示交给父组件。
      这样,我们就需要将子组件中的counter,传给父组件的某个属性,比如total。
<body>
    <div id="app">
      <cpn @item-click="cpnClick"></cpn>
    </div>
    <template id="cpn">
      <div>
        <button v-for="item in categories" @click="btnClick(item)">
          {{item.name}}
        </button>
      </div>
    </template>
    <script src="../vue.js"></script>
    <script>
      const cpn = {
        template: "#cpn",
        data() {
          return {
            categories: [
              { id: "aaa", name: "热门推荐" },
              { id: "bbb", name: "手机数码" },
              { id: "ccc", name: "家用家电" },
              { id: "ddd", name: "电脑办公" },
            ],
          };
        },
        methods: {
          btnClick(item) {
            //   发射事件:自定义事件
            this.$emit("item-click", item);
          },
        },
      };
      //   2.父组件
      const app = new Vue({
        el: "#app",
        data: {
          message: "你好啊",
        },
        components: {
          cpn,
        },
        methods: {
          cpnClick(item) {
            console.log("cpnClick", item);
          },
        },
      });
    </script>
  </body>
父子组件的访问方式

有时候我们需要父组件直接访问子组件,子组件直接访问父组件,或者是子组件访问根组件。

  • 父组件访问子组件:使用$children或$refs

    $children的缺陷:

    • 通过$children访问子组件时,是一个数组类型,访问其中的子组件必须通过索引值。
      但是当子组件过多,我们需要拿到其中一个时,往往不能确定它的索引值,甚至还可能会发生变化。
      有时候,我们想明确获取其中一个特定的组件,这个时候就可以使用$refs

      $refs的使用:
      $refs和ref指令通常是一起使用的。

    • 首先,我们通过ref给某一个子组件绑定一个特定的ID。

    • 其次,通过this.$refs.ID就可以访问到该组件了。

     <body>
        <div id="app">
          <cpn ref="aaa"></cpn>
          <cpn></cpn>
          <cpn></cpn>
          <button @click="btnClick">按钮</button>
        </div>
        <template id="cpn">
          <div>我是子组件</div>
        </template>
        <script src="../vue.js"></script>
        <script>
          const app = new Vue({
            el: "#app",
            data: {
              message: "你好啊",
            },
            methods: {
              btnClick() {
                // console.log(this.$children);
                // for (let c of this.$children) {
                //   console.log(c.name);
                //   c.showMessage();
                // }
                // console.log(this.$children[0].showMessage);
                console.log(this.$refs);
                console.log(this.$refs.aaa.name);
              },
            },
            components: {
              cpn: {
                template: "#cpn",
                data() {
                  return {
                    name: "我是子组件的name",
                  };
                },
                methods: {
                  showMessage() {
                    console.log("showMessage");
                  },
                },
              },
            },
          });
        </script>
      </body>
    
  • 子组件访问父组件:使用$parent

    • 尽管在Vue开发中,我们允许通过$parent来访问父组件,但是在真实开发中尽量不要这样做。

    • 子组件应该尽量避免直接访问父组件的数据,因为这样耦合度太高了。

    • 如果我们将子组件放在另外一个组件之内,很可能该父组件没有对应的属性,往往会引起问题。

    • 另外,更不好做的是通过$parent直接修改父组件的状态,那么父组件中的状态将变得飘忽不定,很不利于我的调试和维护。

posted @ 2021-11-05 08:48  .爬行的蜗牛  阅读(61)  评论(0编辑  收藏  举报
Document