南辞派

导航

Vue-组件间的通信方式

有时候我们在操作组件实现功能时,存在数据之间的传递,这就是组件间的通信

组件间的数据传递

1.组件间的通信----父传子

父传子的通信是通过父组件传递数据,然后子组件通过自身属性prop来进行接收数据,做相应的处理实现的.

方法:通过子组件的props属性进行传递.
props属性设置数据内容变量的定义方式有两种方式:
方式一:

字符串数组类型,数组中的字符串就是用于接收父组件所传数据的自定义变量名称(这种方式不常用)
​ props:['自定义存储变量名1','自定义存储变量名2',...]

​ 方式二:

对象类型,使用对象类型的定义方式我们可以设置父组件传递数据的类型,也可以设置自定义存储变量名的默认值等(推荐使用这种方式)
​ props:{

​ // 普通数据传递(字符串、数字,布尔值等)

​ 自定义存储变量名1:{
​ type: xxx //规定父组件传递的数据必须是什么类型
​ default: xxx //规定父组件没有传递数据时该变量的默认值.
​ required:布尔值 //规定该属性是否必须传递数据
​ },

​ // 数组或对象类型数据传递

​ 自定义存储变量名2:{
​ type:Array/Object,
​ default:function(){ //当设置的类型为数组或者对象时,默认值这里必须是一个函数,通过函数的返回值来设置默认值
​ return [...]/{...}
​ },
​ required:布尔值
​ }

}

实现步骤:

(1)创建一对父、子组件。
(2)在父组件的data属性中准备需要传递的数据;在子组件的props属性中设置一个变量用于接收父组件的数据。
(3)在使用自定义组件时,在组件名称上通过v-bind绑定子组件的props属性中的变量名,值为父组件中的数据变量名。(这里数据就实现了数据信息的传递工作)
<组件名 v-bind:子组件自定义存储变量名="父组件数据变量名"></组件名>
(4)在子组件的html实现功能template模板中使用props属性中设置的相应的自定义变量(这里就是使用从父组件获取到的数据)

案例:

// 实例控制区域
<div id="app">
    // 使用组件
    <Cpn :userinfo="user"></Cpn>
</div>

// 组件功能实现模板
<template id="tempCpn">
	<div>
        <h1>
            管理员信息
        </h1>
        <ul>
            <li v-for="item in userinfo">{{item}}</li>
        </ul>
    </div>
</template>

// 实例对象与组件
const Cpn={ // 创建组件
	template:"#tempCpn", // 关联组件功能模板
	props:{ // 通过props属性管理父组件传递的数据
		usrinfo:{
			type:Object, // 规定父组件传递的数据必须为对象类型
			required:false, // 规定该数据为非必传项
			default(){
				return {
					name:'董事长',
					sex:'男',
				}
			}
		}
	}
}

// 创建Vue实例对象(父组件)
const app=new Vue({
	el:'#app',
	data:{
		user:{
			name:"江小白",
			sex:"女",
			age:20,
			address:'江苏杭州'
		}
	},
	components:{ // 注册子组件
		Cpn:Cpn,
	}
})

2.组件间的通信----子传父

子传父的通信是通过子组件自定义事件进行的(即传递一个事件,然后通过函数传参实现)

实现方法:

子组件向父组件中传递消息通过自定义事件。即子组件通过在自身的事件执行方法中使用this.$emit('自定义事件名称',需要传递的内容),这个方法,在组件使用时监听自定义事件,从而在父组件中处理自定义事件的带参数的执行方法来进行信息传递。

实现步骤:
(1)子组件自身触发事件,在这个事件执行方法中通过调用this.$emit('自定义事件名称',传递的信息内容)这个方式向父组件发送信息
(2)在Vue实例范围内使用组件时,在组件上通过v-on监听子组件中设置的自定义事件,事件的执行方法在父组件中定义,在父组件中处理自定义事件的带参数执行方法(这个参数用于接收传递过来的信息)。

通信步骤详解:
1.创建Vue实例对象;创建子组件构造器对象,设置子组件实现功能;将组件构造器对象挂载到Vue实例对象上,构成父子组件.
2.在子组件中设置触发信息传递的事件,通过子组件的事件执行方法调用this.$emit("自定义事件",所传内容)这个方法进行通信传递
3.在Vue实例对象控制范围内使用子组件,同时监听子组件中设置的自定义事件,并调用父组件的执行方法;通过父组件的带参数执行方法处理子组件传递过来的信息。

案例:

<body>
    <div id="app">
      <!-- 使用组件 -->
      <!-- 监听组件中的自定义事件childclick,在事件方法handleChild中进行数据处理 -->
      <Cpn @childclick="handleChild"></Cpn>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <!-- 组件功能模板 -->
    <template id="tempCpn">
      <div>
        <ul>
          <!-- 循环渲染,监听点击事件,传递参数 -->
          <li v-for="item in books" @click="handleClick(item)">
            {{item.name}}
          </li>
        </ul>
      </div>
    </template>
    <script>
      const cpn = {
        template: "#tempCpn",
        data() {
          return {
            // 组件数据
            books: [
              { name: "小说", id: 1 },
              { name: "动漫", id: 2 },
              { name: "插画", id: 3 },
              { name: "视频", id: 4 },
            ],
          };
        },
        methods: {
          handleClick(item) {
            // 自定义事件childclick,传递数据item
            this.$emit("childclick", {
              ...item, // 解构对象
            });
          },
        },
      };
      const app = new Vue({
        el: "#app",
        data: {},
        components: {
          Cpn: cpn,
        },
        methods: {
          // 处理子组件传递的数据
          handleChild(item) {
            console.log(item);
          },
        },
      });
    </script>
  </body>

组件间的访问(对双方数据方法的调用)

1.组件间的访问———父组件访问子组件

父组件访问子组件通过this.$children或者this.$refs(推荐使用这种方法)
(1)this.$children方法返回值是一个伪数组,数组里面的元素为在父组件下挂载注册的子组件(即:[子组件1,子组件2,子组件3,...])。当我们需要在父组件中调用某个子组件的方法或者变量,属性时。使用:this.$children[该子组件的下标].需要调用的方法或者函数 这种形式来使用.

​ 语法:

​ this.$children[指定子组件所在下标].指定子组件中的方法/数据/函数

​ (2)this.$refs方法是一个对象类型,在默认情况下是一个空对象,只有当我们在组件标签中添加 ref="自定义组件标识名" 属性时,我们才可以通过 this.$refs.自定义组件标识名.需要调用的子组件方法/变量/函数... 这种方式访问子组件.

​ 语法:

​ <组件名 ref="自定义标识"></组件名>

​ 实例父组件中

​ this.$ref.自定义标识.子组件中的方法/数据/函数

案例:

<body>
    <div id="app">
      <Cpn></Cpn>
      <Cpn ref="reC"></Cpn>
      <button @click="handleFclick">查看子组件</button>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <!-- 组件功能模板 -->
    <template id="tempCpn">
      <div>
        <ul>
          <li v-for="item in books" @click="handleClick">{{item.name}}</li>
        </ul>
      </div>
    </template>
    <script>
      const cpn = {
        template: "#tempCpn",
        data() {
          return {
            // 组件数据
            books: [
              { name: "小说", id: 1 },
              { name: "动漫", id: 2 },
              { name: "插画", id: 3 },
              { name: "视频", id: 4 },
            ],
          };
        },
        methods: {
          handleClick() {
            // 访问父组件message
            console.log(this.$parent.message);
          },
        },
      };
      const app = new Vue({
        el: "#app",
        data: {
          message:'Hello,Vue'
        },
        components: {
          Cpn: cpn,
        },
        methods: {
          // 处理组件传递的数据
          handleFclick() {
            // 通过$children访问子组件books
            console.log(this.$children[0].books);

            // 通过$refs属性访问子组件books
            console.log(this.$refs.reC.books);
          },
        },
      });
    </script>
  </body>

2.组件间的访问————子组件访问父组件、子组件访问根组件(即Vue实例对象)

** 子组件访问父组件通过this.$parent,子组件访问根组件(即Vue实例对象)通过this.$root**
调用方法为:
this.$parent.需要调用的父组件变量/函数/方法等名称

​ 或

​ this.$root.需要调用的根组件变量/函数/方法等名称插槽的使用

案例:

<body>
    <div id="app">
      <Cpn></Cpn>
      <Cpn ref="reC"></Cpn>
      <button @click="handleFclick">查看子组件</button>
    </div>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <!-- 组件功能模板 -->
    <template id="tempCpn">
      <div>
        <ul>
          <li v-for="item in books" @click="handleClick">{{item.name}}</li>
        </ul>
      </div>
    </template>
    <script>
      const cpn = {
        template: "#tempCpn",
        data() {
          return {
            // 组件数据
            books: [
              { name: "小说", id: 1 },
              { name: "动漫", id: 2 },
              { name: "插画", id: 3 },
              { name: "视频", id: 4 },
            ],
          };
        },
        methods: {
          handleClick() {
            // 访问父组件message
            console.log(this.$parent.message);
          },
        },
      };
      const app = new Vue({
        el: "#app",
        data: {
          message:'Hello,Vue'
        },
        components: {
          Cpn: cpn,
        },
        methods: {
          // 处理组件传递的数据
          handleFclick() {
            // 通过$children访问子组件books
            console.log(this.$children[0].books);

            // 通过$refs属性访问子组件books
            console.log(this.$refs.reC.books);
          },
        },
      });
    </script>
  </body>

posted on 2020-10-26 13:59  HuaiJinCi  阅读(48)  评论(0编辑  收藏  举报