vue 父子组件 组件挂载 组件通信 slot插槽

Vue父子组件挂载、传值与插槽详解
博客围绕Vue父子组件展开,介绍了父子组件的挂载,包括父组件向子组件传值、子组件通过this.$emit()向父组件传值,还提及父组件可通过this.$refs引用子组件DOM数据,最后讲解了插槽,如默认插槽和具名插槽v - slot。

vue 父子组件挂载
步骤1、导入子组件

步骤2、components中加载子组件

步骤3、视图模板中书写组件标签
<!-- 子组件 -->
<template>
<div>
  张三是个小朋友
</div>
</template>

<script>
export default {
  name: 'VueTwoSon',
  data () {
    return {

    }
  },
  // 生命周期 - 创建完成(访问当前this实例)
  created () {

  },
  // 生命周期 - 挂载完成(访问DOM元素)
  mounted () {

  }
}
</script>
<style scoped>
/* @import url(); 引入css类 */

</style>

<!-- 父组件 -->
<template>
<div>
  <!-- 步骤3 -->
  <vue-two-son></vue-two-son> 

</div>
</template>

<script>

import VueTwoSon from './VueTwoSon.vue' // 步骤1

export default {
  name: 'VueTwo',
  components: {  
    VueTwoSon // 步骤2
  },
  data () {
    return {

    }
  },
  // 生命周期 - 创建完成(访问当前this实例)
  created () {

  },
  // 生命周期 - 挂载完成(访问DOM元素)
  mounted () {

  }
}
</script>
<style scoped>
/* @import url(); 引入css类 */

</style>

父组件往子组件中传值
步骤1、在父组件中通过 v-bind:绑定传值的属性,绑定的属性名不可以使用驼峰
注:如果子组件中使用的是小驼峰,则两个单词之间使用横线

步骤2、子组件中使用props接参
注:如果接的是对象或者数组类型的时候,将默认值设置成一个方法,返回相应的数据

步骤3、子组件props接到参数的时候注意将这些参数赋值给data,在使用或者更改的时候尽可能的使用data中的数据
<!-- 父组件 -->
<template>
<div>

  <!-- 步骤1 -->
  <vue-two-son :son-name="name"
   :son-age="age"
   :son-obj="obj"
   :son-arr="arr"
   :son-func1="func1" />

</div>
</template>

<script>

import VueTwoSon from './VueTwoSon.vue'

export default {
  name: 'VueTwo',
  components: {
    VueTwoSon
  },
  data () {
    return {
      name: '张三丰',
      age: 12,
      obj: {
        teacher: '周发',
        father: '张光磊',
        son: '张晓峰',
        mother: '筱柚柚'
      },
      arr: ['篮球', '足球', '排球']
    }
  },
  methods: {
    func1 () {
      console.log(12 * 12)
    }
  },
  // 生命周期 - 创建完成(访问当前this实例)
  created () {

  },
  // 生命周期 - 挂载完成(访问DOM元素)
  mounted () {

  }
}
</script>
<style scoped>
/* @import url(); 引入css类 */

</style>


<!-- 子组件 -->
<template>
<div>
  <span>张三是个小朋友</span>
  <span>{{sonName}}————{{sonAge}}</span>
  <div v-for="(v,k,i) in sonObj" :key="k">{{v}}-{{k}}-{{i}}</div>
  <div v-for="(v,i) in sonArr" :key="i">{{v}}-{{i}}</div>
  <hr />
  <span>{{name}}————{{age}}</span>
  <div v-for="(v,k,i) in obj" :key="v+k">{{v}}-{{k}}-{{i}}</div>
  <div v-for="(v,i) in arr" :key="v">{{v+i}}-{{i}}</div>

  <hr />
  <label for="name"><input type="text" id="name" name="name" v-model="name" /></label>
</div>
</template>

<script>
export default {
  name: 'VueTwoSon',
  props: { // 步骤2
    sonName: {
      type: String,
      default: ''
    },
    sonAge: {
      type: Number,
      default: 0
    },
    sonObj: {
      type: Object,
      default: () => {
        return {}
      }
    },
    sonArr: {
      type: Array,
      default: () => {
        return []
      }
    },
    sonFunc1: {
      type: Function,
      default: () => {
        console.log('竟然不存在')
      }
    }
  },
  data () {
    return {
      name: this.sonName, // 步骤3
      age: this.sonAge,
      obj: this.sonObj,
      arr: this.sonArr
    }
  },
  // 生命周期 - 创建完成(访问当前this实例)
  created () {
    this.sonFunc1()
  },
  // 生命周期 - 挂载完成(访问DOM元素)
  mounted () {

  }
}
</script>
<style scoped>
/* @import url(); 引入css类 */

</style>


子组件向父组件传值 this.$emit()
步骤1:在子组件中设置操作,操作中使用 this.$emit('方法名',传值)

步骤2:在父组件中引入的子组件标签内书写 this.$emit()中传入的方法名,并绑定上v-on事件进行监听,并将监听事件后触发一个父组件中的 新事件,如果触发的事件不需要其它额外传参的情况,则不需要再进行传参
<组件标签 @emit中的方法名="父组件中的方法名()"></组件标签>

步骤3:在父组件中定义  父组件中的方法名,并设置第一个参数即为this.$emit穿过来的值
父组件方法(传值) {}
<!-- 子组件 -->
<template>
<div>
  <span>张三是个小朋友</span>
  <span>{{sonName}}————{{sonAge}}</span>
  <div v-for="(v,k,i) in sonObj" :key="k">{{v}}-{{k}}-{{i}}</div>
  <div v-for="(v,i) in sonArr" :key="i">{{v}}-{{i}}</div>
  <hr />
  <span>{{name}}————{{age}}</span>
  <div v-for="(v,k,i) in obj" :key="v+k">{{v}}-{{k}}-{{i}}</div>
  <div v-for="(v,i) in arr" :key="v">{{v+i}}-{{i}}</div>

  <hr />
  <label for="name"><input type="text" id="name" name="name" v-model="name" /></label>
</div>
</template>

<script>
export default {
  name: 'VueTwoSon',
  props: {
    sonName: {
      type: String,
      default: ''
    },
    sonAge: {
      type: Number,
      default: 0
    },
    sonObj: {
      type: Object,
      default: () => {
        return {}
      }
    },
    sonArr: {
      type: Array,
      default: () => {
        return []
      }
    },
    sonFunc1: {
      type: Function,
      default: () => {
        console.log('竟然不存在')
      }
    }
  },
  data () {
    return {
      name: this.sonName,
      age: this.sonAge,
      obj: this.sonObj,
      arr: this.sonArr
    }
  },
  watch: {
    name () {
      this.$emit('sonChangeName', this.name)  // 步骤1
    }
  },
  // 生命周期 - 创建完成(访问当前this实例)
  created () {
    this.sonFunc1()
  },
  // 生命周期 - 挂载完成(访问DOM元素)
  mounted () {

  }
}
</script>
<style scoped>
/* @import url(); 引入css类 */

</style>

<!--  -->
<template>
<div>

  <!-- 步骤2: @sonChangeName="changeName" -->
  <vue-two-son :son-name="name"
   :son-age="age"
   :son-obj="obj"
   :son-arr="arr"
   :son-func1="func1" @sonChangeName="changeName" />

   <div>{{name}}</div>

</div>
</template>

<script>

import VueTwoSon from './VueTwoSon.vue'

export default {
  name: 'VueTwo',
  components: {
    VueTwoSon
  },
  data () {
    return {
      name: '张三丰',
      age: 12,
      obj: {
        teacher: '周发',
        father: '张光磊',
        son: '张晓峰',
        mother: '筱柚柚'
      },
      arr: ['篮球', '足球', '排球']
    }
  },
  methods: {
    func1 () {
      console.log(12 * 12)
    },
    changeName (v) { // 步骤3
      console.log(v)
      this.name = v
    }
  },
  // 生命周期 - 创建完成(访问当前this实例)
  created () {

  },
  // 生命周期 - 挂载完成(访问DOM元素)
  mounted () {

  }
}
</script>
<style scoped>
/* @import url(); 引入css类 */

</style>

this.$refs 父组件可以通过它直接引用注册过的子组件DOM中的数据
步骤1: 在父组件中引用的标签中加上 ref="自定义名称"
<子组件标签 ref='自定义名称'></子组件标签>

步骤2:在父组件中定义方法使用this.$refs.自定义名称.DOM中的元素

<!-- 父组件 -->
<template>
<div>

  <!-- 步骤1 ref="vueTwoSon" -->
  <vue-two-son :son-name="name"
   :son-age="age"
   :son-obj="obj"
   :son-arr="arr"
   :son-func1="func1" @sonChangeName="changeName" ref="vueTwoSon" />

   <div>{{name}}</div>

  <div @click="sonDataRef()">$refs操作</div>

</div>
</template>

<script>

import VueTwoSon from './VueTwoSon.vue'

export default {
  name: 'VueTwo',
  components: {
    VueTwoSon
  },
  data () {
    return {
      name: '张三丰',
      age: 12,
      obj: {
        teacher: '周发',
        father: '张光磊',
        son: '张晓峰',
        mother: '筱柚柚'
      },
      arr: ['篮球', '足球', '排球']
    }
  },
  methods: {
    func1 () {
      console.log(12 * 12)
    },
    changeName (v) {
      console.log(v)
      this.name = v
    },
    sonDataRef () {
      console.log(this.$refs)
      console.log(this.$refs.vueTwoSon)
      console.log(this.$refs.vueTwoSon.sonValue) // 步骤2
    }
  },
  // 生命周期 - 创建完成(访问当前this实例)
  created () {

  },
  // 生命周期 - 挂载完成(访问DOM元素)
  mounted () {

  }
}
</script>
<style scoped>
/* @import url(); 引入css类 */

</style>

<!-- 子组件 -->
<template>
<div>
  <span>张三是个小朋友</span>
  <span>{{sonName}}————{{sonAge}}</span>
  <div v-for="(v,k,i) in sonObj" :key="k">{{v}}-{{k}}-{{i}}</div>
  <div v-for="(v,i) in sonArr" :key="i">{{v}}-{{i}}</div>
  <hr />
  <span>{{name}}————{{age}}</span>
  <div v-for="(v,k,i) in obj" :key="v+k">{{v}}-{{k}}-{{i}}</div>
  <div v-for="(v,i) in arr" :key="v">{{v+i}}-{{i}}</div>

  <hr />
  <label for="name"><input type="text" id="name" name="name" v-model="name" /></label>
</div>
</template>

<script>
export default {
  name: 'VueTwoSon',
  props: {
    sonName: {
      type: String,
      default: ''
    },
    sonAge: {
      type: Number,
      default: 0
    },
    sonObj: {
      type: Object,
      default: () => {
        return {}
      }
    },
    sonArr: {
      type: Array,
      default: () => {
        return []
      }
    },
    sonFunc1: {
      type: Function,
      default: () => {
        console.log('竟然不存在')
      }
    }
  },
  data () {
    return {
      name: this.sonName,
      age: this.sonAge,
      obj: this.sonObj,
      arr: this.sonArr,
      sonValue: '$refs的测试'
    }
  },
  watch: {
    name () {
      this.$emit('sonChangeName', this.name)
    }
  },
  // 生命周期 - 创建完成(访问当前this实例)
  created () {
    this.sonFunc1()
  },
  // 生命周期 - 挂载完成(访问DOM元素)
  mounted () {

  }
}
</script>
<style scoped>
/* @import url(); 引入css类 */

</style>

插槽
挂载上子组件后,在子组件中插入信息或者标签等元素,是的子组件在指定位置插入内容信息和标签

子组件中添加<slot></slot>标签以后,
则在父组件中挂载的子标签中间的内容 <父组件中的子组件标签>插槽内容</父组件中的子组件标签>
就会插入到子组件中的 <slot></slot>中

分为默认插槽
默认插槽
默认插槽:即将父组件的内容插入到子组件中所有的插槽中,不对插入过程进行任何处理——————一般俩将非常简单的时候才使用
<!-- 父组件 -->
<template>
<div>

  <!-- 古老的玄祸  就是需要插入到子组件插槽中的内容 -->
  <vue-two-son :son-name="name"
   :son-age="age"
   :son-obj="obj"
   :son-arr="arr"
   :son-func1="func1" @sonChangeName="changeName" ref="vueTwoSon" >
    <span style="color:red">古老的玄祸</span>
  </vue-two-son>

  <div>{{name}}</div>

  <div @click="sonDataRef()">$refs操作</div>

</div>
</template>

<script>

import VueTwoSon from './VueTwoSon.vue'

export default {
  name: 'VueTwo',
  components: {
    VueTwoSon
  },
  data () {
    return {
      name: '张三丰',
      age: 12,
      obj: {
        teacher: '周发',
        father: '张光磊',
        son: '张晓峰',
        mother: '筱柚柚'
      },
      arr: ['篮球', '足球', '排球']
    }
  },
  methods: {
    func1 () {
      console.log(12 * 12)
    },
    changeName (v) {
      console.log(v)
      this.name = v
    },
    sonDataRef () {
      console.log(this.$refs)
      console.log(this.$refs.vueTwoSon)
      console.log(this.$refs.vueTwoSon.sonValue)
    }
  },
  // 生命周期 - 创建完成(访问当前this实例)
  created () {

  },
  // 生命周期 - 挂载完成(访问DOM元素)
  mounted () {

  }
}
</script>
<style scoped>
/* @import url(); 引入css类 */

</style>

<!-- 子组件 -->
<template>
<div>
  <span>张三是个小朋友</span>

  <!-- 插槽 不区分位置 -->
  <div><slot></slot></div>

  <span>{{sonName}}————{{sonAge}}</span>
  <div v-for="(v,k,i) in sonObj" :key="k">{{v}}-{{k}}-{{i}}</div>
  <div v-for="(v,i) in sonArr" :key="i">{{v}}-{{i}}</div>
  <hr />
  
  <!-- 插槽 不区分位置 -->
  <div><slot></slot></div>

  <span>{{name}}————{{age}}</span>
  <div v-for="(v,k,i) in obj" :key="v+k">{{v}}-{{k}}-{{i}}</div>
  <div v-for="(v,i) in arr" :key="v">{{v+i}}-{{i}}</div>

  <hr />
  <label for="name"><input type="text" id="name" name="name" v-model="name" /></label>
</div>
</template>

<script>
export default {
  name: 'VueTwoSon',
  props: {
    sonName: {
      type: String,
      default: ''
    },
    sonAge: {
      type: Number,
      default: 0
    },
    sonObj: {
      type: Object,
      default: () => {
        return {}
      }
    },
    sonArr: {
      type: Array,
      default: () => {
        return []
      }
    },
    sonFunc1: {
      type: Function,
      default: () => {
        console.log('竟然不存在')
      }
    }
  },
  data () {
    return {
      name: this.sonName,
      age: this.sonAge,
      obj: this.sonObj,
      arr: this.sonArr,
      sonValue: '$refs的测试'
    }
  },
  watch: {
    name () {
      this.$emit('sonChangeName', this.name)
    }
  },
  // 生命周期 - 创建完成(访问当前this实例)
  created () {
    this.sonFunc1()
  },
  // 生命周期 - 挂载完成(访问DOM元素)
  mounted () {

  }
}
</script>
<style scoped>
/* @import url(); 引入css类 */

</style>

具名插槽 v-slot /
子组件中有多个位置,通过给插槽命名来插入具体的位置

子组件给插槽定义一个name属性 <slot name="slot1"></slot>

父组件中将需要插入到指定插槽内的内容使用<template>需要插入的内容</template> 包裹起来,并且通过 v-slot:或者#给其绑定插槽名称
<template v-slot:slot1 >需要插入的内容</template>
或者
<template #slot1>需要插入的内容</template>

使用了具名插槽后,没有被包含在具名插槽中的内容将不会再被定义名称的插槽所显示

都组件中插槽的排序不再影响在子组件中的展示顺序,最终顺序将以子组件中插槽的排序为准

<!-- 子组件 -->
<template>
<div>
  <span>张三是个小朋友</span>

  <!-- 插槽1 定义name -->
  <div><slot name="firstPerson"></slot></div>

  <span>{{sonName}}————{{sonAge}}</span>
  <div v-for="(v,k,i) in sonObj" :key="k">{{v}}-{{k}}-{{i}}</div>
  <div v-for="(v,i) in sonArr" :key="i">{{v}}-{{i}}</div>
  <hr />

  <!-- 插槽2 定义name -->
  <div><slot name="twoPerson"></slot></div>

  <span>{{name}}————{{age}}</span>
  <div v-for="(v,k,i) in obj" :key="v+k">{{v}}-{{k}}-{{i}}</div>
  <div v-for="(v,i) in arr" :key="v">{{v+i}}-{{i}}</div>

  <hr />
  <label for="name"><input type="text" id="name" name="name" v-model="name" /></label>
</div>
</template>

<script>
export default {
  name: 'VueTwoSon',
  props: {
    sonName: {
      type: String,
      default: ''
    },
    sonAge: {
      type: Number,
      default: 0
    },
    sonObj: {
      type: Object,
      default: () => {
        return {}
      }
    },
    sonArr: {
      type: Array,
      default: () => {
        return []
      }
    },
    sonFunc1: {
      type: Function,
      default: () => {
        console.log('竟然不存在')
      }
    }
  },
  data () {
    return {
      name: this.sonName,
      age: this.sonAge,
      obj: this.sonObj,
      arr: this.sonArr,
      sonValue: '$refs的测试'
    }
  },
  watch: {
    name () {
      this.$emit('sonChangeName', this.name)
    }
  },
  // 生命周期 - 创建完成(访问当前this实例)
  created () {
    this.sonFunc1()
  },
  // 生命周期 - 挂载完成(访问DOM元素)
  mounted () {

  }
}
</script>
<style scoped>
/* @import url(); 引入css类 */

</style>

<!-- 父组件 -->
<template>
<div>

  <!--  -->
  <vue-two-son :son-name="name"
   :son-age="age"
   :son-obj="obj"
   :son-arr="arr"
   :son-func1="func1" @sonChangeName="changeName" ref="vueTwoSon" >
    <!-- 插槽2的内容 -->
    <template v-slot:twoPerson>
      <span style="color:green;font-size:40px;">我虽然是这里的第二战士,但是总有一天我会当第一战士的</span>
    </template>
    <!-- 默认内容,将不生效 -->
    <span style="color:red">古老的玄祸</span>
    <!-- 插槽1的内容 -->
    <template #firstPerson>
      <span style="color:black;font-size:30px;">我要当第一个战士</span>
    </template>

  </vue-two-son>

  <div>{{name}}</div>

  <div @click="sonDataRef()">$refs操作</div>

</div>
</template>

<script>

import VueTwoSon from './VueTwoSon.vue'

export default {
  name: 'VueTwo',
  components: {
    VueTwoSon
  },
  data () {
    return {
      name: '张三丰',
      age: 12,
      obj: {
        teacher: '周发',
        father: '张光磊',
        son: '张晓峰',
        mother: '筱柚柚'
      },
      arr: ['篮球', '足球', '排球']
    }
  },
  methods: {
    func1 () {
      console.log(12 * 12)
    },
    changeName (v) {
      console.log(v)
      this.name = v
    },
    sonDataRef () {
      console.log(this.$refs)
      console.log(this.$refs.vueTwoSon)
      console.log(this.$refs.vueTwoSon.sonValue)
    }
  },
  // 生命周期 - 创建完成(访问当前this实例)
  created () {

  },
  // 生命周期 - 挂载完成(访问DOM元素)
  mounted () {

  }
}
</script>
<style scoped>
/* @import url(); 引入css类 */

</style>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值