前端知识点—–父子组件的深入使用

前端知识点—–父子组件的深入使用调用自身组件 父子组件

大家好,欢迎来到IT知识分享网。

我们对父子组件的学习,接触的一般是子组件通过事件传参给父组件,父组件拿到参数再进行处理,用来处理表单提交,弹框信息等等,再者就是父组件通过自定义属性传值给子组件,子组件通过props接收,watch监听新值,达到组件的复用的效果;

后我在vue官网接触到一种子父组件深度耦合的方式,使我们不用额外的创建新的组件,也可以达到一些效果,下面与你们分享一下:

直接上代码:

1.递归组件

看名字我们就知道,这是对组件进行递归,vue给我们提供的不只是递归子组件,而且可以在自己的模板中调用自己;

//parent.vue <template> <div> //对子组件传值 <HomeView :list="list"></HomeView> </div> </template> import HomeView from "./HomeView.vue"; <script> export default{ component:{ HomeView } data(){ return{ list: [{ name: "经济", children: [{ name: "如家", children: [{ name: "上江路-如家" }, { name: "望江路-如家" }] },{ name: "7天", children: [{ name: "长江路-7天" }, { name: "望江路-7天" }] }] }], } } } </script>

这里面的数据是嵌套的,嵌套两层children,一般我们可能会拿到数据用两个标签嵌套渲染,这里vue给我们提供了调用自己组件的方法:

//child.vue <template> <div> <div class="list-item" v-for="(item, index) in list" :key="index"> <div class="item-name"> <span>{ 
  {item.name}}</span> </div> <div v-if="item.children" class="children-item"> //调用自身 节省一个for循环 <HomeView :list="item.children"></HomeView> </div> </div> </div> </template> <script> export default{ //通过name选项做调用自身的事情 name:'HomeView', props:{ list: Array }, } </script>

让原本两次for循环的模板变得简洁易懂,虽然节省了一次for循环,但是这样做也是有缺点的,就是容易陷入无限循环中,这是我们需要注意的,最后得到的效果是:

前端知识点-----父子组件的深入使用

 这是vue给我们提供的多一种的使用组件方式

2.组件之间的循环使用

你可以理解为子父组件的深度耦合,相互调用从而更方便达到节点数的效果,形成相互循环渲染的效果

效果图:

前端知识点-----父子组件的深入使用

数据源:

 folders: [ { name: 'folder1', children: [{ name: 'folder1 - folder1', children: [{ name: 'folder1 - folder1 - folder1' }] }, { name: 'folder1 - folder2', children: [{ name: 'folder1 - folder2 - folder1' }, { name: 'folder1 - folder2 - folder2' }] }] }, { name: 'folder 2', children: [{ name: 'folder2 - folder1', children: [{ name: 'folder2 - folder1 - folder1' }] }, { name: 'folder2 - folder2', children: [{ name: 'folder2-content1' }] }] }, { name: 'folder 3', children: [{ name: 'folder3 - folder1', children: [{ name: 'folder3 - folder1 - folder1' }] }, { name: 'folder3 - folder2', children: [{ name: 'folder3-content1' }] }] } ],

 这个案例有爷爷组件这块我有在全局进行注册,HomeView.vue是爷爷组件,包含数据源,引进父级组件等操作;

main.js全局注册:

前端知识点-----父子组件的深入使用

HomeView.vue(爷爷组件):

<template> <div class="home"> <li v-for="folder in folders"> <about-view :folder="folder"></about-view> </li> </div> </template> <script> //引进父组件 import AboutView from './AboutView.vue'; export default { components:{ AboutView, }, data(){ return{ folders: [ { name: 'folder1', children: [{ name: 'folder1 - folder1', children: [{ name: 'folder1 - folder1 - folder1' }] }, { name: 'folder1 - folder2', children: [{ name: 'folder1 - folder2 - folder1' }, { name: 'folder1 - folder2 - folder2' }] }] }, { name: 'folder 2', children: [{ name: 'folder2 - folder1', children: [{ name: 'folder2 - folder1 - folder1' }] }, { name: 'folder2 - folder2', children: [{ name: 'folder2-content1' }] }] }, { name: 'folder 3', children: [{ name: 'folder3 - folder1', children: [{ name: 'folder3 - folder1 - folder1' }] }, { name: 'folder3 - folder2', children: [{ name: 'folder3-content1' }] }] } ], } }, } </script>

AboutView.vue(父级组件):

<template> <div class="about"> <p> <span>{ 
  {folder.name}}</span> <second-view :children="folder.children"></second-view> </p> </div> </template> <script> export default{ props:['folder'], components:{ // HomeView SecondView:()=>import('./SecondView.vue') }, data(){return{}}, } </script>

 SecondView.vue(孙子组件):

<template> <div> <ul> <li v-for="child in children"> <about-view v-if="child.children" :folder="child"></about-view> <span v-else>{ 
  {child.name}}</span> </li> </ul> </div> </template> <script> // import AboutView from './AboutView.vue' export default{ props:['children'], components:{ AboutView:()=>import ('./AboutView.vue') }, data(){return{}}, } </script>

写这个案例的时候出现了一个报错,是一个引入的逻辑错误,你需要找到一个循环支撑点,而又不能让他陷入无限循环,所以我让爷爷组件在全局注册,让子父组件异步引入,这样就可以解决报错问题,当然解决方法还有其他方式,例如在beaforecreate中引入,利用webpack等,欢迎相互讨论!

二,深层次的问题

 该文章是介绍对于多次使用的表单抽离成公共组件,围绕抽离的公共组件的一些技巧和方法;

包含公共组件在父组件的多次使用方法,父组件通过ref调用子组件的方法等;

这是最基础的组件通讯方案:

1,2,3是回顾子组件,父子间,非父子组件的传参;

4,5介绍的是子组件复用,父组件调用子组件的方法使用;

1.父传子

/父传子是自定义属性传值给子组件,子组件通过props接受传值,并渲染 //父页面 //<!-- 通过自定义属性传值给子组件 --> <Child :msg='msg'></Child>  return {       msg:'父组件的值'     } //子页面 <p>父组件的值为:{ 
  {msg}}</p> // 接受父组件传过来的值       props:['msg'],

2.子传父*

//子传父是自定义事件,通过$emit发送,父组件绑定自定义事件
//子组件
 

<button @click="sentInfo">通过自定义事件将值发送给父组件</button>  return {       childInfo:'子组件的值'     }    methods: {    sentInfo(){       // 发送自定义事件       // console.log(this)       // this.$emit('自定义事件名',发送的值)       this.$emit('sendV',this.childInfo)     }   },   //父组件    <!-- 监听子组件的自定义事件 -->  Child @sendV='showInfo'></Child>   return {       msg:'',//等待子组件的值     }    methods:{     // 监听的事件的函数的第一个参数就是传过来的值     showInfo(v){       console.log(v)// v只在{}内有效,父组件模板想要使用这个值,必须将值保存到自己的data中       this.msg = v     }   }

3.兄弟关系

main.js中

//bus事件中心

Vue.prototype.$event = new Vue()

  //兄弟组件是先在main.js初始化页面自定义事件通过​emit发送,b页面$on监听,

one.vue: <button @click="senMsg">发起自定义事件并携带参数</button> return { msg:"one组件的值" }, methods:{ senMsg(){ this.$event.$emit('sendmsgInfo',this.msg) } } //two.vue 监听自定义事件,并接受 mounted() { // 进入页面就开始监听one的自定义事件 // this.$event.$on('监听的自定义事件名'函数(函数的第一个参数就是传过来的值)) this.$event.$on('sendmsgInfo',(v)=>{ console.log(v)//one组件的值 }) },

 4.子组件复用

//这是需要复用的结构,需要抽离成公共组件 <template> <div class=".main_input"> <el-select v-model="name" filterable :filter-method="typeFiltersixone" placeholder="请选择" @change="chooseCustom" ref="multiSelectsixone" clearable> <el-option :value="treeDataValue" style="height: auto"> <el-tree :data="uDeptOptions" :props="defaultProps" :expand-on-click-node="false" :filter-node-method="filterNode" ref="treesixone" default-expand-all @node-click="handleNodeClick" node-key="deptId" /> </el-option> </el-select> </div> </template>

需求是需要复用表单查询,写一个组件复用人员查询模块;

这是正常的子父组件信息通讯,子组件通过事件$emit传递name和id,父组件传值watch监听变化;

//父组件传值监听 props:{ wzryName:{ required: false }, wzryId:{ required: false }, }, watch:{ wzryName:{ handler(newValue, oldValue){ this.name = newValue } }, wzryId:{ handler(newValue, oldValue){ this.ids = newValue } } },

复用的方案是使用同一个子组件,父组件使用时,用单独的方法!

//这就是复用的结构, //staff-queryitem是复用组件,复用两次,不同的是@returninput的方法不一样 <el-col :span="5"> <el-form-item label="派发人姓名" prop="pfryxm"> <staff-queryitem @returninput="inputData"></staff-queryitem> //第一个组件时inpuData方法 </el-form-item> </el-col> <el-col :span="5"> <el-form-item label="监督人姓名" prop="jdryxm"> <staff-queryitem @returninputtwo="inputDatatwo"></staff-queryitem> //第二个组件时inputDatatwo方法 </el-form-item> </el-col> 

单独传参

 //子传父 //两次复用对应两各不同的方法,分别传参 inputData(name,id){ this.queryParams.pfryxm=name this.queryParams.pfryId=id }, inputDatatwo(name,id){ this.queryParams.jdryxm=name this.queryParams.jdryId=id },

5.父组件通过ref调用子组件的方法

案例一:父组件调用子组件的方法,对父组件的数据进行处理

//以转换字符串方法为例: //子组件的方法 methods:{ //在子组件中写好一个反转字符串的方法, changetext(value){ return value.split('').reverse().join(""); } }, //父组件 <template> <div class="home"> <p>{ 
  {list}}</p> <One ref="once"></One> <button @click="reverse">转换子组件</button> </div> </template> //引入子组件 import One from '../components/One.vue'; export default { components:{ One, }, data(){ return{ list:'hellow' } }, methods:{ 通过ref调用子组件写好的changetext方法 reverse(){ console.log(this.$refs.once)//返回的是一个vue对象,所以可以直接调用其方法 this.list= this.$refs.once.changetext(this.list) }, }, } </script> 

此方法可以用来解决子组件复用时,需要对表单进行联动时使用;避免子父组件的反复传参;

案例二:父组件调用组件一的方法,调用组件二的数据进行处理

//还是以反转字符串为例 //组件一: methods:{ //组件一提供方法 changetext(value){ return value.split('').reverse().join(""); } }, //组件二: <template> <div class="home"> <p>{ 
  {list}}</p> <button @click="twos">发送数据</button> </div> </template> <script> export default { data(){ return{ list:'总是在梦里 我看到你无助的双眼' } }, methods:{ //组件二点击发送this.list数据给父组件 twos(){ this.$emit('sendV',this.list) }, }, } </script> //父组件 <template> <div class="home"> <p>{ 
  {info}}</p> <One ref="once"></One> <Two @sendV="Towsinfo"></Two> <button @click="reverse">转换子组件</button> </div> </template> <script> import One from '../components/One.vue' import Two from '../components/Two.vue' export default { components:{ One, Two }, data(){ return{ info:'' } }, methods:{ reverse(){ this.info= this.$refs.once.changetext(this.info) }, Towsinfo(v){ console.log(v); //组件二发送的数据 this.info=v //需要有一个变量接收 } }, } </script> 

通过这两个案例发现vue通过ref操作dom带来的好处是很明显的,便捷灵活的实现方案需求

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/157438.html

(0)
上一篇 2025-02-05 21:45
下一篇 2025-02-05 22:00

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信