Vue笔记(三):深入理解组件

6 篇文章 0 订阅
5 篇文章 0 订阅
本文深入探讨Vue组件的定义、全局与局部注册,以及组件间的通信。通过示例代码,解释了如何使用data、props、$emit和事件监听实现组件状态管理和父子组件交互。同时介绍了单个根元素、prop验证和组件切换的概念,最后总结了组件的不同写法。
摘要由CSDN通过智能技术生成

在Vue笔记(二)中简单看了一下组件 现在做一个更详细的学习

来看一个经典的组件代码(来源于Vue官网)

// 定义一个名为 button-counter 的新组件
Vue.component('button-counter', {
  data: function () {
    return {
      count: 0
    }
  },
  template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})

组件的名称是 “button-counter” 组件生成后我们可以在Vue根实例中调用它

<div id="components-demo">
  <button-counter></button-counter>
</div>
new Vue({ el: '#components-demo' })

注意 在组件中data必须是一个函数 用于维护被返回对象 因此每个组件的data是独立的

注册

组件的注册分为全局注册和局部注册

Vue.component('my-component-name', {
  // ... options ...
})

这样的声明是全局注册

那么如何进行局部注册呢?

首先定义组件

var ComponentA = { /* ... */ }
var ComponentB = { /* ... */ }
var ComponentC = { /* ... */ }

然后再components中定义使用的组件

new Vue({
  el: '#app',
  components: {
    'component-a': ComponentA,
    'component-b': ComponentB
  }
})

局部注册的组件,没有办法在其他的子组件中使用 除非在其他子组件中再次注册

使用ES模块 那么写法是

import ComponentA from './ComponentA.vue'

export default {
  components: {
    ComponentA
  },
  // ...
}

使用webpack这样的模块系统时 最好将组件放在各自的文件中 在需要时调用

import ComponentA from './ComponentA'
import ComponentC from './ComponentC'

export default {
  components: {
    ComponentA,
    ComponentC
  },
  // ...
}

有的时候组件是一个基础组件 它可能只是一个输入框或者按钮 它将会被频繁的用到

单个根元素

Vue.component('blog-post', {
  props: ['post'],
  template: `
    <div class="blog-post">
      <h3>{{ post.title }}</h3>
      <div v-html="post.content"></div>
    </div>
  `
})

利用props来重构组件 这个组件接受一个对象post 这样不用去给post对象绑定所有的属性了

理解 $emit

一直没搞懂什么叫父组件 子组件

父组件就是一个new Vue对象 子组件就是这个Vue对象管辖范围内的Vue对象

举例 现在有一个组件

Vue.component('blog-post', {
  props: ['title'],
  template: '<h3>{{ title }}</h3>'
})

这个组件存在于

<div id="blog-post-demo">
<blog-post v-for="post in posts" v-bind:key="post.id"v-bind:title="post.title"></blog-post>
</div>

注意 此时管辖blog-post-demo的Vue实例就是组件blog-post的父级

那么这个组件内的各种信息 post.id post.title都是父级传递给子组件的 在父组件内

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' }
    ]
  }
})

所以说 子组件通过props来接受父级(父组件)的信息

同样 我们来看 $emit 怎么才能让子组件能够改变父级的信息呢

我们在子组件里添加一个$emit方法

<button v-on:click="$emit('enlarge-text')">
  Enlarge text
</button>

即 点击这个button时 触发父级的enlarge-text事件

接着我们在父级中写明这个事件会发生什么 使用v-on进行绑定(后面我们会看到在Vue中使用methods也是可以的)

<blog-post
  ...
  v-on:enlarge-text="postFontSize += 0.1"
></blog-post>

当子组件的按钮被点击时 enlarge-text事件被触发 这个事件将被父组件捕捉到并修改自身的postFontSize属性

现在就很清楚了

同样 $emit还可以传参

<button v-on:click="$emit('enlarge-text', 0.1)">
  Enlarge text
</button>

这个参数在父级中 使用$event来捕捉

<blog-post
  ...
  v-on:enlarge-text="postFontSize += $event"
></blog-post>

如果这个事件句柄是一个方法

<blog-post
  ...
  v-on:enlarge-text="onEnlargeText"
></blog-post>

那么这个参数将作为方法的第一个参数

methods: {
  onEnlargeText: function (enlargeAmount) {
    this.postFontSize += enlargeAmount
  }
}

自定义事件可以用于创建支持v-model的自定义输入组件

在vue中 下面的代码

<input v-model="searchText">

等价于

<input
  v-bind:value="searchText"
  v-on:input="searchText = $event.target.value"
>

prop验证

为组件的prop指定验证要求 再需求没有被满足时 Vue将会进行警告

Vue.component('my-component', {
  props: {
    // 基础的类型检查 (`null` 和 `undefined` 会通过任何类型验证)
    propA: Number,
    // 多个可能的类型
    propB: [String, Number],
    // 必填的字符串
    propC: {
      type: String,
      required: true
    },
    // 带有默认值的数字
    propD: {
      type: Number,
      default: 100
    },
    // 带有默认值的对象
    propE: {
      type: Object,
      // 对象或数组默认值必须从一个工厂函数获取
      default: function () {
        return { message: 'hello' }
      }
    },
    // 自定义验证函数
    propF: {
      validator: function (value) {
        // 这个值必须匹配下列字符串中的一个
        return ['success', 'warning', 'danger'].indexOf(value) !== -1
      }
    }
  }
})

组件切换

一个非常典型的场景就是点击某个标签时 出现不同的内容 即组件发生了切换

我们使用is来实现组件的切换

<component v-bind:is="currentTabComponent"></component>

通过对currentTabComponent进行计算属性computed来实现切换

总结:组件的多种写法

1、全局组件

// 组件的注册
Vue.component( 'componentName', {
    template:  // 组件的html结构,
    data(){
        return{
            // 组件中的属性
        }
    },
    method: {
        // 组件中的方法
    }
    ...... // 组件其他的属性和方法
})
 
// 组件的使用
new Vue({
    el: '#app'
})

2、局部组件

// 构造组件对象
const componentName = {
    template:  // 组件的html结构,
    data(){
        return{
            // 组件中的属性
        }
    },
    method: {
        // 组件中的方法
    }
    ...... // 组件其他的属性和方法
}
 
// 组件的使用
new Vue({
    el: '#app',
    components: {
        // 组件注册、调用
        componentName
    }
})

3、使用template标签

先使用<template>标签把组件的html结构写好

<template id="componnet">
    // 组件的html结构
</template>

全局注册

// 全局组件的注册与使用
Vue.component( 'componentName', {
    template:  '#component',
    data(){
        return{
            // 组件中的属性
        }
    },
    method: {
        // 组件中的方法
    }
    ...... // 组件其他的属性和方法
})
 
new Vue({
    el: '#app'
})

局部注册

// 局部组件的注册与使用
const componentName = {
    template:  '#component',
    data(){
        return{
            // 组件中的属性
        }
    },
    method: {
        // 组件中的方法
    }
    ...... // 组件其他的属性和方法
}
 
new Vue({
    el: '#app',
    components: {
        // 组件注册、调用
        componentName
    }
})

4、单文件组件

<template lang="html">
    // 组件中的html结构
</template>

<script>
    //组件的逻辑
    export default {
        // 组件的属性和方法
    }
</script>

<style lang="css" scoped>
    // 组件的样式
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值