vue组件传值的十种方式
一、props
父传子
- 子组件
// 第一种数组方式
props: [xxx, xxx, xxx]
// 第二种对象方式
props: { xxx: Number, xxx: String}
// 第三种对象嵌套对象方式
//第三种对象默认支持 4 种属性,并且都是非必填的。可以随意使用
props: {
xxx: {
//类型不匹配会警告
type: Number,
default: 0,
required: true,
// 返回值不是 true,会警告
validator(val) { return val === 10}
}
}
- 父组件
// 第一种静态属性传参
// 注意:
// 1.在不定义 props 类型的情况下 props 接受到的均为 String。
// 2.当 props 属性指定为 Boolean 时,并且只有属性 key 没有值 value 时接受到的是 true
<!--props 接受到的均为 String -->
<children xxx="123"></children>
<!-- 有只有属性没有值, 这种情况 props 指定类型是 Boolean 则接收到的是 true -->
<children xxx></children>
// 第二种动态属性传参
// 注意:
// 1.需要区分非简写形式传入的值是对象,则会对应 props 中多个值
// 2.会保留传入值的类型
// 3.如果是表达式则获取到的是表达式的计算结果
<!-- prop 接收到 Number 类型的 123-->
<children :xxx="123"></children>
<!-- prop 接收到 Array 类型的 [1, 2, 3]-->
<children v-bind:xxx="[1, 2, 3]"></children>
<!-- prop 会接收到 xxx1 和 xxx2 俩个参数。这种不支持简写形式-->
<children v-bind="{xxx1: 1, xxx2: 2}"></children>
二、$emit-- $on
子传父
- 子组件
<template>
<div>
子组件:
<span>{{childValue}}</span>
<!-- 定义一个子组件传值的方法 -->
<input type="button" value="点击触发" @click="childClick">
</div>
</template>
<script>
export default {
data () {
return {
evidence: '我是子组件的数据'
}
},
methods: {
childClick () {
// childByValue是在父组件on监听的方法
// 第二个参数this.childValue是需要传的值
this.$emit("materials", this.evidence); //触发 input 事件,并传入新值
}
}
}
</script>
- 父组件
<template>
<div>
父组件:
<span>{{name}}</span>
<br>
<br>
<!-- 引入子组件 定义一个on的方法监听子组件的状态-->
<child
:third="third"
@materials="getMaterials">
</child>
</div>
</template>
<script>
import child from './child'
export default {
components: {
child
},
data () {
return {
name: ''
}
},
methods: {
getMaterials(evidence) {
// childValue就是子组件传过来的值
this.name = evidence
}
}
}
</script>
三、公共仓库bus.js
非父子组件之间传值,需要定义个公共的公共实例文件bus.js,作为中间仓库来传值,不然路由组件之间达不到传值的效果
- 公共bus.js
//bus.js
import Vue from 'vue'
export default new Vue()
- 组件A(传值的页面)
<template>
<div>
A组件:
<span>{{elementValue}}</span>
<input type="button" value="点击触发" @click="elementByValue">
</div>
</template>
<script>
// 引入公共的bug,来做为中间传达的工具
import Bus from './bus.js'
export default {
data () {
return {
elementValue: 4
}
},
methods: {
elementByValue () {
Bus.$emit('val', this.elementValue)
}
}
}
</script>
- 组件B (接收值的页面)
<template>
<div>
B组件:
<input type="button" value="点击触发" @click="getData">
<span>{{name}}</span>
</div>
</template>
<script>
import Bus from './bus.js'
export default {
data () {
return {
name: 0
}
},
mounted () {
// 用$on事件来接收参数
Bus.$on('val', elementValue => {
console.log(elementValue)
vm.name = elementValue
})
},
methods: {
getData () {
this.name++
}
}
}
</script>
四、vuex
五、v-model
- 父组件
// 引入子组件
// 写法 1
<plaintiff v-model="activeName_copy"></plaintiff >
// 写法 2
<plaintiff :activeName_copy="activeName_copy" @update:activeName_copy="activeName_copy= $event"></plaintiff>
// 写法 3
// 1. 事件名必须是 update: + 属性名
// 2. 参数不能是表达式,最好是 data 里面的属性
<plaintiff :activeName_copy.sync="activeName_copy"></plaintiff>
data(){
return{
activeName_copy: "first",
}
}
- 子组件
props: ['activeName_copy],
data(){
return{
activeName: this.activeName_copy,
}
}
methods:{
aa(){
this.activeName = 'fifth'
this.$emit('update:activeName_copy', this.activeName) //触发 input 事件,并传入新值
}
}
六、project / inject
<!--父组件 提供-->
{
project() {
return {
parent: this.test
}
},
data(){
return{
test:true
}
}
}
<!--子组件 注入-->
{
// 写法一
inject: ['parent']
// 写法二
inject: { parent: 'parent' }
// 写法三
inject: {
parent: {
from: 'parent',
default: 222
}
}
}
七、$refs和ref
八、$root
九、 $parent 和 $children (但是在实际中 $parent用的非常少——考虑到耦合度的原因)
$root 获取根组件
$parent 获取父组件—父传子
$children 获取子组件(所有的子组件,不保证顺序)-----子传父
$refs 组件获取组件实例,元素获取元素
十、插槽
十一、$attrs 和 $listeners