序:
vue最常见的,容易为难新手的,应该就是组件间的传参的,所以本次笔记就记录下传参,顺带也记录下vue2吧
一、vue3
1、父传子
父组件atherTitle,fatherMoney,fatherWifi,thisIsEmpty等都是传过去给子组件的
<template>
<el-row class="mb-4">
<el-button type="danger">props.vue传递父组件的参数到子组件,子组件用defineProps接收,fatherTitle和fatherMoney参数</el-button>
</el-row>
<!--写在父组件的子组件-->
<Son :fatherTitle="xxxxx" :fatherMoney="money" :fatherWifi="wifi" :thisIsEmpty="myEmptyStr" :fatherArr="myArr"></Son>
</template>
<script lang="ts" setup>
import { ref,reactive,watch,watchEffect } from 'vue'
import Son from "./son.vue"//引入子组件
const xxxxx = ref("-----这是父组件的标题-----")
const money = ref(9999999999)
const wifi = reactive({pwd:222,name:"fffff"})
const myEmptyStr = ref("")
const myArr = reactive([{code:666,msg:"success"},{code:555,msg:"fail"}])
</script>
子组件接收defineProps() 接收父组件传递过来的参数,defineProps在setup语法糖可以直接使用,不需要import
<template>
<el-row class="mb-4">
<el-button type="success">
son.vue:{{sonTitle}}-------{{fatherTitle}}-----{{fatherMoney}}
</el-button>
<el-button type="success">{{fatherWifi}}--{{fatherWifi.pwd}}--{{fatherWifi.name}}</el-button>
<el-button type="danger">
父传递的空字符串:{{myEmptyStr}}
</el-button>
</el-row>
<el-row class="mb-4">
<el-button type="primary" v-for="(item,index) in fatherArr" :key="index">
{{item}},{{item.code}}
</el-button>
</el-row>
</template>
<script lang="ts" setup>
import { ref,reactive} from 'vue'
const sonTitle = "This is son title"
//接收父组件传过来的值,需要注意defineProps只能在setup语法糖里面使用,不需要import引入
const yyyy = defineProps({
fatherTitle:{
type:String,//类型字符串
default:'当前Child.vue的默认值'//如果没有传递msg参数,默认值是这个
},
fatherMoney:{
type:Number,//类型字符串
default:0//如果没有传递msg参数,默认值是这个
},
fatherWifi:{
type:Object,//类型字符串
default:{id:999}//如果没有传递msg参数,默认值是这个
},
myEmptyStr:{
type:String,
default:"myEmptyStr默认值为空字符串"
},
fatherArr:{
type:Object,//类型字符串
//default:[]//如果没有传递msg参数,默认值是这个
},
})
console.log(yyyy.fatherArr)
console.log("-------这是子组件---------")
console.log(yyyy.fatherWifi)
console.log(yyyy.fatherTitle)
</script>
2、子传父
子组件
<script lang="ts" setup>
import { ref,reactive} from 'vue'
//子组件调用父组件的方法,
//父组件的调用子组件的地方写上@onMySonFunc="fatherFunc"
const myEmit = defineEmits(["onMySonFunc"])//这样就调用到父组件的fatherFunc方法了
//传递参数: "调用父组件的方法"和666666
myEmit("onMySonFunc","调用父组件的方法",666666)
</script>
父组件@onMySonFunc="funcToSon",这样上面的子组件就能调用到父组件的funcToSon()方法了
<template>
<!--子组件调用父组件的funcToSon()方法-->
<Son @onMySonFunc="funcToSon"></Son>
</template>
<script lang="ts" setup>
import { ref,reactive} from 'vue'
import Son from "./son.vue"//引入子组件
const funcToSon = (name:any,id:number)=>{
console.log("子组件调用了父组件的funcToSon()方法",id)
return {message:name}
}
</script>
3、隔代传
父组件provide传递参数到其他子孙组件
<script lang="ts" setup>
import { provide } from 'vue'
provide('test001', "987654321")
//provide传递test001的参数,值是987654321到子孙节点
</script>
儿子组件用inject接收父组件传递过来的参数
<script lang="ts" setup>
import {inject} from "vue"
//儿子组件用inject接收父组件传递过来的参数
const provideFatherStr = inject('thisFromGrandFather')
</script>
孙子组件也可以用inject接收父组件传递过来的参数
<script lang="ts" setup>
import {inject} from "vue"
//孙子组件用inject接收它爷爷组件传递过来的参数
const provideFatherStr = inject('thisFromGrandFather')
</script>
4、第三库(mitt || tiny-emitter
)
mitt 使用举例:
// eventBus.js
import mitt from 'mitt';
const emitter = mitt();
export default emitter;
// a.js
import emitter from './utils/eventBus'
emitter.emit('panda', {name: 'lokka', age: 2})
emitter.emit('flamingo', {name: 'disy', age: 1})
// b.js
import emitter from './utils/eventBus'
// 逐个监听
—————————————————————————————————————————
emitter.on('panda', (val) => {
console.log(val)
})
emitter.on('flamingo', (val) => {
console.log(val)
})
// 取消监听
funtion onFoo() {}
emitter.on('foo', onFoo)
emitter.off('foo', onFoo)
—————————————————————————————————————————
// 监听多个
emitter.on('*', (type, val) => {
console.log(type, val)
})
// 取消监听多个
emitter.all.clear()
二、vue2
1、父传子
父组件
<template>
<div class="wrap">
<div>我是Father组件</div>
<Son
str="我是字符串"
isPublished
:num=5
:obj="{cont:'我是一个对象'}"
:func="()=>{this.hello()}"
:arr="arr"></Son>
</div>
</template>
<script>
import Son from './Son'
export default {
name: "Father",
data(){
return{
arr:[1,2,3]
}
},
methods:{
hello(){
console.log("hello world!")
}
},
components:{ Son }
}
</script>
子组件
<template>
<div>我是Son组件</div>
</template>
<script>
export default {
name: "Son",
props:{//props列表
arr:Array,//定义参数类型
num:Number,
isPublished: Boolean,
str:String,
str2:{
type:String,
default:"我是默认字符串"//定义参数默认值
},
func:{
type:Function,
required:false//定义参数是否必须值
},
obj:{
type: Object,
required:false
}
},
created() {
console.log(this.str);//我是字符串
console.log(this.str2);//我是默认字符串
console.log(this.num);//5
console.log(this.isPublished);//true
console.log(this.func);//hello(){console.log("hello world!");}
console.log(this.arr);//[1,2,3]
console.log(this.obj);//{cont:'我是一个对象'}
this.func();//hello world!
}
}
</script>
2、子传父
2.1、$emit
父组件
<template>
<div class="wrap">
<div>我是Father组件</div>
<Son @func="speak" ></Son>
</div>
</template>
<script>
import Son from './Son'
export default {
name: "Father",
methods:{
speak(msg){
console.log(msg);//我是子组件发送的消息!
}
},
components:{
Son
}
}
</script>
子组件
<template>
<div>
<div>我是Son组件</div>
</div>
</template>
<script>
export default {
name: "Son",
mounted() {
//func 是绑定的事件名
this.$emit('func',"我是子组件发送的消息!");
}
}
</script>
2.2、直接传
父组件
<template>
<div class="parent">
<child :fatherMethod='fatherMethod'></child>// 父组件把方法传入子组件中,在子组件里直接调用这个方法
</div>
</template>
<script>
import child from '../base/child'
export default {
methods:{
fatherMethod() {
alert('我是父组件的know方法');
}
},
components:{
child
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped></style>
子组件
<template>
<div class="child" @click='childClick'>
</div>
</template>
<script>
export default {
props:{
fatherMethod: {
type: Function,
default: null
}
},
methods:{
childClick(){
this.fatherMethod()
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.child{
width: 100px;
height: 100px;
background-color: blue;
}
</style>
2.3、$refs
父组件
<template>
<div class="wrap">
<div>我是Father组件</div>
<!-- ref绑定节点 -->
<Son ref="son">
<!-- @click.stop 阻止冒泡 -->
<button @click.stop="UGG">按钮</button>
</Son>
</div>
</template>
<script>
import Son from './Son'
export default {
name: "Father",
mounted(){
//获取节点
this.$refs['son'].$on('func',(msg)=>{
console.log(msg);
})
},
methods:{
UGG(){
//调用节点里的方法
this.$refs['son'].show()
}
},
components:{
Son
}
}
</script>
子组件
<template>
<div>
<div>我是Son组件</div>
<button @click="$emit('func','我是子组件传递的消息1!')">Send1</button>
<button @click="sendMsg">Send2</button>
<!-- 插槽 -->
<slot></slot>
</div>
</template>
<script>
export default {
name: "Son",
methods:{
sendMsg(){
//func 是绑定的事件名
this.$emit('func','我是子组件传递的消息2!');
},
show(){
console.log('显示')
}
}
}
</script>
2.4、$parent
$root
和 $parent
都能够实现访问父组件的属性和方法,两者的区别在于,如果存在多级子组件,通过parent 访问得到的是它最近一级的父组件,通过root 访问得到的是根父组件(App.vue) 所以存在组件嵌套的情况下 不要使用 $root
父组件
<template>
<div class="parent">
<child></child>// ref 作用在组件上 指向的是组件的实例 实例上的方法都可以调用
</div>
</template>
<script>
import child from '../base/child'
export default {
data() { // 组件的data必须是函数
return {
msg:'父组件数据测试'
}
},
methods:{
fatherMethod() {
alert('我是父组件的方法')
}
},
components:{
child
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped></style>
子组件
<template>
<div class="child" @click='childClick'>
</div>
</template>
<script>
export default {
data() {
return {
msg: '我是子组件传递过来的数据'
}
},
methods:{
childClick(){
this.$parent.fatherMethod()
console.log(this.$parent.msg)
}
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.child{
width: 100px;
height: 100px;
background-color: blue;
}
</style>
3、兄弟传值
在main.js种挂载全局EventBus
Vue.prototype.$EventBus = new Vue()
A组件
<template>
<div class="wrap">
<div>我是组件A</div>
<button @click="sendMsg">发送</button>
</div>
</template>
<script>
export default {
name: "A",
methods:{
sendMsg(){
this.$EventBus.$emit('sendMsg',"这是组件A发送的消息!")
}
}
}
</script>
B组件
<template>
<div>
<div>我是组件B</div>
</div>
</template>
<script>
export default {
name: "B",
mounted(){
this.$EventBus.$on('sendMsg',(msg)=>{
console.log(msg);//这是组件A发送的消息!
})
},
}
</script>
4、隔代传值( provide
/ inject
)
provide是父级组件需要传递给子孙组件的属性/方法
//选项一
provide: {
content: 'hello world'
}
//选项二
provide(){
return {
content: 'hello world'
}
}
inject是子孙组件用来接收父级组件属性/方法
//选项一
inject: ['content']
//选项二
inject: {
content: 'content'
}
//选项三
inject: {
content: {
from:'content',
default:'hello world'
}
}
a.vue
<template>
<div>
<span>{{a}}</span>
<aa></aa>
</div>
</template>
<script>
import aa from './aa';
export default {
data(){
return {
a: "我是a组件中数据"
}
},
provide() {
return {
msg: this.a
}
},
components: {
aa
}
}
</script>
aa.vue
<template>
<div>
</div>
</template>
<script>
export default {
inject: ['msg'],
created() {
console.log(this.msg); // 我是a组件中数据
}
}
</script>
5、跨级($attrs
/ $listeners
)
- **$attrs:**包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件。通常配合 interitAttrs 选项一起使用。
- **$listeners:**包含了父作用域中的 (不含 .native修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件
父组件
<template>
<div>
<span>{{name}}</span>
<span>{{price}}</span>
<aa
:name="name"
:price="price"
:size="size"
></aa>
</div>
</template>
<script>
import aa from './aa';
export default {
data(){
return {
name: "可乐",
price: 3,
size: "500ml"
}
},
provide() {
return {
msg: this.a
}
},
components: {
aa
}
}
</script>
子组件aa.vue
<template>
<div>
<span>{{name}}</span>
<aaa v-bind="$attrs"></aaa>
</div>
</template>
<script>
import aaa from './aaa';
export default {
props: ['name'],
components: {
aaa
}
}
</script>
子组件aaa.vue
<template>
<div>
</div>
</template>
<script>
export default {
created() {
console.log(this.$attrs); // {price: 3, size: "500ml"}
}
}
</script>
总结: $attrs 与 $listeners 是两个对象,$attrs 里存放的是父组件中绑定的非 Props 属性,$listeners里存放的是父组件中绑定的非原生事件。
6、插件传值
安装 pubsub-js
插件: npm i pubsub-js -s
可实现全局参数传递
publishSync
同步发送消息publish
同步发送消息subscribe
订阅消息unsubscribe
卸载特定订阅clearAllSubscriptions
清除所有订阅
组件A
<template>
<div class="wrap">
<div>我是组件A</div>
<button @click="sendMsg">发送</button>
</div>
</template>
<script>
import pubsub from 'pubsub-js'
export default {
name: "A",
methods:{
sendMsg(){
//publishSync 同步发送消息
pubsub.publishSync("sendMsg","这是A组件发布的消息!");
}
}
}
</script>
组件B
<template>
<div>
<div>我是组件B</div>
</div>
</template>
<script>
import pubsub from 'pubsub-js'
export default {
name: "B",
mounted(){
//subscribe 订阅消息
pubsub.subscribe("sendMsg",(e,msg)=>{
console.log(e,msg);//sendMsg 这是A组件发布的消息!
})
},
}
</script>
7、路由传值
7.1、页面直接传参
<router-link :to="{ path:'./attachment',query:{order_id: task.ORDERID}}">
<mt-button type="primary" size="small">查看附件</mt-button>
</router-link>
7.2、通过方法传递参数
methods: {
society() {
//console.log('society');
this.$router.push({
name:'society',
query:{value:1}
})
},
7.3、接值
methods:{
loadData:function(){
this.id = this.$route.query.order_id;
axios.get("http://testqywx.origimed.com:18082/weixin-qy/order/Order/userOrderFilesList.json?usercode=sysadmin&orderId="+this.id)
.then(response=>this.tasks=response.data.reason);
}
},
哎呀,累了,没想到总结下来,还不少,暂时先这么多吧,回头有了再更新~