vue3,vue组件,props给一个对象参数。vue组件间传参数,vue父组件给子组件传参数。组件参数类型。父组件调用子组件的方法。vue组件事件监听,给子组件传递方法,子组件调用父组件方法 电脑版发表于:2020/7/1 16:55 [TOC] 组件可以使用props给组件传值,可以同时传递多个,可以是任意类型,比如字符串或者对象。 下面是个简单的例子: ``` <div id="components-demo"> <blog-post test="aaa" content="哈哈哈"></blog-post> <blog-post test="hello component" content="嘿嘿嘿"></blog-post> </div> <script> //向子组件传值 Vue.component('blog-post', { props: ['test', "content"], template: '<h3>{{ test }}:{{content}}</h3>' }) var vm = new Vue({ el: '#components-demo' }); </script> ``` 效果如下: ![](https://img.tnblog.net/arcimg/aojiancc2/fd6a2c1c7f034d5f9743ea60f05c4ea3.png) ---- <br/> 在贴一个传多个props简单的例子,可以自己运行看看效果: ``` <div id="blog-post-demo"> <blog-post v-for="post in posts" v-bind:mykey="post.id" v-bind:title="post.title"></blog-post> </div> <script> //向子组件传值 Vue.component('blog-post', { props: ['mykey', "title"], template: '<h3>{{ mykey }}:{{title}}</h3>' }); new Vue({ el: '#blog-post-demo', data: { posts: [ { id: 1, title: 'My journey with Vue' }, { id: 2, title: 'Blogging with Vue' }, { id: 3, title: 'Why Vue is so fun' } ] } }) </script> ``` <br/> --- <br/> 但是如果一个组件内部需要的参数很多,不可能去定义那么多的props参数,还要用那么多的v-bind去给props钟的参数赋值,这个时候就可以只给一个props参数,给一个对象,然后只需要给一个参数使用v-bind赋值即可。 ``` <div id="blog-post-demo"> <blog-post v-for="article in myArticles" v-bind:article="article"></blog-post> </div> <script> //向子组件传值 Vue.component('blog-post', { props: ['article'], template: '<div><h4>{{article.title}}</h4><div>{{article.content}}</div><div>作者:{{article.autor}}</div></div>' }); new Vue({ el: '#blog-post-demo', data: { myArticles: [ { content: "只要你敢,我会毫不犹豫地跟你走,不顾一切,带着一腔勇敢和爱,跟你走。可是啊,你还是不敢", title: '文章一', autor: "aa" }, { content: "还是很喜欢你,性情善良,待人真诚,像日光洒满天地,温柔惬意", title: '文章二', autor: "xx" }, { content: "想把每天发生的事都分享给你的人大概是真的真的很喜欢你吧", title: '文章三', autor: "jj" } ] } }); </script> ``` 注意几点 - props: ['article'] 也要设置一个参数,虽然可以是对象。但是也要提供 - 使用v-bind提供参数,比如这里的v-bind:article。 如果不提供参数模块里边是拿不到的 - 外面使用组件的时候提供值的名称和组件里边的无关,可以随便取,比如这里组件里边定义的props属性名叫article,但是外面我使用的是data使用的是myArticles 效果如下: ![](https://img.tnblog.net/arcimg/aojiancc2/25afdd197dec4c39ae4f5cf2fd37c93f.png) ## Vue组件传递参数的类型常用可选的有 ``` 'title':String, 'bool':Boolean, 'getFun':Function ``` 普通类型:字符串(String)、数字(Number)、布尔值(Boolean)、空(Null) 引用类型:数组(Array)、对象(Object) #### 常用类型的定义示例: ``` // 组件参数 props: { percentage: { type: Number, default: 0 }, title: { type: String, default: '' }, show: { type: Boolean, default: false }, // 列配置 columnsConfg: { type: Array, default: () => { return [] }, }, // 数据项 rowdata: { type: Array, default: () => { return [] }, // required: true } // 对象参数 datas: { type: Object, default: () => { return {CompleteRate:50,PassRate:60,TrueRate:80} }, } }, ``` #### 常用类型的使用示例: **Boolean类型:** ``` <MyGrid title="图表展示" :Showtitle="false" style="height:100%"> </MyGrid> ``` **对象类型:** ``` <DataChart :datas="datas" /> ``` 数据也是按照正常的方式提供即可 ``` data() { return { datas:{CompleteRate: 60, PassRate: 70, TrueRate: 90}, } }, ``` **字符串类型,int类型,数组类型** 提供参数的时候具体加不加冒号,看着是直接给的还是通过数据绑定上去的 ``` <ScrollTable rowStyle="content_tr_center" :runSpeed="teacherDataRunSpeed" :scrollContentHeight=310 :columnsConfg="teacherColumnsConfg" :rowdata="teacherRowdata"> </ScrollTable> ``` 其中`数组类型`提供的值也和正常绑定的一样的放到data里边就行,比如 ``` data() { return { teacherColumnsConfg: [ { label: "教员", prop: "teacherName", width: "90px", }, { label: "班级数", prop: "classCount", width: "90px", }, { label: "课程数", prop: "courseCount", width: "90px", } } } } ``` ### vue3里边父组件给子组件传参 传递: ``` <OceanFreightTableEdit title="海运费" :isCanEditOceanFreight="ruleForm.isCanEditOceanFreight" ref="OceanFreightTableEditRef"></OceanFreightTableEdit> ``` 默认参数: ``` const props = defineProps({ schoolId: String, taskIds: { type: [] as any, default:[] } }) ``` 接收 ``` const props = defineProps({ title: String, isCanEditOceanFreight: Boolean }) ``` 取值: ``` <el-checkbox v-if="props.isCanEditOceanFreight" checked="true" disabled="true" v-model="isCanEdit" size="default" /> ``` 取值直接可以这样:props.isCanEditOceanFreight,props.title这种。 tn4>注意:父向子传参数的时候要注意时机问题哦,比如要传递的某个参数要从接口里边查询回来,然后组件的加载要比接口数据返回回来之前被加载了,这样传递到组件里边的参数永远都是默认的参数,不会是从接口回来的参数,所以这种情况就要进行处理,可以考虑等接口返回回来了在去加载组件,或者在子组件里边去监听一下父组件传递参数的值的变化也可以。 ## vue父组件调用子组件的方法 可以直接使用ref,在引用子组件的地方添加一个ref ``` <FeedbackDialog ref="feedbackDialog" /> ``` 然后通过ref的名字拿到子组件就可以调用子组件的方法了 ``` this.$refs.feedbackDialog.openFeedbackDialog(); ``` 可以用来传递参数,或者需要一个字段双向绑定的时候可以参考使用这种方式 ## vue3父组件调用子组件的方法 **子组件** 在`<script setup>`中子组件需要使用defineExpose暴露出来需要的方法,才能被父组件调用 ``` // 子组件需要使用defineExpose暴露出来需要的方法,才能被父组件调用 defineExpose({ getTrainingSubProgramList }) ``` 父组件 ``` <SubProgramPublic ref="subProgramPublicRef"></SubProgramPublic> // 注意:这里的属性名必须跟子组件定义的 ref 值一模一样,否者会关联失效 const subProgramPublicRef = ref(null) const subProgramSaveSuccess = ()=>{ // 调用子组件的方法 subProgramPublicRef.value.getTrainingSubProgramList() } ``` ## vue组件事件监听,给组件传递方法。子组件事件触发父组件方法 封装的组件里边,使用$emit方法就行,规定一个方法名称 ``` <div class="title_com_menu" v-if="ShowtitleMenu" @click="$emit('menuclick','可以传递需要的参数回去')"> <div class="title_com_menu_dot"></div> <div class="title_com_menu_dot"></div> <div class="title_com_menu_dot"></div> </div> ``` 然后使用的时候这样就行 ``` <MyGrid style="height:100%" title="教学动态" :ShowtitleMenu="true" @menuclick="menuclick()"/> <MyGrid style="height:100%" title="学习数据" :ShowtitleMenu="true" @menuclick="learnDataMore()"/> ``` 内部当前不一定要在`@click`中去触发,其他方式也可以,比如在表单填写好数据,进行数据验证成功后在调用引用组件时候定义的方法,相当于就类似一个回调函数的使用方式,但是用起来要灵活一些随时定义,随时使用 ``` saveLoadPortCharges() { var self = this self.$refs['editFormRef'].validate((valid) => { if (valid) { console.log(self.editFromData) // 通过emit调用引用组件时候定义的方法 self.$emit('insertData',self.editFromData) } }) } ``` 但是要注意这种方式父子组件只能跨一级,不能跨两级,比如子组件调用爷爷组件就不行。 **如果是跨越多级可以这样使用** ``` my.$parent.$parent.changeLabroomTodayCount(res.data.todayCount) ``` 跨几级就调用几次$parent 还可以使用EventBus等方式比如:https://blog.csdn.net/weixin_44867717/article/details/125632991 ## vue3子组件调用父组件方法 子组件: ``` <template> <view class="container"> <view @click="handleClose">关闭</view> </view> </template> const emit = defineEmits(['closePopup']) const handleClose = () => { emit('closePopup','参数') } ``` 父组件: ``` <uni-popup ref="classRankingPopup" type="bottom" @change="change"> <classSort :classRankData="state.classRankData" @closePopup="closeClassRankingPopup"></classSort> </uni-popup> ``` #### 如果是有多个方法就这样 子组件 ``` <template> <view class="popup-container"> <view class="titleWrap"> <view class="title">{{ title }}</view> <view class="closeTag" @tap="handleClose">×</view> </view> <scroll-view scroll-y="true" style=" height: 666rpx;"> <view class="pc-content" > <view class="pcc-item" @tap="choiseClass(item.id,item.className)" v-for="(item, index) in state.classList" :key="index"> {{item.className}} </view> </view> </scroll-view> </view> </template> // 触发closePopup事件(关闭事件) const emit = defineEmits(['closePopup','choiseClass']) const handleClose = () => { emit('closePopup', '参数') } // 点击选择了班级,传递了班级id和班级名称 const choiseClass = (_classId:string,_className:string) => { emit('choiseClass', _classId,_className) } ``` 父组件: ``` <uni-popup ref="choiseClassPopup" background-color="#fff" border-radius="60rpx 60rpx 0rpx 0rpx;" type="bottom" @change="methods.change"> <choiseClass @closePopup="popupMethods.closeChoiseClassDetails" @choiseClass="methods.choiseClass"></choiseClass> </uni-popup> const methods = { // 弹窗里边重新选择班级后的查询 choiseClass: function (_classId: string,_className:string) { console.log("重新选择班级了",_classId) // 关闭弹窗 popupMethods.closeChoiseClassDetails() state.classId = _classId state.className =_className } } ```