转自 https://www.cnblogs.com/vickylinj/p/10877765.html
一、子组件向父组件传值 emit
1、自定义事件
在子组件中定义事件触发,通过
e
m
i
t
(
)
把
值
传
递
给
父
组
件
,
父
组
件
使
用
v
−
o
n
:
x
x
x
(
或
者
使
用
语
法
糖
@
x
x
x
)
进
行
监
听
并
接
受
参
数
;
但
是
需
要
注
意
emit()把值传递给父组件,父组件使用v-on:xxx(或者使用语法糖@xxx)进行监听并接受参数;但是需要注意
emit()把值传递给父组件,父组件使用v−on:xxx(或者使用语法糖@xxx)进行监听并接受参数;但是需要注意emit()第一个参数是自定义事件的名称。
原理:父组件将方法的引用,传递到子组件内部,子组件在内部调用父组件传递过来的方法,同时把要发送给父组件的数据,在调用方法的时候当作参数传递进去;
子组件:
父组件:
2、使用v-model
在父组件上使用v-model指令,子组件使用this.$emit(‘input’,this.子组件属性)
......
<my-component v-model="total "></my-component>
......
this.$emit ('input', this.counter);
二、父组件向子组件传值
1、 使用props
子组件通过 props方法获取父组件传递过来的值。props中可以定义能接收的数据类型,如果不符合会报错
父组件
//引入的add-widget组件
//动态传值使用的是表达式,使用 v-bind 的缩写语法通常更简单:XXX;静态传值不用绑定,传递的是字符串
<add-widget :msg-val="msg"> //这里必须要用 - 代替驼峰
// HTML 特性是不区分大小写的。所以,当使用的不是字符串模板,camelCased (驼峰式) 命名的 prop 需要转换为相对应的 kebab-case (短横线隔开式) 命名,当你使用的是字符串模板的时候,则没有这些限制
</add-widget>
data(){
return {
msg: [1,2,3]
};
}
子组件
//子组件通过props来接收数据:
//方式1:
props: ['msgVal']
//方式2 :
props: {
msgVal: Array //这样可以指定传入的类型,如果类型不对,会警告
}
//方式3:
props: {
msgVal: {
type: Array, //指定传入的类型
//type 也可以是一个自定义构造器函数,使用 instanceof 检测。
default: [0,0,0] //这样可以指定默认的值
},
// isPublic: {
// type: Boolean,
// default: undefined //注意!对于布尔类型,默认值不要写成false,否则isPublic永远为false。
// }
}
//注意 props 会在组件实例创建之前进行校验,所以在 default 或 validator 函数里,诸如 data、computed 或 methods 等实例属性还无法使用
注意:父子组件传值,数据是异步请求,有可能数据渲染时报错
原因:异步请求时,数据还没有获取到但是此时已经渲染节点了
解决方案:可以在父组件需要传递数据的节点加上 v-if = isReady(isReady默认为false),异步请求获取数据后(isReady赋值为true),v-if = isReady
2、使用$ref
ref 是被用来给元素或子组件注册引用信息的。引用信息将会注册在父组件的 $refs 对象上。
如果ref用在子组件上,指向的是组件实例,可以理解为对子组件的引用,通过 r e f 可 能 获 取 到 在 子 组 件 里 定 义 的 属 性 和 方 法 。 如 果 r e f 在 普 通 的 D O M 元 素 上 使 用 , 引 用 指 向 的 就 是 D O M 元 素 , 通 过 ref可能获取到在子组件里定义的属性和方法。 如果ref在普通的 DOM 元素上使用,引用指向的就是 DOM 元素,通过 ref可能获取到在子组件里定义的属性和方法。如果ref在普通的DOM元素上使用,引用指向的就是DOM元素,通过ref可能获取到该DOM 的属性集合,轻松访问到DOM元素,作用与JQ选择器类似。
父组件
<template>
<div>
<h1>父组件!</h1>
//注册子组件,起名 msg
<child ref="msg"></child>
</div>
</template>
<script>
import Child from '../components/child.vue'
export default {
components: {Child},
mounted: function () {
//获取子组件对象 msg
console.log( this.$refs.msg);
//调用子组件对象方法传值
this.$refs.msg.getMessage('子组件!')
}
}
</script>
子组件
<template>
<h3>{{message}}</h3>
</template>
<script>
export default {
data(){
return{
message:''
}
},
methods:{
//子组件定义方法,供父组件调用传值
getMessage(m){
this.message=m;
}
}
}
</script>
比较:
props通过父组件属性绑定,子组件定义相应属性,进行接收;
ref通过父组件注册子组件,调用子组件定义的方法进行传值
prop 着重于数据的传递,它并不能调用子组件里的属性和方法。像创建文章组件时,自定义标题和内容这样的使用场景,最适合使用prop。
$ref 着重于引用,主要用来调用子组件里的属性和方法,其实并不擅长数据传递。而且ref用在dom元素的时候,能使到选择器的作用,这个功能比作为索引更常有用到
三、子组件向子组件传递数据
通过eventBus或vuex(小项目少页面用eventBus,大项目多页面使用 vuex)传值
1、通过eventBus(即通过on监听、emit触发的方式)
1.1定义一个新的vue实例专门用于传递数据,并导出
1.2定义传递的方法名和传输内容,点击事件或钩子函数触发eventBus.emit事件
1.3接收传递过来的数据
注意:enentBus是一个另一个新的Vue实例,区分两个this所代表得vue实例
2、vuex进行传值
详情见:https://baijiahao.baidu.com/s?id=1618794879569468435&wfr=spider&for=pc
四、画面迁移的组件之间传递数据
1、通过路由带参数进行传值,例:两个组件 A和B,A组件通过query把orderId传递给B组件
A组件传值写法:
this.$router.push({ path: '/conponentsB', query: { orderId: 123 } }) // 跳转到B
B组件取值写法:
this.$route.query.orderId
注意:
①Vue-详解设置路由导航的两种方法:声明式的导航 和编程式的导航router.push(…)
②其中画面迁移有push和replace两种方式,详情如:
https://www.cnblogs.com/vickylinj/p/10880869.html
③传参的方式又分为查询参数query(+path)和命名路由params(+name)两种方式:
命名路由搭配params,刷新页面参数会丢失
查询参数搭配query,刷新页面数据不会丢失
接受参数使用this.$router后面就是搭配路由的名称就能获取到参数的值
详情如:https://blog.csdn.net/crazywoniu/article/details/80942642
2、通过设置 Session Storage缓存的形式进行传递
两个组件A和B,在A组件中设置缓存orderData
const orderData = { 'orderId': 123, 'price': 88 }
sessionStorage.setItem('缓存名称', JSON.stringify(orderData))
B组件就可以获取在A中设置的缓存了
const dataB = JSON.parse(sessionStorage.getItem('缓存名称'))
五、通过provide/inject传值
详情见:https://www.cnblogs.com/vickylinj/p/13368745.html
六、通过 a t t r s 、 attrs、 attrs、listeners传值
详情见:https://www.cnblogs.com/vickylinj/p/13376391.html