3.Vue2.x组件(含组件注册使用、组件生命周期函数、组件之间的数据共享)

# 了解组件


vue 中规定:组件的后缀名是 .vue。因此,组件一般是以 .vue 后缀的,比如 App.vue 文件本质上就是一个 vue 的组件。组件化开发,根据封装的思想,把页面上可重用的 UI 结构封装为组件,从而方便项目的开发和维护。

1. 组件的组成

每个 .vue 组件都由 3 部分构成。提示:安装了相关的插件之后按control+<就可以自动生成基本骨架了。

<template>
</template>

<script>
export default {};
</script>

<style lang="less" scoped>
//支持less,scoped表示给每个标签加上属性
</style>

1.1 template节点


  • template 是 vue 提供的容器标签,只起到包裹性质的作用,它不会被渲染为真正的 DOM 元素
  • template 中只能包含唯一的根节点

1.2 script节点

<script>
    //组件相关的data、methods等都要定义到 export default 导出的对象中
    export default{  }
</script>

1.3 style节点


//支持less语法,scoped表示给本组件里的每个标签加上统一属性,防止样式冲突
<style lang="less" scoped>

</style>

 

 # 组件的注册使用


1. 私有组件的注册使用

注:一般某个组件只被调用一两次的时候,可以选择注册私有组件。

查看代码
<template>
  <!-- APP根组件 -->
  <div class="app-container">

      <!-- 渲染 Left 组件和 Right 组件 -->
    <div class="box">
      <!-- 3. 以标签形式,使用注册好的组件 -->
      <Left> 这是left组件 </Left>
      <Right> 这是right组件 </Right>
    </div>

  </div>
</template>

<script>
  // 1. 导入需要使用的 .vue 组件
import Left from '@/components/Left.vue'
import Right from '@/components/Right.vue'

export default {
  // 2. 使用 components 节点注册组件
  components: {
    Left,
    Right,
  }
}
</script>

2. 全局组件的注册使用

注:当某个组件被调用的次数多时,选择注册全局组件。

注册方式:

在 vue 项目的 main.js 入口文件中,通过 Vue.component() 方法,可以注册全局组件。示例代码如下代码第3点:

查看代码
// 1 导入 vue
import Vue from 'vue'
// 2 导入 App.vue 组件
import App from './App.vue'
// 3 导入需要被全局注册的那个组件
//    Count 是需要注册的组件真实名称,MyCount是自定义名称
import Count from '@/components/Count.vue'
Vue.component('MyCount', Count)

Vue.config.productionTip = false

new Vue({
  // render 函数中,渲染的是哪个 .vue 组件,那么这个组件就叫做 “根组件”
  render: h => h(App)
}).$mount('#app')

使用方式:

依然是使用标签方式使用

查看代码
<template>
  <!-- App 根组件 -->
  <div class="app-container">
    <div class="box">
      <!-- 以标签形式,使用全局注册好的MyCount组件 -->
      <MyCount></MyCount>
    </div>
  </div>
</template>

 

 # 自定义属性props节点


注意:props是只读的,不可以动态修改。需要动态修改的自定义属性,可以将它“绑定”到data数据中,因为data中数据是可读写的。

props 是组件的自定义属性,在封装通用组件的时候,合理地使用 props 可以极大的提高组件的复用性! 它在props节点里定义,有两种语法格式。

1. 数组格式定义的自定义属性

数组格式定义有局限性,不可设置自定义属性的 默认值 和 数据类型

export default {
    //组件的自定义属性
    props:['自定义属性A','自定义属性B','自定义属性C',...]
           }

使用:

1)如组件A(封装者)定义了自定义属性 init 

<template>
  <div class="left-container">
    <p>{{ msg }}</p>
  </div>
</template>

<script>
export default {
  props: ['msg']
</script>

2)组件B(使用者)使用组件A,并自定义了A组件中的自定义属性 init

<template>
  <div class="right-container">
      <!--传字符串类型-->
    <A msg="我自己来定义我自己的msg">  </A>
      <!--传数字类型,需要配合v-bind使用-->
    <A :msg="100">  </A>
  </div>
</template>

2. 对象格式定义的自定义属性

对象格式定义有局限性,可以设置自定义属性的 默认值 和 数据类型【其使用同上】

export default {
    //组件的自定义属性
    props{
         msg:{
            default: '我是默认内容'  //自定义属性msg的默认值
            type: String  //数据类型,有Number/Object/Array/Booleans等
            required: true  //调用时是否必须传递属性值
         }
    }
}

 

# 组件嵌套中样式冲突问题


//scoped表示给本组件里的每个标签加上统一属性,防止样式冲突(使样式在本组件中生效)
//但是不能够穿透样式(父组件不能给子组件设置样式)
<style lang="less" scoped>
    //加上 /deep/ 的样式就可以穿透,父组件设置的样式可以在子组件中生效
    /deep/ .title{
        color:blue;
    }
</style>

 

 # 组件的生命周期&生命周期函数


生命周期(Life Cycle):指一个组件从 【创建 -> 运行 -> 销毁】 的整个阶段,强调的是一个时间段。

生命周期函数:是由 vue 框架提供的内置函数,会伴随着组件的生命周期,自动按次序执行。

created()生命周期函数示例: 

查看代码
<script>
export default {
  created() {
    bus.$on('share', val => {
      console.log('在 Right 组件中定义的 share 被触发了!', val)
      this.msgFromLeft = val
    })
  }
}
</script>

 

# 组件之间的数据共享


在项目开发中,组件之间的关系分为两大类: 父子、兄弟。

【它们之间的数据共享,一定要时刻明白是数据的共享,弄清楚数据到底在谁那里。有时候本组件展示的数据不一定属于自己的数据】

 1. 父->子 共享数据(自定义属性)

父组件向子组件共享数据使用 自定义属性 方式。步骤如下:

1.父组件传递信息:

查看代码
<template>
  <div class="app-container">
      //父组件在调用子组件Son的时候 顺便添加自定义属性
      //属性内容就是父组件给子组件传递的内容
      //加:就是传message下定义的内容,可以是字符串、方法、事件等等,这个例子传的是字符串和对象
      //不加:的话,是传输message这个字符串本身
     <Son :msg="message" :user="userinfo"></Son>
  </div>
</template>

<script>
   //导入子组件 
   import Son from '@/components/Son.vue'

   export default {
    data(){
        return{
            message:"我是父组件的信息",
            userinfo:{name:'zs', age:20}
</script>

2.子组件接收信息:

查看代码
<template>
  <div class="son-container">
    <p>父组件传过来的 msg 的内容是:{{ msg }}</p>
    <p>父组件传过来的 user 的内容是:{{ user }}</p>
  </div>
</template>

<script>
  export default {
     //用来接收父组件传过来的信息
     //自定义属性用props来接收
     //props: ['msg', 'user']
     props:{
         msg:{
             type:String,  //类型
             default:'默认值', //默认值
             required:true //代表必须
         },
         user:{
             type:Object,  //类型
             default:'默认值', //默认值
             required:true //代表必须
  }
</script>

 2. 子->父 共享数据(自定义事件)

子向父组件共享数据通过 自定义事件 方式。步骤如下:

1.子组件传送信息,通过 $emit 方法发送:

查看代码
<template>
  <div class="son-container">
    <h3>Son 组件的 {{ count }} </h3>
    <button @click="add">+1</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // 子组件自己的数据,将来希望把 count 值传给父组件
      count: 0,
    }
  },
  methods: {
    // 当触发 click 事件,就触发 add 方法
    // 触发 add 方法,就触发 this.$emit 方法
    // 触发 this.$emit 方法,就触发 numchange 这个自定义事件,
    // 并把 this.count 作为实参传递给 父组件接收的 numchange 这个事件绑定的方法的形参
    // 父组件的 numchange 事件绑定的 方法 通过参数可以拿到 this.count
    add() {
      // 让子组件的 count 值自增 +1
      this.count += 1
      // 把自增的结果,传给父组件,numchange 是自定义事件名称,this.count 是传输的数据
      this.$emit('numchange', this.count)
    }
  }
}
</script>

2.父组件接收信息,通过 调用自定义事件 接收:

查看代码
<template>
  <div class="app-container">
    <h1>App 父组件 渲染子组件传过来的 {{ countFromSon }}</h1>

    <!--渲染子组件的同时注册 自定义事件-->
    <div class="son">
        // 注册子组件传过来的自定义事件,给事件绑定getNewCount方法
        // 子组件通过一系列操作触发了这个自定义事件,就会调用该函数
        // 通过函数参数可以拿到传过来的内容
      <Right @numchange="getNewCount"></Right>
    </div>
  </div>
</template>

<script>
import Son from '@/components/Son.vue'

export default {
  data() {
    return {
      // 定义 countFromSon 来接收子组件传递过来的数据
      countFromSon: 0
    }
  },
  methods: {
    // 获取子组件传递过来的数据
    getNewCount(val) {
      console.log('numchange 事件被触发了!', val)
        //val就是子组件传过来的内容 this.count
      this.countFromSon = val
    }
  },
}
</script>

3. 兄弟组件间 共享数据(EventBus)

vue2.x 中,兄弟组件之间数据共享的方案是 EventBus 。实际上,任何两个组件间都可以用这个方案。步骤如下:

1 创建 eventBus.js 模块,并向外共享一个 Vue 的实例对象
2 在数据发送方,调用 bus.$emit('事件名称', 要发送的数据) 方法触发自定义事件
3 在数据接收方,调用 bus.$on('事件名称', 事件处理函数) 方法注册一个自定义事件

1.创建中间C位角色 EventBus.js 文件,文件代码如下:

import Vue from 'vue'
export default new Vue()

2.兄弟自己A(数据发送方):

查看代码
<template>
  <div class="a-container">
    <button @click="send">把好诗发给傻 B 兄弟</button>
  </div>
</template>

<script>
// 1. 导入 eventBus.js 模块
import bus from './eventBus.js'

export default {
  data() {
    return {
      str: `栏杆拍遍,无人会,登临意!`
    }
  },
  methods: {
    // 触发 click 事件,即触发send()方法,进而触发 bus.$emit 方法
    // bus.$emit 方法触发了就触发 share 这个 自定义事件
    // 并把 this.str 作为实参传递给接收方 share 事件所绑定的函数的形参
    send() {
      // 2. 通过 eventBus 来发送数据
      // share 是自定义事件名称,接下来给B兄弟调用的
      bus.$emit('share', this.str)
    }
  }
}
</script>

3.兄弟自己B(数据接收方):

查看代码
<template>
  <div class="b-container">
    <p>{{ msgFromA }}</p>
  </div>
</template>

<script>
// 1. 导入 eventBus.js 模块
import bus from './eventBus.js'

export default {
  data() {
    return {
      // 用来存储B发过来的信息的
      msgFromA: ''
    }
  },
  created() {
    // 2. 为 bus 绑定兄弟A组件的自定义事件 share
    // A通过一系列操作,触发了 share 事件 val 拿到的就是传过来的东西了
    bus.$on('share', val => {
      console.log('在 A 组件中定义的 share 被触发了!', val)
      this.msgFromA = val
    })
  }
}
</script>

 

posted @ 2022-04-12 00:54  RHCHIK  阅读(186)  评论(0编辑  收藏  举报