如果项目比较复杂,使用组件可以极大简化代码量,并且对后期的需求变更和维护也更加友好。组件化提供了一种抽象,让我们可以开发一个个独立的可复用的小组件来构建我们的应用。任何的应用都会被抽象成一颗组件树。

以下引用尚硅谷张天禹老师的两张图,这很清晰明了得指出了传统编程方式的冗杂以及组件化的简化与友好


组件分为了非单文件组件与单文件组件
- 非单文件组件:一个文件中包含有 n 个组件
- 单文件组件:一个文件中只有 1 个组件
在项目开发中,使用最多的肯定是单文件组件,但非单文件组件是单文件组件的基础,拿下非单文件组件,单文件组件岂不是分分钟的事。
Vue中使用组件的三大步骤:
- 定义组件(创建组件)
- 注册组件
- 使用组件(写组件标签)
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>非单文件组件基本使用title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<h1>{{msg}}h1>
<hr>
<school>school>
<hr>
<student>student>
div>
body>
<script type="text/javascript">
// 创建school组件
const school = Vue.extend({
//组件定义时,一定不要写 el 配置项,因为最终所有的组件都要被一个 vm 管理,由 vm 决定服务于哪个容器。
template:`
学校名称:{{schoolName}}
学校地址:{{address}}
`,
data(){
return {
schoolName:'家里蹲',
address:'重庆'
}
}
})
// 创建student组件
const student = Vue.extend({
template:`
学生姓名:{{studentName}}
学生年龄:{{age}}
`,
data(){
return {
studentName:'划水艺术家',
age:20
}
}
})
//创建vm
new Vue({
el:'#root',
data:{
msg:'你好,划水艺术家!'
},
// 注册组件(局部注册)
components:{
school,
student
}
})
script>
html>
运行效果:

components选项Vue.component('组件名',组件)<script type="text/javascript">
// 创建school组件
const school = Vue.extend({
// ...
})
// 创建student组件
const student = Vue.extend({
// ...
})
//创建vm
new Vue({
el:'#root',
// ...
})
// 组件注册(全局注册)
Vue.component("school", school);
Vue.component("student ", student );
</script>
DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>组件的嵌套title>
<script type="text/javascript" src="../js/vue.js">script>
head>
<body>
<div id="root">
<app>app>
div>
body>
<script type="text/javascript">
//定义student组件
const student = Vue.extend({
template:`
学生名称:{{name}}
学生年龄:{{age}}
`,
data(){
return {
name:'划水艺术家',
age:20
}
}
})
//定义school组件, school 组件里面有 student
const school = Vue.extend({
template:`
学校名称:{{name}}
学校地址:{{address}}
`,
components:{
student
},
data(){
return {
name:'家里蹲',
address:'重庆'
}
}
})
//定义hello组件
const hello = Vue.extend({
template:`
{{msg}}
`,
data(){
return {
msg:"你好,划水艺术家"
}
}
})
//定义app组件, app 组件里面有 school、hello 组件
const app = Vue.extend({
template:`
`,
components:{
school,
hello
}
})
//创建vm
new Vue({
el:'#root',
components:{
app
}
})
script>
html>

关于组件名:
一个单词组成:
① 首字母小写:school
② 首字母大写:School
多个单词组成:
① kebab-case命名:my-school
② CamelCase命名:MySchool (需要Vue脚手架支持)
备注:
name配置项指定组件在开发者工具中呈现的名字关于组件标签:
①
②
会导致后续组件不能渲染一个简写方式:const school = Vue.extend(options)可简写为:const school = options
我们依然使用上述非单文件组件中的例子,只是把每一个组件列出来单独成为一个组件。

<template>
<div>
<h2>学生姓名:{{name}}h2>
<h2>学生年龄:{{age}}h2>
div>
template>
<script>
export default {
name:'Student',
data() {
return {
name:'划水艺术家',
age:20
}
},
}
script>
<template>
<div id='Demo'>
<h2>学校名称:{{name}}h2>
<h2>学校地址:{{address}}h2>
<button @click="showName">点我提示学校名button>
div>
template>
<script>
export default {
name:'School',
data() {
return {
name:'家里蹲',
address:'重庆'
}
},
methods: {
showName(){
alert(this.name)
}
},
}
script>
<style>
#Demo{
background: orange;
}
style>
<template>
<div>
<School>School>
<Student>Student>
div>
template>
<script>
import School from './School.vue'
import Student from './Student.vue'
export default {
name:'App',
components:{
School,
Student
}
}
script>
import App from './App.vue'
new Vue({
template:` `,
el:'#root',
components:{
App
}
})
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>单文件组件练习title>
head>
<body>
<div id="root">
div>
<script src="../js/vue.js" type="text/javascript">script>
<script src="./main.js" type="text/javascript">script>
body>
html>

当我们运行 index.html,发现什么都没有,并且控制台还报错,这是因为只有脚手架才支持组件开发。
① 全局安装 @vue/cli
npm install -g @vue/cli
② 切换到你要创建项目的目录,然后使用命令创建项目
vue create xxxx

③ 选择使用vue的版本

④ 启动项目:npm run serve


⑤ 暂停项目:Ctrl+C

.文件目录
├── node_modules
├── public
│ ├── favicon.ico: 页签图标
│ └── index.html: 主页面
├── src
│ ├── assets: 存放静态资源
│ │ └── logo.png
│ │── component: 存放组件
│ │ └── HelloWorld.vue
│ │── App.vue: 汇总所有组件
│ └── main.js: 入口文件
├── .gitignore: git版本管制忽略的配置
├── babel.config.js: babel的配置文件
├── package.json: 应用包配置文件
├── README.md: 应用描述文件
└── package-lock.json: 包版本控制文件
将上述的单文件案例迁移至脚手架中
① 将 School.vue 与 Student.vue 加入 components

② App.vue 引入组件并使用

③ index.html
DOCTYPE html>
<html lang="">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %>title>
head>
<body>
<div id="app">div>
body>
html>
运行效果:

vue inspect > output.js 可以查看Vue脚手架的默认配置
vue.config.js 是一个可选的配置文件,如果项目的(和 package.json 同级的)根目录中存在这个文件,那么它会被 @vue/cli-service 自动加载module.exports = {
pages: {
index: {
// 入口
entry: 'src/index/main.js'
}
},
// 关闭语法检查
lineOnSave:false
}
ref属性:
或 this.$refs.xxx测试案例:
<template>
<div>
<h1 ref="title">{{msg}}h1>
<School ref="sch"/>
<button @click="show" ref="btn">点我输出refbutton>
div>
template>
<script>
import School from './components/School.vue'
export default {
name:'App',
components: { School },
data() {
return {
msg:'欢迎学习Vue!'
}
},
methods:{
show(){
console.log(this.$refs.title)
console.log(this.$refs.sch)
console.log(this.$refs.btn)
}
}
}
script>

mixin(混入):
功能:可以把多个组件共用的配置提取成一个混入对象
使用方式:
① 定义混入
export const mixin = {
data(){
....
},
methods:{
....
}
....
}
② 引入混入
局部混入:
mixins:['xxx']
全局混入:Vue.mixin(xxx)
src/mixin.js
export const mixin = {
methods: {
showName() {
alert(this.name)
}
},
mounted() {
console.log("hello~")
}
}
src/components/School.vue
<template>
<div>
<h2 @click="showName">学校姓名:{{name}}h2>
<h2>学校地址:{{address}}h2>
div>
template>
<script>
//引入混入
import {mixin} from '../mixin'
export default {
name:'School',
data() {
return {
name:'家里蹲',
address:'重庆'
}
},
mixins:[mixin]
}
script>
src/components/Student.vue
<template>
<div>
<h2 @click="showName">学生姓名:{{name}}h2>
<h2>学生性别:{{sex}}h2>
div>
template>
<script>
//引入混入
import {mixin} from '../mixin'
export default {
name:'Student',
data() {
return {
name:'划水艺术家',
sex:'男'
}
},
mixins:[mixin]
}
script>
src/main.js
import Vue from 'vue'
import App from './App.vue'
import {mixin} from './mixin'
Vue.config.productionTip = false
Vue.mixin(mixin)
new Vue({
el:"#app",
render: h => h(App)
})
备注:
- 组件和混入对象含有
同名选项时,这些选项将以恰当的方式进行“合并”,在发生冲突时以组件优先。- 同名生命周期钩子将合并为一个数组,因此都将被调用。另外,混入对象的钩子将在组件自身钩子之前调用。
插件:
plugin.install = function (Vue, options) {
// 1. 添加全局过滤器
Vue.filter(....)
// 2. 添加全局指令
Vue.directive(....)
// 3. 配置全局混入
Vue.mixin(....)
// 4. 添加实例方法
Vue.prototype.$myMethod = function () {...}
Vue.prototype.$myProperty = xxxx
}
Vue.use(plugin)测试案例:
src/myPlugin.js
export default {
install(Vue, x, y, z){
console.log(x,y,z)
//全局过滤器
Vue.filter('mySlice',function(value){
return value.slice(0,4)
})
//定义混入
Vue.mixin({
data() {
return {
x:100,
y:200
}
},
})
//给Vue原型上添加一个方法(vm和vc就都能用了)
Vue.prototype.hello = ()=>{alert('你好啊')}
}
}
src/main.js
import Vue from 'vue'
import App from './App.vue'
import myPlugin from './myPlugin '
Vue.config.productionTip = false
Vue.use(myPlugin ,1,2,3)
new Vue({
el:"#app",
render: h => h(App)
})
scoped样式:
scoped样式一般不会在App.vue中使用
测试案例:
src/components/School.vue
<template>
<div class='Demo'>
<h2>学校名称:{{name}}h2>
<h2>学校地址:{{address}}h2>
div>
template>
<script>
export default {
name:'School',
data() {
return {
name:'家里蹲',
address:'重庆'
}
},
}
script>
<style>
.Demo{
background: orange;
}
style>
src/components/Student.vue
<template>
<div class="Demo">
<h2>学生姓名:{{name}}h2>
<h2>学生年龄:{{age}}h2>
div>
template>
<script>
import {mixin} from "@/mixin";
export default {
name:'Student',
data() {
return {
name:'划水艺术家',
age:20
}
},
}
script>
<style scoped>
.Demo{
background: red;
}
style>
src/App.vue
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<School>School>
<hr>
<Student>Student>
div>
template>
<script>
import Student from './components/Student.vue'
import School from './components/School.vue'
export default {
name: 'App',
components: {
School,
Student
},
}
script>
