VUE中多级透传的常用方法
多级传递参数,自定义函数
- 根组件 parent.vue
<template>
<div class="w-100p h-100p relative">
<my-console-assign
task-type="5"
:card-height="cardHeight"
:subtract-width="subtractWidth"
is-enhance-find-lesson
:is-show-none="true"
:is-dispatch="false"
@handleButtonEvent="handleButtonEvent"
></my-console-assign>
</div>
</template>
<script>
import myConsoleAssign from '@/pc/view/listenAndDiscuss/myConsole/myConsoleAssign';
import WrapperContentBox from '@/pc/components/wrapperContentBox/wrapperContentBox.vue';
export default {
name: 'parent',
components: {
myConsoleAssign
},
props: {
// 面板高度
cardHeight: {
default: 222,
type: Number
},
// 左侧距离
subtractWidth: {
default: 0, //330通用 (减去了左侧的区块) 0(屏幕百分比宽度)
type: Number
}
},
data() {
return {};
},
methods:{
handleButtonEvent(){
}
}
};
</script>
<style lang="scss" scoped></style>
- 中间组件
props(父组件向子组件传值) 子传父应该用通过绑定事件然后及$emit传值,普通组件间传值用全局事件总线 $bus
中间组件不用接收 props 可以使用
v-bind=“$attrs” 传递 下级组件调用即可
自定义事件 v-on=“$listeners”
.sync 子更新父数据(当一个子组件改变了一个 prop 的值时,这个变化也会同步到父组件中所绑定。 .sync 它会被扩展为一个自动更新父组件属性的 v-on 监听器)
:data.sync=“dataList”
:columns=“getTableColumns()”
:current-page.sync=“page”
<template>
<div class="border-box flex-column p-20 h-100p w-100p">
<el-select class="m-b-20 select-drop-list select-w-custom" v-model="currentTermId" :placeholder="formatTerm">
<el-option
v-for="item in schoolTermList"
:key="item.school_term_id"
:label="item.label"
:value="item.val"
>
</el-option>
</el-select>
<module-wrap-title
title="我的听课记录"
title-class="f-s-18"
:margin-bottom="20"
:height="20"
is-show-notice-board
more-class="f-s-14 col-b-blue bold"
>
</module-wrap-title>
<wrapper-content-box
:data-list="dataListLessRecordList"
@diffSize="diffSize"
@handleButtonEvent="handleButtonEvent"
v-on="$listeners"
v-bind="$attrs"
:line-number="1"
></wrapper-content-box>
</div>
</template>
<script>
import { getCurrentMonthRangeDate } from '@/utils/old/time';
import myConsole from '@/pc/view/listenAndDiscuss/myConsole/mixins/myConsole';
export default {
components: {
ModuleWrapTitle,
WrapperContentBox,
},
filters: {
},
mixins: [myConsole],
props: {
taskType: {
type: String,
default: ''
}
},
data() {
return {
cardWidth: '325px',
dataList: [],
dateParams: {},
};
},
computed: {
},
watch: {
currentTerm(newVal) {
if (newVal.term_start) {
//newVal?.term_year + '' + (newVal?.term_number === '1' ? '春季' : '秋季') + '学期';
this.currentTerm.term_start = newVal.term_start;
this.currentTerm.term_end = newVal.term_end;
// this.getStatisticData();
}
},
},
mounted() {},
created() {
// 查询的用户id
this.queryUserId = this.$route.query.id ? this.$route.query.id : this.userInfo.user_id;
},
methods: {
init() {
},
// 格式化当前日期选项f
formatTermLabel(percentage) {
return percentage === 0 ? '---' : `${percentage}%`;
},
}
};
</script>
<style lang="scss" scoped>
$borderColor: #e6e6e6;
::v-deep .el-progress {
.el-progress-bar__outer,
.el-progress-bar__inner {
border-radius: 4px;
}
}
@media screen and (max-width: 1919px) {
.calendar-min {
width: 304px;
}
}
@media screen and (min-width: 1920px) {
.calendar-min {
width: 332px;
}
}
</style>
- 孙子组件
<template>
<div class="flex flex-wrap wrapper-box">
<!--放置占位卡片-->
<MediaWrapper v-if="isSeat" :match-size="matchSizeInfo.width">
<slot></slot>
</MediaWrapper>
<!--添加-->
<MediaWrapper v-if="isAdd" :card-width="cardWidth" :match-size="matchSizeInfo.width">
<div class="w-100p flex-center pointer border-box p-20 brs8 white-bg" :style="{ height: `${addHeight}px` }">
<div class="justify-center align-center flex-col add w-100p h-100p" @click="add">
<img src="@static/img/add_supervisor.png" alt="" class="w-32 h-32" />
<div class="m-t-16">{{ addTitle }}</div>
</div>
</div>
</MediaWrapper>
<MediaWrapper
v-for="(item, index) in newList"
:key="index"
is-margin
:card-width="cardWidth"
:match-size="matchSizeInfo.width"
> <!--新版听评课卡片-->
<enhance-find-lesson
v-if="isEnhanceFindLesson"
:item-info="item"
v-bind="$attrs"
v-on="$listeners"
></enhance-find-lesson>
<!--督导评课基本设置-->
<listen-manage-card
:item-info="item"
v-if="isListenManage"
:threshold-value="thresholdValue"
v-bind="$attrs"
></listen-manage-card>
</MediaWrapper>
<div
v-if="newList.length === 0 && isShowNone"
class="flex-1 m-10 "
v-bind="$attrs"
:title="noDataTitle"
v-empty
></div>
</div>
</template>
<script>
export default {
name: 'wrapperContentBox',
components: {
},
mixins: [multiPlatformType],
props: {
dataList: {
default: () => {
return [];
},
type: Array
},
//卡片前需要占位的个数
hasSizeNumber: {
default: 0,
type: Number
},
//是否单行展示
isWrap: {
default: false,
type: Boolean
},
//是否有添加的卡片
isAdd: {
default: false,
type: Boolean
},
//新开页面
isOpen: {
default: false,
type: Boolean
},
// 是否阈值
thresholdValue: {
default: false,
type: Boolean
},
},
data() {
return {
isScrollbarY: false,
diffSize: 0,
// 当前可用的宽度
freeScreenWidth: 0,
// 当前的matchSize信息
matchSizeInfo: {}
};
},
computed: {
},
created() {
},
// 大量页面用该组件包裹,所以缓存后的触发调用接口也放在该组件内
activated() {
// 防止多掉一次接口:created或者mounted中也会getData
if (this.$route.meta?.isFirstEnter === false) {
this.calcPageSize();
}
},
methods: {
async calcPageSize() {
await this.$store.dispatch('app/getViewWidth');
// 当前屏幕可用宽度
this.freeScreenWidth = this.$store.state.app.viewWidth - this.subtractWidth;
console.log('freeWidth', this.freeScreenWidth);
this.matchSizeInfo = getMatchSizeInfo(this.freeScreenWidth, this.pageSizeInDiffPx);
this.diffSize = listPageSize(this.freeScreenWidth, this.lineNumber);
if (this.isAdd) {
this.diffSize = this.diffSize - 1;
}
this.$emit('diffSize', this.diffSize);
},
toDetail(name, id, type, isPassword, isNewOpen, val) {
let routeUrl = this.$router.resolve({
name: name
});
if (isNewOpen) {
const token = getStorage(AccessToken);
window.open(
window.location.origin + window.location.pathname + routeUrl.href + '?id=' + id + '&token=' + token
);
} else {
if (isPassword) {
passwordDia(this, id, name, type, this.isOpen);
return;
} else if (this.isOpen) {
const token = getStorage(AccessToken);
window.open(
window.location.origin +
window.location.pathname +
routeUrl.href +
'?id=' +
id +
'&token=' +
token
);
return;
}
this.$router.push({
name: name,
query: {
...concatDistrictParams(this.$isDistrict, { id: id }, { isDistrict: 1 })
}
});
}
}
}
};
</script>
<style lang="scss" scoped>
</style>
$emit(子传父) 使用 .sync省略手动监听
<!--- 父组件 --->
<template>
<div class="app">
<Student v-on:at="getStudentName" v-on:go="getStudentAge"></Student>
</div>
</template>
<script>
// 引入Student组件
import Student from './components/Student.vue'
// 定义vue组件
export default {
name:'App',
components:{
Student
},
data() {
return {
msg:'你好啊'
}
},
methods: {
getStudentName(name) {
console.log('app收到了学生名',name);
},
getStudentAge(age) {
console.log('app收到了学生年龄',age);
}
}
}
</script>
<!--- 子组件 --->
<template>
<div class="student">
<h2>学生姓名:{{name}}</h2>
<h2>学校年龄:{{age}}</h2>
<button @click="sendStudentName">把学生名给app</button>
<button @click="sendStudentAge">把学生年龄给app</button>
</div>
</template>
<script>
export default {
name:'MyStudent',
data() {
return {
name:'张三',
age:18
}
},
methods: {
sendStudentName() {
// 触发Student组件实例对象vc上的at事件(绑定at事件)
this.$emit('at',this.name)
},
sendStudentAge() {
// 触发Student组件实例对象vc上的go事件(绑定go事件)
this.$emit('go',this.age)
}
}
</script>