1、认识vue组件
组件是 vue 最基础、最常用的功能
vue 组件化就是把页面分割成不同模块,每个模块视为一个组件,每个组件包含三部分:内容(模板代码)、功能(js代码)、样式(css 代码,less 等需要构建工具支撑)。
开发组件三步骤:
⑴ 创建组件
⑵ 注册组件(全局注册、局部注册)
⑶ 应用组件
提示:在使用 Vue 组件,建议先理解 ES6 的箭头函数、模块化等基础知识。
2、创建组件
每个 .vue 文件即可视作一个组件,每个组件由 3 部分构成,如下:(注意:每个组件必须包含 template 模板结构,缺失此部分启动 vue 时会报错,而 script 行为和 style 样式是可选的组成部分)
template: 组件的模板结构
script: 组件的 javascript 行为
style: 组件的样式
导出组件:(省去此部分 vue 也能正常运行,但缺失 name 属性后,可能出现不可预期的错误)
<script>
export default{
name: 'Swiper',
props: [],
methods: {}
}
</script>
常用的组件配置对象:
export default {
//返回数据
data(){
return {
//变量
}
},
computed: {
//计算属性
},
methods: {
//方法
},
template: `...模板`,
render(m){ ... }
}
3、组件命名
官方推荐的两种组件命名法:
⑴ PascalCase 命名法,俗称帕斯卡命名或大驼峰命名法,比如:MyTitle
⑵ kebab-case 命令法,俗称短横线命名法,比如:my-title
用大驼峰命名后,使用组件时既可以使用驼峰式,也可使用短横线式,比较灵活,实际卡法中推荐使用。
4、注册组件
注册组件分为局部注册和全局注册。一些组件在开发期间的使用频率很高,推荐进行全局注册。其它大部分场景不建议使用全局注册,因为使用构建工具时,可能会导致工具无法优化打包,影响打包结果,一般情况是组件在哪里用,就在哪里注册。
⑴ 局部注册:在 Vue 实例中,使用 import 引入组件,然后使用 components 注册(速写属性即可)
比如定义一个组件 Title,在 Vue 配置中局部注册:
<template>
<title></title>
</template>
<script>
import Title from '../Title.vue'
export default ({
components: {Title}
});
</script>
⑵ 全局注册:全局注册的组件,整个应用中任何地方都可以使用(包括 Vue 实例中,其它组件中)
编辑 src 目录下的 main.js,添加如下代码进行组件全局注册
import { createApp } from 'vue'
import App from './App.vue'
const app = createApp(App)
// 1. 导入组件
import Swiper from './components/Swiper.vue';
// 2. 调用 app 实例的 component() 方法,在全局注册 my-swiper 组件
app.component('my-swiper', Swiper);
app.mount("#app");
使用全局注册的组件,任意的 .vue 文件中都可直接使用
<template>
<my-swiper></my-swiper>
</template>
注意:组件之间可以相互使用,没有注册的组件不能使用
5、应用组件:
把注册的组件当成一个元素来用,有两种写法,“<组件名/>” 和 “<组件名></组件名>”
比如使用大驼峰命名法注册了一个全局组件:
app.component("MyTitle", title);
使用方法:
<MyTitle /> //写法一
<MyTitle></MyTitle> //写法二
<my-title /> //写法三
<my-title></my-title> //写法四
</template>
6、组件封装原则
为了提高组件的复用性,在封装 vue 组件时需要遵守如下的原则
组件的 DOM 结构、style 样式要尽量复用
组件中要展示的数据,尽量由组件的使用者提供
7、template中的根节点
在 vue2.x 的版本中,<template> 节点内的 DOM 结构仅支持单个根节点:
<template>
<!-- 在vue2.x中,template节点内的所有元素,最外层必须有唯一的根节点进行包裹,否则报错-->
<div>
<h1>这是标题</h1>
<h2>这是副标题</h2>
</div>
</template>
在 vue3.x 的版本中,<template> 中支持定义多个根节点:
<template>
<!-- 这是包含多个根节点的template结构,因为h1标签和h2标签外层没有包裹性质的根元素 -->
<h1>这是标题</h1>
<h2>这是副标题</h2>
</template>
8、组件中可以使用的指令
组件内的属性也可以被提取到Vue实例中,因此在组件内可以通过 {{属性名}} 直接使用
在组件的 template 节点中使用指令,支持常用的 vue 指令语法,来辅助开发者渲染当前的 dom 结构,比如:
<template>
<!-- 使用 {{}} 插值表达式 -->
<p>生成随机数:{{ (Math.random() * 10).toFixed(2) }}</p>
<!-- 使用 v-bind 属性绑定-->
<p :title="new Date().toLocaleTimeString()">生成日期</p>
<!-- 属性 v-on 事件绑定-->
<button @click="showInfo">显示</button>
</template>
9、在浏览器中调试vue
在 Chorm 浏览器中安装 vue 插件,通过插件即可查看组件信息

创建组件
创建一个最最简单的组件:
template: `<h1>我是标题</h1>`
}
创建一个包含数据的组件:
var title = {
data(){
return {
title: '内容管理系统'
}
},
template: `<h1>{{title}}</h1>`
}
通过上面案例可以看出:
在Vue中创建组件,就是创建一个配置对象,该配置对象和Vue实例的配置几乎一样。
注意:在组件中,如果要声明data数据,不能直接指向对象(比如使用 data:{} 这种格式),必须要指向一个函数,在函数中对外return一个对象,才能够真正返回数据。
向组件传递数据:
在Vue中,实例或组件的data属性用来配置变量,但data()是组件内部的,不推荐修改,所以不能用data接收数据
向组件传入数据的方式有很多种,最常用的是组件属性props,父组件通过props向子组件传递要展示的数据,供子组件内部进行使用,类似于函数传参
首先在组件里申明需要接收哪些属性
props: ['title','page','pagesize'],
template: `<h1>{{title}}</h1>`
}
使用组件时,向其传递属性,有如下几种方式:
1、直接传字符串,比如title="雇员管理系统"
2、使用v-bind绑定变量,比如 v-bind:page="page" 或 :page="page"
3、使用v-bind固定参数类型,比如 :pagesize="10",此时传入数字10,类型为int
4、使用v-bind传入固定字符串+变量,比如 :author="'post by' + info.author",此时传入一个字符串“post by”,还有一个变量 info.author
new Vue({
components: {
MyCom
},
data: {
page: 1
},
template: `
<div>
<!-- 组件中使用参数(直接写变量名,无需被括号包裹)-->
<MyCom title="雇员管理系统" :page="page" :pagesize="10" />
</div>
`
}).$mount("#app");
需要注意的是,props有两种格式,一种是数组,其中只写参数名即可,如上所示,另一种是对象格式,如:
var MyCom = {
props: {
title: '',
page: '',
pagesize: {},
}
}
既然有对象格式,说明它可以做一些配置,比如数据合法性的校验:
var MyCom = {
props: {
//约束类型,指向类型(并非赋值)
title: String, //字符串
size: Number, //数字
//约束多个类型,指向数组(并非赋值)
page: [String, Number, Object],
//自定义校验规则
pagesize: {
type: Boolean, //约束类型
required: true, //必传属性,不传值会在终端中提示
default: 10 //默认值
},
//在封装组件时,可以为prop属性指定自定义的验证函数,从而对prop属性的值进行更加精确的控制
//通过“配置对象”的形式,定义name属性的“验证规则”
name: {
//通过validator函数,对propA属性的值进行校验,“属性的值”可以通过形参value进行接收
validator: function(n){
//name属性的值,必须匹配下列字符串中的一个
//validator函数返回true表示验证通过,false表示验证失败
return n==='fine' || n==='ok';
//return ['Tom', 'Jack', 'Lucy'].indexOf(n) !== -1; //是否存在某个值
//return false; //直接返回false
}
}
}
}
prop属性支持的基础校验类型:
export default{
props: {
propA: String //字符串类型
propB: Number //数字类型
propC: Boolean //布尔值类型
propD: Array //数组类型
propE: Object //对象类型
propF: Date //日期类型
propG: Function //函数类型
propH: Symbol //符号类型
}
}
定义类型校验后,若传入的类型不匹配,会在控制台做出提示,并不过抛出错误,编译也能正常进行,会把传入的值实际赋值给对应的属性,比如布尔值true,会被编辑成字符串“true”。
注意:在组件中,props中的属性为只读,不可在组件中更改props中属性的值,这叫做单项数据流(即:组件中定义的属性,组件自己不可以修改)
如果父组件给子组件传递了未声明的props属性,则这些属性会被忽略,无法被子组件使用;如果父组件没有传递子组件中声明的props属性,则这些属性也会被忽略,不会报错

prop的大小写命名问题
组件中如果使用了“came-Case(驼峰命名法)”声明了 props 属性的名称,则有两种方式为其绑定属性的值:
# 子组件
<template>
<h2>{{dateTime}}</h2>
</template>
<script>
export default {
name: 'Article',
props: ['dateTime']
}
</script>
# 父组件
<template>
<Article dateTime="2020-12-20" />
<Article date-time="2020-12-20" />
</template>