vue组件之间传值方式方法---实战面试篇

vue组件传值

最近准备面试跳槽。说到前端面试,有一些知识尤为重要,例如本篇文章要讲到的vue组件传值,几乎每家公司都会问到,所以在这里结合实战来总结一下。相信vue组件化对于前端开发者来说是家常便饭,所以组件之间的传值就变得尤为重要。本文章分为介绍、父子组件传值、兄弟组件传值、多层组件传值实操概括一下所有内容。

vue组件化

什么是组件化?

就拿开发一个页面来说,如果你把一个页面的所有逻辑都放到了一起,那样代码看起来就会非常复杂,处理起来会非常麻烦,而且重复性高。假如你是开发后台管理系统的,那么将会有70%的功能是重复的,相似功能的代码重复的写,这样就会造成代码冗余。所以把一些重复使用的功能分出来单独模块管理,这样在需要的地方引进便可以了。因此组件化对于前端开发尤为重要,可以把页面看成是很多组件结合而成。
如下图:
在这里插入图片描述

vue组件通讯

上面讲到vue组件化思想,现在开始进入正题,讲解一下vue组件之间的通讯方式以及方法。如果一个组件引入另一个组件,那么这个组件就是主组件,被引进的组件就是子组件。

父组件向子组件传值

父组件first.vue 子组件childA

父组件通过v-bind(:)向子组件传值,子组件通过props来接收。

// 父组件
<!-- 赋值给子组件A -->
<childA :mainstring="main"></childA>
// 子组件
props:{
  mainstring: {
    type: String, //接收类型
    requires: true //固定写法
  }
},
//以下为其他几种写法
--------------------------------------------------------------------------------------
props: { mainstring: String }
props: { mainstring: [String, Number] } //多个可能类型
props: { 
    childMsg: { 
        type: Array, 
        default: () => [] 
    }
}  // default指定默认值

props接收主组件的type类型可以分为:

  • 普通类型:字符串(String)、数字(Number)、布尔值(Boolean)、空(Null

因为vue是基于单向数据流的原理,父级 prop 的更新会向下流动到子组件中,但是反过来则不行,子组件中改变了值不会流向父组件并造成报错,因此可以赋值给childA,再进行更改就不会报错了。

props:{
  mainstring: {
    type: String,
    requires: true //固定写法
  }
},
data() {
  return {
    childA:this.mainstring
  }
},
methods: {
	// 重新赋值
	change(){
		this.childA = '子组件内部重新赋值'
	}
}

另外,子组件接收的mainstring值不会随着父组件的改变而改变,所以如果需要子组件的mainstring值随父组件改变,则需要建立一个watch监听来完成这一需求。

// 监听父组件mainstring值改变,进入改变childA值
watch: {
  mainstring(newval) {
    this.childA = newval
  }
}
  • 引用类型:数组(Array)、对象(Object

如果是引用类型,当在子组件中修改后,父组件的也会修改,因其数据是公用的,其他同样引用了该值的子组件也会跟着被修改。可以理解成父组件传递给子组件的值,就相当于复制了一个副本,这个副本的指针还是指向父组件中的那个,即共享同一个引用。所以除非有特殊需要,否则不要轻易修改。

子组件向父组件传值

  1. 子组件通过v-on(@)绑定一个方法,在方法中通过$emit传值

假设子组件有一个按钮,当我们点击这个按钮,子组件通过$emit向父组件传一个值,父组件拿到这个值渲染到页面上。

// 子组件
// 点击把 child 传给父组件
<a-button type="primary" @click="change">传值</a-button>

export default {
  data() {
    return {
      childA:'我是子组件的值'
    }
  },
  methods: {
    // 触发change方法 
    change() {
      this.$emit('changechild',this.childA) //传值操作,changechild为父组件绑定的方法
    }
  }
}
// 父组件
<span>主组件:{{ main }}</span>
<childA @changechild="changestring"></childA>

export default {
  components:{ childA },
  data() {
    return {
      main:"",
    }
  },
  methods: {
    // 接收子组件的传值
    changestring(name) {
      this.main = name
    }
  }
}
  1. 通过callback函数

父组件定义一个 callback 函数,通过prop传给子组件,子组件触发 callback 方法。

// 父组件
<span>主组件:{{ main }}</span>
<childA :callback="change"></childA>

import childA from './childA.vue'
export default {
  components:{ childA },
  data() {
    return {
      main:""
    }
  },
  methods: {
    // 接收子组件传过来的值
    change(name) {
      this.main = name
    },
  }
}
// 子组件
<a-button type="primary" @click="callback(childA)">传值</a-button>

export default {
  props: {
    callback: Function
  },
  data() {
    return {
      childA:'我是子组件的值'
    }
  }
}
  1. 通过$refs 访问组件实例

这两种都是直接得到组件实例,使用后可以直接调用组件的方法或访问数据。

// 父组件
<a-button type="primary" @click="change">点击触发子组件方法</a-button>
<childA ref="callchild"></childA>

import childA from './childA.vue'
export default {
  components:{ childA },
  methods: {
    // 点击触发子组件方法 -- ref方法
    change() {
      // 通过ref方法
      this.$refs.callchild.callprint()
    },
  },
}
// 子组件
callprint() {
  console.log('Hello World')
}

注:这种方式的组件通信不能跨级。

  1. $attrs / $listeners 后面会出一篇文章详细讲。

兄弟组件传值

  1. 通过props和$emit两者结合

现在有三个组件,分别为父组件和它的两个子组件,这两个子组件都在父组件下,没有上下级关系,因此称为兄弟组件。改变其中一个值,另外一个兄弟组件的某个值要被改变。可以先改变组件A值之后去触发$emit返回父组件,父组件再去改变传到组件B的值,组件B只需要用watch判断,实时渲染便可。

// 父组件
<!-- 子组件A -->
<childA :mainstring="main" @changechild="changestring"></childA>
<!-- 子组件B -->
<childB :mainstring="main"></childB>

import childA from './childA.vue'
import childB from './childB.vue'
export default {
  components:{ childA,childB },
  data() {
    return {
      main:"我是父组件的值",
      childA:"",
      childB:""
    }
  },
  methods: {
    // 改变传给子组件的值
    changestring(name) {
      this.main = name
    }
  },
}
// childA组件
<span>子组件A{{ childA }}</span>
<a-button type="primary" @click="change">传值</a-button>

export default {
  // 接收父组件的值
  props: { 
    mainstring: {
      type:String,
      requires:true
    }
  },
  data() {
    return {
      childA:this.mainstring
    }
  },
  methods: {
    // 传出新的值给父组件
    change() {
      this.childA = '我是childA的值'
      this.$emit('changechild',this.childA)
    }
  }
}
<span>子组件B{{ childB }}</span>

export default {
  // 接收父组件的值
  props: {
    mainstring: {
      type:String,
      requires: true
    }
  },
  data() {
    return {
      childB:this.mainstring
    }
  },
  // 监听父传子值改变赋值
  watch:{
    mainstring(newVal) {
      this.childB = newVal
    }
  }
}
  1. 新建一个vue实例,连接着两个组件。

创建一个空的 vue 实例EventBus.js文件来作为事件中心或者说是中转站,用来传递和接收事件,然后在需要的地方import引进即可,也可直接挂载在main上面。用法:假设兄弟A和B,A通过$emit触发事件发送至中间站EventBus.jsEventBus.js接收之后。B通过 $on监听中间件方法回调,获取数据。此种方法适用于任何组件间的通信。包括父子、兄弟、跨级。

// EventBus.js
import Vue from 'vue'
export default new Vue()
// childA.vue
<a-button type="primary" @click="change">修改传值</a-button>

import EventBus from './EventBus.js' 
change() {
   this.name = 'Lity'
   EventBus.$emit('getchildAchange',this.name) //发送到中间站
}
// childB.vue
import EventBus from './EventBus.js'
created() {
  EventBus.$on('getchildAchange', (name) => {
    this.childB = name  //name就是childA传到中间站的值
  })
}
  1. 通过 vuex 来处理,后面会出一篇文章详细讲。

上面通过创建一个vue实例,来实现数据的中间站处理可针对于一些简单的项目,对于更大型的、更复杂的项目,推荐使用 vue 提供的状态管理模式 Vuex 来进行处理。

总结

  1. 父传子:props直接传值;新建vue实例EventBus.js;
  2. 子传父:$emit;callback函数; $refs访问组件实例; $attrs / $listeners;
  3. 兄弟传值:props和$emit结合;新建vue实例EventBus.js;使用vuex;
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值