赞
踩
目录
更多关于Vue前端相关技术点,敬请关注公众号:CTO Plus后续的发文,有问题欢迎后台留言交流。
注意:由于排版太费时间,所以还是多多注重技术干货的内容吧。
接下来的一段时间我将除了总结下关于【Python进阶系列】的知识点分享文章外,还将为各位前端读者(全栈开发者)分享下关于前端开发框架Vue3的内容,当然还会包括:H5、CSS3、JavaScript、JQuery、前端开发规范等前端内容。
然后对Python开发感兴趣的读者也可以关注公众号CTO Plus,关注【Python进阶系列】的内容,同时涉及到Web开发、爬虫开发、操作系统开发、网络安全开发应用领域这块,可以分别参考我的公众号CTO Plus【Flask进阶系列】、【Django进阶系列】、【DRF进阶系列】、【互联网分布式爬虫系列】和【网络安全系列】的内容,敬请关注,欢迎交流。
以下是【Vue3进阶系列】的部分内容
Vue3是一款流行的JavaScript框架,用于构建用户界面。Vue 3是Vue框架的最新版本,引入了许多新功能和改进,其中一个核心概念是组件化,Vue 3 中的组件开发得到了很大的改进,它允许开发者将界面拆分为独立、可复用的组件。
那么,本文我将为大家详细介绍组件的概念、定义和作用,以及通过几个实战案例介绍如何使用Vue3开发组件,包括了组件的创建、注册全局组件、注册局部组件、组件名的定义规范等内容,帮助你构建高质量、可复用的UI组件。
组件(Component)是 Vue3中的核心概念最强大的功能之一,是Vue中构建用户界面的核心部分。它将用户界面拆分为独立、可复用的模块,它可以被看作是可复用的代码块。
组件(Component)可以包含(封装)HTML、CSS 和JavaScript,用于封装特定的功能和样式,并提供了一种简洁、可组合的方式来构建应用程序。
组件可以扩展 HTML 元素,封装可重用的代码,通过组件化的方式,我们可以提高代码的可维护性和复用性。
在Vue中,一个组件实际上是一个Vue实例,拥有自己的状态(数据)和方法(行为)。它可以接受props(属性)和emit事件,与其他组件进行通信。关于props和emit的内容将在公众号CTO Plus后面的文章《Vue3进阶:Props实现父子组件之间通信的桥梁详解》和《Vue3进阶:Vue3 组件开发指南之使用 Props 传递和管理组件之间的数据》中的详细介绍。
组件可以包含子组件,并形成组件树的层次结构。
通过前面几篇文章的介绍和代码示例可以看出:一个应用需要被挂载到一个 DOM 元素中。每个 Vue 应用都是通过用 createApp 函数创建的,传递给 createApp 的选项用于配置根组件。当我们挂载应用时,该组件被用作渲染的起点。
接下来,我再总结下DOM的几种挂载方式。
以下实例我们将 Vue 应用挂载到 <div id="app"></div>,则mount应该传入 #customApp:
const RootComponent = { /* 选项 */ }
const app = Vue.createApp(RootComponent)
const vm = app.mount('#customApp')
<body>
<div id="steverocket" class="demo" style="background-color: bisque">
整个元素:{{ infos }}
如果想循环遍历整个元素内容,可以参考Vue的v-for指令
<br/>
第一个元素:{{ infos[0] }}
<br/>
属性个数(长度):{{ infos.length }}
</div>
<div id="steverocket2" style="background-color: #42b983; height: 100px"></div>
<div id="steverocket3" style="background-color: cadetblue; height: 100px"></div>
</body>
<script>
// data 选项
const HelloVueApp = {
data() {
return {
age: 28,
infos: [{"name": "Steverocket", "age": 22}, {"name": "Cramer", "age": 20}]
}
}
}
Vue.createApp(HelloVueApp).mount("#steverocket");
const app2 = Vue.createApp({
data() {
//data 选项是一个函数。Vue 在创建新组件实例的过程中调用此函数。它应该返回一个对象,然后 Vue 会通过响应性系统将其包裹起来,并以 $data 的形式存储在组件实例中。
return {
name: "SteveRocket",
age: 28,
datetime: "2023-08-04 14:35:40"
}
}
}).mount("#steverocket2");
// 我们可以在组件中添加方法,使用 methods 选项,该选项包含了所需方法的对象。
const app3 = Vue.createApp({
data(){
return {
count:0
};
},
methods: {
function01() {
// this 指向该组件实例
this.count++;
}
}
}).mount("#steverocket3");
</script>
<body>
</body>
<script>
const VueApp = {
data() {
return {
}
}
}
Vue.createApp(VueApp).mount('body')
</script>
<div id="steverocket" class="demo-v-bind">
<img v-bind:src="imageSrc"><br/>
简化成如下:<br/>
<img :src="imageSrc">
</div>
<script>
const MyData = {
data() {
return {
imageSrc: './../../../static/wechat.png'
}
}
}
Vue.createApp(MyData).mount('.demo-v-bind')
</script>
参考阅读:《Vue3进阶:常用的指令缩写详解,以及代码使用示例》和《Vue3进阶:简化前端开发的利器,以及常用指令汇总详解》
有了上面的知识点做铺垫,接下来介绍下组件的创建,在Vue 3中,我们可以使用Vue的`createApp`函数来创建一个应用实例,并在其中注册组件。例如,我们可以创建一个名为`MyComponent`的组件:
<div id="app">
<my-component></my-component>
<my-component></my-component>
<my-component></my-component>
</div>
<script>
const MyConponent = {
template: '<div>Hello, 欢迎关注微信公众号:CTO Plus</div>'
}
const app = Vue.createApp({})
app.component('my-component', MyConponent)
app.mount('#app')
</script>
在上面的代码中,我们可以看到首先定义了一个包含`template`属性的对象`MyComponent`,它指定了该组件的模板。然后,我们使用`app.component`方法注册了`MyComponent`组件,将其命名为`my-component`,也即是使用了`my-component`作为自定义标签,在组件被渲染时,会替换为`MyComponent`组件的模板(即`<div> Hello, 欢迎关注微信公众号:CTO Plus </div>`)。最后,我们使用`app.mount`方法将应用实例挂载到一个具有`id`为`app`的DOM元素上。
输出结果
注册一个全局组件语法格式如下:
const app = Vue.createApp({...})
app.component('my-component-name', {
/* ... */
})
my-component-name 为组件名,/* ... */ 部分为配置选项。注册后,我们可以使用以下方式来调用组件:
<my-component-name></my-component-name>
或使用下面的链式写法:
Vue.createApp({...}).component('my-component-name', {
// ... 选项 ...
})
这里使用app.component来创建的组件这些组件是全局注册的。也就是说它们在注册之后可以用在任何新创建的组件实例的模板中。比如:
const app = Vue.createApp({})
app.component('component-a', {
/* ... */
})
app.component('component-b', {
/* ... */
})
app.component('component-c', {
/* ... */
})
app.mount('#app')
<div id="app">
<component-a></component-a>
<component-b></component-b>
<component-c></component-c>
</div>
在所有子组件中也是如此,也就是说这三个组件在各自内部也都可以相互使用。
下面是一个简单的 Vue 组件实例,这里注册了一个简单的全局组件steverocket,并使用它:
<steverocket></steverocket>
<steverocket></steverocket>
<steverocket></steverocket>
<script>
// 创建一个Vue应用
const app = Vue.createApp({})
// 定义一个steverocket的全局组件
app.component('steverocket', {
template: "<p><a href=\"https://mp.weixin.qq.com/s/0yqGBPbOI6QxHqK17WxU8Q\">https://mp.weixin.qq.com/s/0yqGBPbOI6QxHqK17WxU8Q</a></p>"
})
app.mount('body')
</script>
输出结果
全局注册往往是不够理想的。比如,如果你使用一个像 webpack 这样的构建系统,全局注册所有的组件意味着即便你已经不再使用一个组件了,它仍然会被包含在你最终的构建结果中。这造成了用户下载的 JavaScript 的大小无谓的增加。全局注册往往是不够理想的,很多时候我们需要私有组件。
关于webpack工具的使用和优化将在后面的文章中做详细介绍,敬请关注公众号CTO Plus。
我们也可以在实例选项中,通过component选项来注册局部组件,这样组件只能在这个实例中使用,如下我们可以定义一个普通的 JavaScript 对象来定义组件,然后通过在组件内部使用components选项来定义私有的、局部组件:
const ComponentA = {
/* ... */
}
const ComponentB = {
/* ... */
}
const ComponentC = {
/* ... */
}
然后在 components 选项中定义我们想要使用的组件:
const app = Vue.createApp({
components: {
'component-a': ComponentA,
'component-b': ComponentB
}
})
对于 components 对象中的每个属性(键值对)来说,其属性(键)名就是局部组件的名字,这里表示的是自定义元素的名字(component-a、component-b),其属性值就是这个组件的定义选项对象(ComponentA、ComponentB)。
注意局部注册的组件在其子组件中不可用。例如,如果你希望 ComponentA在 ComponentB 中可用,则你需要这样写:
const ComponentA = {
/* ... */
}
const ComponentB = {
components: {
'component-a': ComponentA
}
// ...
}
或者如果你通过 Babel 和webpack 使用 ES2015 模块,那么代码看起来如下:
import ComponentA from './ComponentA.vue'
export default {
components: {
ComponentA
}
// ...
}
注意在 ES2015+ 中,在对象中放一个类似 ComponentA 的变量名其实是 ComponentA: ComponentA 的缩写,即这个变量名同时是:
用在模板中的自定义元素的名称
包含了这个组件选项的变量名
注册一个简单的局部组件steverocket,并使用它代码示例如下:
<steverocket></steverocket>
<steverocket></steverocket>
<steverocket></steverocket>
<script>
const SteveRocket = {
template: '<p><a href="https://mp.weixin.qq.com/s/0yqGBPbOI6QxHqK17WxU8Q">https://mp.weixin.qq.com/s/0yqGBPbOI6QxHqK17WxU8Q</a></p>'
}
const VueApp = Vue.createApp({
components: {
'steverocket': SteveRocket
}
})
VueApp.mount('body')
</script>
输出结果
从上面的输出结果可以看出全局组件和局部组件实现了同样的输出结果。
初学者一定要掌握ES2015+之后的缩写、简写语法。我将在后面的文章中做详细的总结和介绍。
我们可以将组件进行任意次数的复用:
<button-cunter></button-cunter>
<button-cunter></button-cunter>
<button-cunter></button-cunter>
<button-cunter></button-cunter>
<script>
// 创建一个vue应用
const VueApp = Vue.createApp({})
// 定义一个名为button-counter的新全局组件
VueApp.component('button-cunter', {
data() {
return {
count: 0
}
},
template: `
<button @click="count++">点击了{{ count }}次</button>`
})
VueApp.mount('body')
</script>
注意:template 中 ` 是反引号,不是单引号 '。
以上的实例中,我们的组件都只是通过 component 全局注册的。全局注册的组件可以在随后创建的 app 实例模板中使用,也包括根实例组件树中的所有子组件的模板中。
这里,接下来我介绍下组件的名称,从上面的代码示例中我们已经看到在注册一个组件的时候,我们始终需要给它定义一个名字。
比如在全局注册的时候我们已经看到了:
const app = Vue.createApp({...})
app.component('my-component-name', {
/* ... */
})
该组件名就是 app.component 的第一个参数,在上面的例子中,组件的名称是“my-component-name”。
组件的命名与在哪使用它有关。因为HTML是不区分大小写的,所以当直接在 DOM 中 (而不是在字符串模板或单文件组件中) 使用一个组件的时候,官方强烈推荐遵循W3C 规范来给自定义标签命名:
全部小写
包含连字符- (及:即有多个单词与连字符符号连接)
新手请务必牢记命名规范和注意事项,这样可以帮助我们避免与当前以及未来的 HTML 元素发生冲突。
关于前端的系列开发规范我后期将会做个总结分享在文末的QQ群中,以及单文件组件的使用请关注公众号CTO Plus后面的文章《Vue3进阶:单文件组件的介绍、使用详解和代码实战案例》和《Vue3进阶:应用规模化:单文件组件的使用实践详解(附代码示例)》的详细介绍。
在字符串模板或单个文件组件中定义组件时,组件名的风格有两种:
app.component('my-component-name', {
/* ... */
})
当使用kebab-case (短横线分隔命名) 定义一个组件时,你也必须在引用这个自定义元素时使用 kebab-case,例如<my-component-name>。
app.component('MyComponentName', {
/* ... */
})
当使用 PascalCase (首字母大写命名) 定义一个组件时,你在引用这个自定义元素时两种命名法都可以使用。也就是说 <my-component-name>和 <MyComponentName> 都是可接受的。
再次强调,尽管如此,直接在DOM (即非字符串的模板) 中使用时只有kebab-case 是有效的。
通过本文,我们了解了Vue 3中组件的基本概念,以及如何使用Vue3创建组件、定义组件逻辑、编写模板,并在其他Vue3应用程序中使用组件。Vue3的组件化能力使我们能够构建可复用和可组合的UI组件,提高开发效率和代码质量。
Vue 3中的组件是构建Vue应用程序的核心部分。掌握Vue 3中的组件使用方法,将帮助你构建现代、可维护和可扩展的应用程序。希望本文对你在Vue3组件开发方面有所帮助!
下一篇文章我将为大家介绍下组件之间的通信、组件生命周期和其他功能:《Vue3进阶:Props实现父子组件之间通信的桥梁详解》和《Vue3进阶:Vue3 组件开发指南之使用 Props 传递和管理组件之间的数据》
大前端专栏
https://blog.csdn.net/zhouruifu2015/category_5734911.html
更多精彩,关注我公号,一起学习、成长
CTO Plus
一个有深度和广度的技术圈,技术总结、分享与交流,我们一起学习。 涉及网络安全、C/C++、Python、Go、大前端、云原生、SRE、SDL、DevSecOps、数据库、中间件、FPGA、架构设计等大厂技术。 每天早上8点10分准时发文。
306篇原创内容
公众号
推荐阅读:
最后,不少前端粉丝后台留言问加技术交流群,之前也一直没弄,所以为满足粉丝需求,现建立了一个关于前端开发相关的技术交流群,加群验证方式必须为本公众号的粉丝,群号如下:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。