Vue零基础教程|从前端框架到GIS开发系列课程(五)组件式开发
Party1
简介
1) 什么是组件
组件可以理解成项目的零件
项目 就是由多个 组件 构成的
举例
-
一个房子是一个Vue应用, 那么客厅/卧室/厨房/卫生间就是组件
-
一个电脑是一个Vue应用, 那么硬盘/内存/主板/显示器/键盘就是组件
组件化思想
2) 为什么需要组件
将逻辑相近的功能模块封装到一起. 方便复用
示例
<!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>Document</title>
<script src="../node_modules/vue/dist/vue.global.js"></script>
</head>
<body>
<div id="app">
<!-- 文章一 -->
<div class="blog-item">
<h3>{{title}}</h3>
<div>{{content}}</div>
</div>
<!-- 文章二 -->
<div class="blog-item">
<h3>{{title}}</h3>
<div>{{content}}</div>
</div>
<!-- 文章三 -->
<div class="blog-item">
<h3>{{title}}</h3>
<div>{{content}}</div>
</div>
</div>
<script>
const { createApp } = Vue
const vm = createApp({
data() {
return {
title: '文章标题',
content: '文章内容',
}
},
}).mount('#app')
</script>
</body>
</html>
如果要使用组件需要先注册. 从注册的方式不同
可以将组件分为
-
全局组件
-
局部组件
3) 全局组件
顾名思义, 全局都可以使用的组件, 组件在当前 Vue 应用中全局可用
语法
// 可以使用 Vue 应用实例的 app.component() 方法
import { createApp } from 'vue'
const app = createApp({})
app.component(
// 注册的名字
'MyComponent',
// 组件的配置对象
{
/* ... */
}
)
组件对象中的配置项和createApp
中的配置项一致
什么是当前Vue应用
每次调用createApp
会创建一个新的Vue应用. 不同的Vue应用实例有自己的空间. 不能跨应用引用组件
const app = createApp({}) // 创建一个应用实例
const app1 = createApp({}) // 创建一个新的应用实例
console.log(app === app1) //false
// 在app中注册的组件, 不能在app1中使用
🤔为什么data是一个函数?
每个实例可以维护一份被返回对象的独立的拷贝:
data: function () {
return {
count: 0
}
}
如果 Vue 没有这条规则,点击一个按钮就会影响到其它所有实例!
示例
<!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>Document</title>
<script src="../node_modules/vue/dist/vue.global.js"></script>
<body>
<div id="app">
<counter></counter>
<counter></counter>
<counter></counter>
</div>
<script>
const {createApp} = Vue
const app = createApp({})
// 定义组件
app.component('counter', {
template: '<button @click="count++">点击了{{count}}次</button>',
data() {
return {
count: 0
}
}
})
app.mount('#app')
</script>
</body>
</html>
引用
在模板中, 通过组件名称引用组件
<blog-item></blog-item>
注意事项
-
命名原则
-
闭合方式
-
引用位置
<!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>Document</title>
<script src="../node_modules/vue/dist/vue.global.js"></script>
<body>
<div id="app">
<table>
<my-button></my-button>
</table>
</div>
<script>
const {createApp} = Vue
const app = createApp({})
// 定义组件
// 一. 组件名称
// 1. 组件名不能是HTML原生的标签名
// 2. 组件名尽量使用多个单词, 多个单词之间使用-连接(kebab-case)
// 3. 组件名尽量使用PascalCase(驼峰法)
// 二. 组件引用
// 1. 在不使用构建工具的情况下, 由于HTML不区分大小写, 所以在模板中不能使用PascalCase来引用组件
// 2. 组件使用双标签形式
// 3. 组件不要在ul.ol,table,select内部直接使用
app.component('MyButton', {
template: '<button @click="count++">点击了{{count}}次</button>',
data() {
return {
count: 0
}
}
})
app.mount('#app')
</script>
</body>
</html>
4) 局部组件
语法
使用components
选项
<!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>Document</title>
<script src="../node_modules/vue/dist/vue.global.js"></script>
</head>
<body>
<!-- 根组件解析的模板 -->
<div id="app">
<!-- 局部组件只能在当前组件的模板中引用 -->
<first-com></first-com>
<second-com></second-com>
</div>
<script>
const { createApp } = Vue
// 参数{}: 根组件配置对象
const app = createApp({
// 定义根组件下的子组件
components: {
// 组件名: 组件配置对象
FirstCom: {
template: `<div>FirstCom</div>`,
},
SecondCom: {
template: `<div>SecondCom</div>`,
},
},
})
app.mount('#app')
</script>
</body>
</html>
如何理解局部
局部注册的组件在后代组件中不可用, 只能在当前组件的模板中引用
示例
<!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>Document</title>
<script src="../node_modules/vue/dist/vue.global.js"></script>
</head>
<body>
<!-- 根组件解析的模板 -->
<div id="app">
<!-- 局部组件只能在当前组件的模板中引用 -->
<first-com></first-com>
<second-com></second-com>
</div>
<script>
const { createApp } = Vue
// 参数{}: 根组件配置对象
// 在当前组件的配置项中定义的组件只能在当前组件对应的模板中使用
const app = createApp({
// 定义根组件下的子组件
components: {
// 组件名: 组件配置对象
FirstCom: {
template: `<div>
不能在FirstCom组件的模板中引用父组件配置对象中定义的组件
<second-com></second-com>
</div>`,
},
SecondCom: {
template: `<div>SecondCom</div>`,
},
},
})
// const app = createApp({})
// app
// .component('FirstCom', {
// template: `<div>
// FirstCom
// -- <second-com></second-com>
// </div>`,
// })
// .component('SecondCom', {
// template: '<div>SecondCom</div>',
// })
app.mount('#app')
</script>
</body>
</html>
Party2
父子组件间通信(重点掌握)
1) 为什么需要通信
场景
父组件Root
, 子组件为BlogItem
每一篇blog的标题都不同. 子组件只能决定结构和样式. 具体的数据要变化, 需要父组件通知
<!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>Document</title>
<script src="../node_modules/vue/dist/vue.global.js"></script>
</head>
<body>
<div id="app">
<!-- 1. 在父组件的模板中, 通过自定义属性传值 -->
<blog-item title="Vue深入浅出"></blog-item>
<blog-item :title="msg"></blog-item>
<blog-item title="Vue的最佳实践"></blog-item>
</div>
<script>
const { createApp } = Vue
// 父组件: 确定数据
const vm = createApp({
data() {
return {
msg: 'Vue的设计与实现',
}
},
components: {
// 子组件定义: 确定结构和样式
BlogItem: {
// 在子组件的配置项中, 通过props接收
props: ['title'],
template: `
<div>
<h3>{{title}}</h3>
<p>内容</p>
</div>
`,
},
},
}).mount('#app')
</script>
</body>
</html>
2) 父传子
通过子组件的自定义属性
-
在父组件模板中, 设置自定义属性
-
在子组件选项中, 通过
props
接收
示例
父组件:
<!-- 在父组件的模板中, 设置自定义属性 -->
<blog-item title="Vue深入浅出"></blog-item>
<!-- 在父组件的模板中, 绑定自定义属性 -->
<blog-item :title="msg"></blog-item>
子组件对象:
{
// 在子组件的配置项中, 通过props接收
props: ['title'],
template: `
<div>
<h3>{{title}}</h3>
<p>内容</p>
</div>
`,
},
3) 子传父
借助子组件的中自定义事件
-
在子组件中, 触发自定义事件
-
在父组件中, 监听自定义事件
示例
<!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>Document</title>
<script src="../node_modules/vue/dist/vue.global.js"></script>
</head>
<body>
<div id="app">
<!-- 1. 在父组件的模板中, 通过自定义属性传值 -->
<blog-item title="Vue深入浅出"></blog-item>
<blog-item :title="msg"></blog-item>
<!-- 2. 在父组件的模板, 监听自定义事件 -->
<blog-item v-if="show" title="Vue的最佳实践" @close="handleClose"></blog-item>
</div>
<script>
const { createApp } = Vue
// 父组件: 确定数据
const vm = createApp({
data() {
return {
msg: 'Vue的设计与实现',
show: true,
}
},
methods: {
handleClose(i) {
this.show = false
console.log(i)
},
},
components: {
// 子组件定义: 确定结构和样式
BlogItem: {
// 在子组件的配置项中, 通过props接收
props: ['title'],
template: `
<div>
<h3>{{title}}</h3>
<p>内容</p>
// 1. 在子组件中触发一个自定义事件
<button @click="$emit('close', 1)">关闭</button>
</div>
`,
},
},
}).mount('#app')
</script>
</body>
</html>
动态组件
渲染的组件是动态生成, 根据不同的状态渲染不同的组件
踢踢备注:《Vue零基础教程》