简介
在了解了Vue语法的基础知识和常用特性之后,在进行正式的开发之前,非常有必要的对组件化的相关知识进行了解。本文就是为介绍组件的相关知识点的。
1、组件化开发思想
现实生活中的组件化思想主要是:标准,分治,重用和组合。而软件上的组件化思想,其实都是对上面所说的进行抽象表示,然而每种语言所用的标准可能又不相同。
组件化规范:Web Components
但是这个规范并不是所有的浏览器都支持
- 我们希望尽可能多的重用代码
- 自定义组件的方式不太容易(
html,css和js
) - 多次使用组件可能导致冲突
Web Components 通过创建封装好功能的定制化元素来解决上述问题。
其官网地址为:https://developer.mozilla.org/zh-CN/docs/Web/Web_Components。
Vue部分的实现了上述规则。
2、组件注册
2.1 全局组件注册语法
Vue.component(组件名称 ,{
data: 组件数据,
template: 组件模板内容
})
以下是定义组件的具体例子。
// 定义一个名为button-counter的新组件
Vue.component('button-counter',{
data: function () {
return {
count : 0
}
},
template : '<button v-on:click="count++">点击了{{count}}次。</button>'
})
2.2 组件的用法
<div id="app">
<button-counter></button-counter>
</div>
<div id="app">
<button-counter></button-counter>
<button-counter></button-counter>
<button-counter></button-counter>
</div>
2.3 组件注册的注意事项
-
data 必须是一个函数
- 分析函数和普通对象的对比
-
组件模板内容必须是单个根元素
- 分析演示实际的效果
-
组件模板内容可用是模板字符串
- 模板字符串需要浏览器提供支持(
ES6
语法) - 即模板内容使用反引号(tab键上面那个键)包裹,可多行显示,可读性强。(正常是用单引号包裹的)
- 模板字符串需要浏览器提供支持(
-
组件命名方式
- 短横线方式
- 驼峰方式
Vue.component('my-component',{ /*...*/})
Vue.component('MyComponent',{ /*...*/})
如果使用驼峰式命名组件,那么在使用组件的时候,只能在字符串模板中用驼峰的方式使用组件;但是在普通的标签模板中,必须使用短横线的方式使用组件。
2.4 局部组件注册
var ComponentA = { /* ... */}
var ComponentB = { /* ... */}
var ComponentC = { /* ... */}
new Vue({
el: '#app',
components: {
'component-a': ComponentA,
'component-b': ComponentB,
'component-c': ComponentC
}
})
局部组件只能在组测它的父组件中使用,其他地方不可以使用。
3、Vue调试工具
3.1 安装调试工具
在官网的生态系统菜单下可找到 Devtools
。
安装步骤:
- 克隆仓库
- 安装依赖包
- 构建
- 打开
chrome
扩展页面 - 选中开发者模式
- 加载已经解压的扩展,选中
shells/chrome
安装后如下图所示:
可用很直观的查看组件之间的层次关系。
4、组件间的数据交互
4.1 父组件向子组件传值
1、组件内部通过props
接收传递过来的值
Vue.component('menu-item',{
props: ['title'],
data: function() {
return {
msg: '子组件本身的数据'
}
}
template:'<div>{{ msg + "-------" + title }}</div>'
})
2、父组件通过属性将值传递给子组件
<menu-item title="来自父组件的数据"></menu-item>
<menu-item :title="title"></menu-item>
3、props
属性名规则
-
在props中使用驼峰形式,模板中需要使用短横线的形式
-
字符串形式的模板中没有这个限制
Vue.component('menu-item', {
// 在javascript中是驼峰式的
props: ['menuTitle'],
template: '<div>{{ menuTitle }}</div>'
})
<!-- 在html中是短横线方式的 -->
<menu-item menu-title="nihao"></menu-item>
4、props
属性值类型
- 字符串
String
- 数值
Number
- 布尔值
Boolean
- 数组
Array
- 对象
Object
4.2 子组件向父组件传值
props传递数据原则:单项数据流。即父组件可通过props向子组件传递数据,不建议通过props从子组件向父组件传值。
1、子组件通过自定义事件向父组件传递信息
<button v-on:click='$emit("enlarge-text")'>扩大字体</button>
2、父组件监听子组件的事件
<menu-item v-on:enlarge-text='fontSize += 0.1'></menu-item>
3、子组件通过自定义事件(带参数)向父组件传递信息
<button v-on:click='$emit("enlarge-text",0.1)'>扩大字体</button>
<!--父组件处理事件-->
<menu-item v-on:enlarge-text='fontSize += $event'></menu-item>
4.3 非父子组件间传值
1、单独的事件中心管理组件间的通信
var eventHub = new Vue()
2、监听事件与销毁事件
eventHub.$on('add-todo',addToDo)
eventHub.$off('add-todo')
3、触发事件
eventHub.$emit('add-todo',id)
可参考下图所示
5、组件插槽
5.1 组件插槽的作用
- 父组件向子组件传递内容
5.2 组件插槽级别用法
1、插槽位置
Vue.conmponent('alert-box', {
template: `
<div class="demo-alert-box">
<strong>Error:</strong>
<slot>默认内容</slot>
</div>
`
})
2、插槽内容和显示效果
<alert-box>有一个bug</alert-box>
<alert-box>有一个警告</alert-box>
<alert-box></alert-box>
<!--显示如下-->
Error:有一个bug
Error:有一个警告
Error:默认内容
5.3 具名插槽用法
1、插槽定义
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
2、插槽内容
<base-layout>
<h1 slot=="header">标题内容</h1>
<p>主要内容1</p>
<p>主要内容2</p>
<p name="footer">底部内容</p>
</base-layout>
<base-layout>
<tempalte slot=="header">
<h1>标题内容</h1>
<h1>标题内容</h1>
</tempalte>
<p>主要内容1</p>
<p>主要内容2</p>
<tempalte name="footer">
<p>底部内容</p>
<p>底部内容</p>
</tempalte>
</base-layout>
5.4 作用域插槽
- 应用场景:父组件对子组件的内容进行加工处理。
1、插槽定义
<ul>
<li v-for="item in list" v-bind:key="item.id">
<!--bind后的item是自定义的,引号中的item是上面的-->
<slot v-bind:item="item">
{{ item.name }}
</slot>
</li>
</ul>
2、插槽内容
<fruit-list v-bind:list="list">
<template slot-scope="slotProps">
<!--此处显示了加工处理的情况-->
<strong v-if="slotProps.item.current">
{{ slotProps.item.text}}
</strong>
</template>
</fruit-list>
总结
组件化的开发,可以让我们在实际的项目中对很多公共的功能进行抽取,从而实现重用。当然,本文中的很多知识点不是只看看就能理解的,需要手动的编码去感受代码的实现细节,并加深理解。接下来是关于前后的交互的相关总结,有兴趣的也可看看。