下面先说JS传统的this.$emit使用方法,然后对比TS的@emit方法便可一目了然,首先看this.$emit的使用方法。
this.$emit 算是父子通信的一种方法,作用为在子组件可以触发父级函数并且可以传参,当然这只是其中一种方法,之前总结过Vue子组件调用父组件函数的方法,可以点击查看,并且还有父调子组件的方法供大家参考。
首先回顾下this.$emit的使用方法
父组件
<template>
<div>
<child @fatherMethod="fatherMethod"></child>
</div>
</template>
<script>
import child from '~/components/dam/child';
export default {
components: {
child
},
methods: {
fatherMethod() {
console.log('测试');
}
}
};
</script>
子组件
<template>
<div>
<button @click="childMethod()">点击</button>
</div>
</template>
<script>
export default {
methods: {
childMethod() {
this.$emit('fatherMethod');
}
}
};
</script>
TypeScript语法中@emit
子组件
<template>
<section>
<el-table :data="tableData">
<el-table-column prop="parentId" label="父级编号"></el-table-column>
<el-table-column label="操作" width="320">
<template slot-scope="scope">
<el-link icon="el-icon-edit" type="primary" @click="editHandle(scope.row)">编辑</el-link>
</template>
</el-table-column>
</el-table>
</section>
</template>
<script lang="ts">
import {
Component,
Emit,
Prop,
Vue
} from "vue-property-decorator";
@Component
export default class DataDictionaryTable extends Vue {
@Prop() private tableData!: [];
//编辑
@Emit("editHandleEmit")
private editHandle(row) {
return row; // return将要传递的值
}
}
</script>
父组件
<ph-table :tableData="tableData" @editHandleEmit="editHandle"></ph-table>
//编辑
editHandle(row: any) {
console.log(row)
}
使用总结:
1.在ts中首先引用并抛出:
2.@emit使用方法与this.$emit对比, 父级完全一致,区别在于子组件(项目中截图代码,当前为子组件)
看上图注释了一行代码是 this.$emit('closeMainIndex'),目的是触发父级引用当前组件时@closeMainIndex等于的值(值代表父级要被触发的函数,可以与@后相同,也就是@closeMainIndex = “closeMainIndex”),可以参考最上面this.$emit的案例。
注释后调用了一个函数,this.editHandleIndex();在定义函数的上方,有一行@Emit("closemainindex"),此时closemainindex这个值和this.$emit('closeMainIndex')要触发的是一致的,完事。而this.editHandleIndex()这个函数内return的值是要传递的参数.
而使用 this.$emit('closeMainIndex')时,this.$emit('closeMainIndex', 'name', 'value'),这个方法name 和 value两个字符串才是要传递的参数,closeMainIndex触发父级的关键。
注意事项:
1.不论this.$emit('closeMainIndex')还是@Emit("closeMainIndex")都要切记,不要使用驼峰,this.$emit('closemainindex') @Emit("closemainindex")这么写才是对的,一定要全部小写,不要不信邪,今天发这篇文章的目的就是遇到了这个问题,在vue+ts项目中开发环境没问题,打包后线上就触发不了父级函数,也没有报错。其实之前没有在意过驼峰,也没有出现过问题,但这家公司的架子上真实遇到一次,写代码还是要按照规范来。
2.父级需要接收参数时,@closeMainIndex = “closeMainIndex(name, value)”,这么写是错误的,@closeMainIndex = “closeMainIndex”,不要加括号,在js区域中声明closeMainIndex函数时直接接收即可,closeMainIndex(name, value){}
题外拓展(网上找的例子,vue + ts 项目中Emit的用法,与本篇无太大关联,以上内容已经)
要使vue支持ts写法,我们需要用到vue-property-decorator,这个组件完全依赖于vue-class-componet
首先安装:
npm i -D vue-property-decorator
@Emit(event?: string)
@Emit装饰器接收一个可选参数,作为事件名;如果没有提供这个参数,$emit会将回调函数的camelCase(驼峰式)转为kebab-case(短横线命名),并将其作为事件名;
@Emit会将回调函数的返回值作为第二个参数,如果返回值是一个Promise对象,$emit会将Promise对象状态为resolved之后触发;
@Emit的回调函数的参数,会放在其返回值之后,一起被$emit当作参数使用;
看下面例子:
import { Vue, Component, Emit } from 'vue-property-decorator'
@Component
export default class YourComponent extends Vue {
count = 0
@Emit()
addToCount(n: number) {
this.count += n
}
@Emit('reset')
resetCount() {
this.count = 0
}
@Emit()
returnValue() {
return 10
}
@Emit()
onInputChange(e) {
return e.target.value
}
@Emit()
promise() {
return new Promise((resolve) => {
setTimeout(() => {
resolve(20)
}, 0)
})
}
}
以上代码等同于:
export default {
data() {
return {
count: 0,
}
},
methods: {
addToCount(n) {
this.count += n
// 将addToCount转成add-to-count
this.$emit('add-to-count', n)
},
resetCount() {
this.count = 0
this.$emit('reset')
},
returnValue() {
this.$emit('return-value', 10)
},
onInputChange(e) {
this.$emit('on-input-change', e.target.value, e)
},
promise() {
const promise = new Promise((resolve) => {
setTimeout(() => {
resolve(20)
}, 0)
})
promise.then((value) => {
this.$emit('promise', value)
})
},
},
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!