前端面试题,vue详解(组件传值)

看了很多关于vue组件传值的文章,于是想把文章总结一下,把关于vue组件传值好好聊聊,欢迎大家指正。

组件之间传值主要分两种
1、父子组件:props方法、ref方法、children和parent方法、 emit方法
2、非父子组件:公共bus.js、attrs/listeners、vuex

一、父子组件传值

1、props方法

父组件嵌套的子组件中,使用v-bind:msg=‘xxxx’进行对象的绑定,子组件中通过定义props接收对应的msg对象

父组件

<template>
  <div> 
    <child v-bind:msg="msg" ></child>
  </div>
</template>

<script>
// 引入子组件
import child from './child'
export default {
  components: {
    child,
  },
  data () {
    return {
      msg: '父组件传给值'
    }
  },
}
</script>

子组件

<template>
  <div>
    <h5>{{msg}}</h5>
  </div>
</template>

<script>
export default {
  // 要接受父组件传递的参数,在 props 中添加了元素之后,就不需要在 data 中再添加变量了
  props: {
    msg: {
      type: String
    },
  },
}
</script>

2、$ref方法

使用ref方法获取指定的子组件,使父组件轻松获取子组件的值,

父组件

<template>
  <div>  
    <p>{{msg2}}</p>
    <child ref="child"></child>
  </div>
</template>

<script>
// 引入子组件
import child from './child'
export default {
  components: {
    child
  },
  data() {
    return { 
      msg2: this.$refs.child.msg2
    }
  }
}
</script>

子组件

<template>
  <div> 
    <h5>{{msg2}}</h5>
  </div>
</template>

<script>
export default { 
  data(){
    return{
      msg2: "子组件传给父组件"
    }
  }
}
</script>

3、children,parent方法

使用 parent 查找当前组件的父组件。
使用 this.$children 查找当前组件的直接子组件,可以遍历全部子组件, 需要注意 $children 并不保证顺序,也不是响应式的,故不推荐使用。
父组件

<template>
  <div>  
    <h1>{{msg2}}</h1>
    <child :msg2="msg2"></child>
  </div>
</template>

<script>
// 引入子组件
import child from './child'
export default {
  components: {
    child
  },
  data() {
    return { 
      msg: "父组件传给子组件",
      msg2: ""
    }
  },
  mounted(){
    // 注意,this.$children[0].msg2只能在mounted生命周期下面才能获取,否则会报错
    this.msg2 = this.$children[0].msg2
  }
}
</script>

子组件

<template>
  <div> 
    <h5>{{msg}}</h5>
  </div>
</template>

<script>
export default { 
  data(){
    return{
      msg2: "子组件传给父组件",
      msg: this.$parent.msg
    }
  }
}
</script>

4、emit方法

子组件使用emit触发父组件的自定义事件:

vm.$emit( event, arg ) 	//触发当前实例上的事件
vm.$on( event, fn )	//监听event事件后运行 fn

父组件

<template>
  <div>  
    <h1>{{msg2}}</h1>
    <child @eventName="changeMsg"></child>
  </div>
</template>

<script>
// 引入子组件
import child from './child'
export default {
  components: {
    child
  },
  data() {
    return { 
      msg2: "父组件的值", 
    }
  },
  methods:{
    //changeMsg是自定义方法名,msg是子组件传过来的参数
    changeMsg(msg){
      this.msg2 = msg
    }
  }
}
</script>

子组件

<template>
  <div>  
    <button @click="open">请点击</button>
  </div>
</template>

<script>
export default { 
  data(){
    return{
      msg: "子组件传给父组件"
    }
  },
  methods: {
    open(){
   	  //eventName是父组件的自定义方法名,this.msg是传过去的参数
      this.$emit('eventName', this.msg)
    }
  }
}
</script>

二、非父子组件传值

1、公共的bus.js

1、兄弟之间传递数据需要借助于事件车,通过事件车的方式传递数据。
2、创建一个Vue的实例,让各个兄弟共用同一个事件机制。
3、传递数据方,通过一个事件触发bus.$emit(方法名,传递的数据)4、接收数据方,通过mounted(){}触发bus.$on (方法名,function(接收数据的参数){用该组件的数据接收传递过来的数据}),此时函数中的this已经发生了改变,可以使用箭头函数。

bus.js

import Vue from 'vue'
export default new Vue

公共组件存放兄弟组件

<template>
  <div>
    <list1></list1>
    <list2></list2>
  </div>
</template>

<script>
import list1 from './list1'
import list2 from './list2'
export default {
  components:{
    list1,
    list2
  }
}
</script>

兄弟组件1

<template>
  <div>  
    <h1>{{msg}}</h1> 
    <button @click="trans">把值传给小弟</button>
  </div>
</template>

<script> 
import bus from "./bus"
export default { 
  data() {
    return { 
      msg: "大哥组件的值传给小弟", 
    }
  },
  methods:{ 
    trans(){
      bus.$emit('eventName', this.msg)
    }
  }
}
</script>

兄弟组件2

<template>
  <div>  
    <h5>{{msg}}</h5> 
  </div>
</template>

<script> 
import bus from "./bus"
export default { 
  data() {
    return { 
      msg: "小弟组件的值",
    }
  }, 
  mounted(){
    bus.$on('eventName', val =>{ 
      this.msg = val; 
    })
  }
}
</script>

2、attrs和listeners的使用

在这里插入图片描述

在很多开发情况下,我们只是想把A组件的信息传递给C组件,如果使用props 绑定来进行信息的传递,虽然能够实现,但是代码并不美观。
在vue2.4中,为了解决该需求,引入了attrs 和listeners , 新增了inheritAttrs 选项。
在版本2.4以前,默认情况下父作用域的不被认作props的属性,将会“回退”且作为普通的HTML特性应用在子组件的根元素上。

$attrs
包含了父作用域中不被认为 (且不预期为) props 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 props 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind=”$attrs” 传入内部组件——在创建更高层次的组件时非常有用。
 
$listeners
包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on=”$listeners” 传入内部组件——在创建更高层次的组件时非常有用。

inheritAttrs
默认情况下父作用域的不被认作 props 的特性绑定 (attribute bindings) 将会“回退”且作为普通的 HTML 特性应用在子组件的根元素上。当撰写包裹一个目标元素或另一个组件的组件时,这可能不会总是符合预期行为。通过设置 inheritAttrs 到 false,这些默认行为将会被去掉。而通过 (同样是 2.4 新增的) 实例属性 $attrs 可以让这些特性生效,且可以通过 v-bind 显性的绑定到非根元素上。

A组件

<template>
  <div id="app">
    <!-- 此处监听了两个事件,可以在B组件或者C组件中直接触发 -->
    <child1 :p-child1="child1" :p-child2="child2" v-on:test1="onTest1" v-on:test2="onTest2"></child1>
  </div>
</template>
<script>
import Child1 from './Child1.vue'
export default {
  data() {
    return {}
  },
  components: { Child1 },
  methods: {
    onTest1() {
      console.log('test1 running...')
    },
    onTest2() {
      console.log('test2 running')
    }
  }
}
</script>

B组件

<template>
  <div class="child-1">
    <p>in child1:</p>
    <p>props: {{pChild1}}</p>
    <p>$attrs: {{$attrs}}</p>
    <hr />
    <!-- C组件中能直接触发test的原因在于 B组件调用C组件时 使用 v-on 绑定了$listeners 属性 -->
    <!-- 通过v-bind 绑定$attrs属性,C组件可以直接获取到A组件中传递下来的props(除了B组件中props声明的) -->
    <child2 v-bind="$attrs" v-on="$listeners"></child2>
  </div>
</template>
<script>
import Child2 from './Child2'
export default {
  props: ['pChild1'],
  data() {
    return {}
  },
  inheritAttrs: false,
  components: { Child2 },
  mounted() {
    this.$emit('test1')
  }
}
</script>

C组件

<template>
  <div class="child-2">
    <p>in child2:</p>
    <p>props: {{pChild2}}</p>
    <p>$attrs: {{$attrs}}</p>
    <hr />
  </div>
</template>
<script>
export default {
  props: ['pChild2'],
  data() {
    return {}
  },
  inheritAttrs: false,
  mounted() {
    this.$emit('test2')
  }
}
</script>

3、vuex

vuex是我们开发中最常用的一种跨组件传值方式,下期我们单独聊聊vuex。以上就是vue组件传值常用的几种方式,如有错误,欢迎指正。

发布了29 篇原创文章 · 获赞 32 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_41698051/article/details/105459566